Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : #ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
32 : #define GOOGLE_PROTOBUF_MAP_FIELD_H__
33 :
34 : #include <google/protobuf/stubs/atomicops.h>
35 : #include <google/protobuf/stubs/mutex.h>
36 : #include <google/protobuf/stubs/common.h>
37 : #include <google/protobuf/generated_message_reflection.h>
38 : #include <google/protobuf/arena.h>
39 : #include <google/protobuf/map_entry.h>
40 : #include <google/protobuf/map_field_lite.h>
41 : #include <google/protobuf/map_type_handler.h>
42 : #include <google/protobuf/message.h>
43 : #include <google/protobuf/repeated_field.h>
44 : #include <google/protobuf/unknown_field_set.h>
45 :
46 :
47 : namespace google {
48 : namespace protobuf {
49 : class DynamicMessage;
50 : class MapKey;
51 : namespace internal {
52 :
53 : class ContendedMapCleanTest;
54 : class GeneratedMessageReflection;
55 : class MapFieldAccessor;
56 :
57 : // This class provides accesss to map field using reflection, which is the same
58 : // as those provided for RepeatedPtrField<Message>. It is used for internal
59 : // reflection implentation only. Users should never use this directly.
60 : class LIBPROTOBUF_EXPORT MapFieldBase {
61 : public:
62 : MapFieldBase()
63 : : arena_(NULL),
64 : repeated_field_(NULL),
65 : entry_descriptor_(NULL),
66 : assign_descriptor_callback_(NULL),
67 0 : state_(STATE_MODIFIED_MAP) {}
68 0 : explicit MapFieldBase(Arena* arena)
69 : : arena_(arena),
70 : repeated_field_(NULL),
71 : entry_descriptor_(NULL),
72 : assign_descriptor_callback_(NULL),
73 0 : state_(STATE_MODIFIED_MAP) {
74 : // Mutex's destructor needs to be called explicitly to release resources
75 : // acquired in its constructor.
76 0 : arena->OwnDestructor(&mutex_);
77 0 : }
78 : virtual ~MapFieldBase();
79 :
80 : // Returns reference to internal repeated field. Data written using
81 : // google::protobuf::Map's api prior to calling this function is guarantted to be
82 : // included in repeated field.
83 : const RepeatedPtrFieldBase& GetRepeatedField() const;
84 :
85 : // Like above. Returns mutable pointer to the internal repeated field.
86 : RepeatedPtrFieldBase* MutableRepeatedField();
87 :
88 : // Pure virtual map APIs for Map Reflection.
89 : virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
90 : virtual bool InsertMapValue(const MapKey& map_key, MapValueRef* val) = 0;
91 : virtual bool DeleteMapValue(const MapKey& map_key) = 0;
92 : virtual bool EqualIterator(const MapIterator& a,
93 : const MapIterator& b) const = 0;
94 : virtual void MapBegin(MapIterator* map_iter) const = 0;
95 : virtual void MapEnd(MapIterator* map_iter) const = 0;
96 : // Sync Map with repeated field and returns the size of map.
97 : virtual int size() const = 0;
98 :
99 : // Returns the number of bytes used by the repeated field, excluding
100 : // sizeof(*this)
101 : int SpaceUsedExcludingSelf() const;
102 :
103 : protected:
104 : // Gets the size of space used by map field.
105 : virtual int SpaceUsedExcludingSelfNoLock() const;
106 :
107 : // Synchronizes the content in Map to RepeatedPtrField if there is any change
108 : // to Map after last synchronization.
109 : void SyncRepeatedFieldWithMap() const;
110 : virtual void SyncRepeatedFieldWithMapNoLock() const;
111 :
112 : // Synchronizes the content in RepeatedPtrField to Map if there is any change
113 : // to RepeatedPtrField after last synchronization.
114 : void SyncMapWithRepeatedField() const;
115 0 : virtual void SyncMapWithRepeatedFieldNoLock() const {}
116 :
117 : // Tells MapFieldBase that there is new change to Map.
118 : void SetMapDirty();
119 :
120 : // Tells MapFieldBase that there is new change to RepeatedPTrField.
121 : void SetRepeatedDirty();
122 :
123 : // Provides derived class the access to repeated field.
124 : void* MutableRepeatedPtrField() const;
125 :
126 : // Creates descriptor for only one time.
127 : void InitMetadataOnce() const;
128 :
129 : enum State {
130 : STATE_MODIFIED_MAP = 0, // map has newly added data that has not been
131 : // synchronized to repeated field
132 : STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that
133 : // has not been synchronized to map
134 : CLEAN = 2, // data in map and repeated field are same
135 : };
136 :
137 : Arena* arena_;
138 : mutable RepeatedPtrField<Message>* repeated_field_;
139 : // MapEntry can only be created from MapField. To create MapEntry, MapField
140 : // needs to know its descriptor, because MapEntry is not generated class which
141 : // cannot initialize its own descriptor by calling generated
142 : // descriptor-assign-function. Thus, we need to register a callback to
143 : // initialize MapEntry's descriptor.
144 : const Descriptor** entry_descriptor_;
145 : void (*assign_descriptor_callback_)();
146 :
147 : mutable Mutex mutex_; // The thread to synchronize map and repeated field
148 : // needs to get lock first;
149 : mutable volatile Atomic32 state_; // 0: STATE_MODIFIED_MAP
150 : // 1: STATE_MODIFIED_REPEATED
151 : // 2: CLEAN
152 :
153 : private:
154 : friend class ContendedMapCleanTest;
155 : friend class GeneratedMessageReflection;
156 : friend class MapFieldAccessor;
157 : friend class ::google::protobuf::DynamicMessage;
158 :
159 : // Virtual helper methods for MapIterator. MapIterator doesn't have the
160 : // type helper for key and value. Call these help methods to deal with
161 : // different types. Real helper methods are implemented in
162 : // TypeDefinedMapFieldBase.
163 : friend class ::google::protobuf::MapIterator;
164 : // Allocate map<...>::iterator for MapIterator.
165 : virtual void InitializeIterator(MapIterator* map_iter) const = 0;
166 :
167 : // DeleteIterator() is called by the destructor of MapIterator only.
168 : // It deletes map<...>::iterator for MapIterator.
169 : virtual void DeleteIterator(MapIterator* map_iter) const = 0;
170 :
171 : // Copy the map<...>::iterator from other_iterator to
172 : // this_iterator.
173 : virtual void CopyIterator(MapIterator* this_iterator,
174 : const MapIterator& other_iterator) const = 0;
175 :
176 : // IncreaseIterator() is called by operator++() of MapIterator only.
177 : // It implements the ++ operator of MapIterator.
178 : virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
179 : };
180 :
181 : // This class provides common Map Reflection implementations for generated
182 : // message and dynamic message.
183 : template<typename Key, typename T>
184 : class TypeDefinedMapFieldBase : public MapFieldBase {
185 : public:
186 0 : TypeDefinedMapFieldBase() {}
187 0 : explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
188 0 : ~TypeDefinedMapFieldBase() {}
189 0 : void MapBegin(MapIterator* map_iter) const;
190 0 : void MapEnd(MapIterator* map_iter) const;
191 0 : bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
192 :
193 : virtual const Map<Key, T>& GetMap() const = 0;
194 : virtual Map<Key, T>* MutableMap() = 0;
195 :
196 : protected:
197 : typename Map<Key, T>::const_iterator& InternalGetIterator(
198 : const MapIterator* map_iter) const;
199 :
200 : private:
201 : void InitializeIterator(MapIterator* map_iter) const;
202 : void DeleteIterator(MapIterator* map_iter) const;
203 0 : void CopyIterator(MapIterator* this_iteratorm,
204 0 : const MapIterator& that_iterator) const;
205 0 : void IncreaseIterator(MapIterator* map_iter) const;
206 :
207 : virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
208 : };
209 :
210 : // This class provides accesss to map field using generated api. It is used for
211 : // internal generated message implentation only. Users should never use this
212 : // directly.
213 : template <typename Key, typename T,
214 : WireFormatLite::FieldType kKeyFieldType,
215 : WireFormatLite::FieldType kValueFieldType,
216 : int default_enum_value = 0>
217 : class MapField : public TypeDefinedMapFieldBase<Key, T>,
218 : public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
219 : default_enum_value> {
220 : // Provide utilities to parse/serialize key/value. Provide utilities to
221 : // manipulate internal stored type.
222 : typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
223 : typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
224 :
225 : // Define message type for internal repeated field.
226 : typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
227 : EntryType;
228 : typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
229 : default_enum_value> EntryLiteType;
230 :
231 : // Define abbreviation for parent MapFieldLite
232 : typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
233 : default_enum_value> MapFieldLiteType;
234 :
235 : // Enum needs to be handled differently from other types because it has
236 : // different exposed type in google::protobuf::Map's api and repeated field's api. For
237 : // details see the comment in the implementation of
238 : // SyncMapWithRepeatedFieldNoLock.
239 : static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
240 : typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
241 :
242 : public:
243 : MapField();
244 : explicit MapField(Arena* arena);
245 : // MapField doesn't own the default_entry, which means default_entry must
246 : // outlive the lifetime of MapField.
247 : MapField(const Message* default_entry);
248 : // For tests only.
249 : MapField(Arena* arena, const Message* default_entry);
250 : ~MapField();
251 :
252 : // Implement MapFieldBase
253 : bool ContainsMapKey(const MapKey& map_key) const;
254 : bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
255 : bool DeleteMapValue(const MapKey& map_key);
256 :
257 : // Accessors
258 : const Map<Key, T>& GetMap() const;
259 : Map<Key, T>* MutableMap();
260 :
261 : // Convenient methods for generated message implementation.
262 : int size() const;
263 : void Clear();
264 : void MergeFrom(const MapFieldLiteType& other);
265 : void Swap(MapFieldLiteType* other);
266 :
267 : // Allocates metadata only if this MapField is part of a generated message.
268 : void SetEntryDescriptor(const Descriptor** descriptor);
269 : void SetAssignDescriptorCallback(void (*callback)());
270 :
271 : private:
272 : typedef void InternalArenaConstructable_;
273 : typedef void DestructorSkippable_;
274 :
275 : // MapField needs MapEntry's default instance to create new MapEntry.
276 : void InitDefaultEntryOnce() const;
277 :
278 : // Manually set default entry instance. For test only.
279 : void SetDefaultEntryOnce(const EntryType* default_entry) const;
280 :
281 : // Convenient methods to get internal google::protobuf::Map
282 : const Map<Key, T>& GetInternalMap() const;
283 : Map<Key, T>* MutableInternalMap();
284 :
285 : // Implements MapFieldBase
286 : void SyncRepeatedFieldWithMapNoLock() const;
287 : void SyncMapWithRepeatedFieldNoLock() const;
288 : int SpaceUsedExcludingSelfNoLock() const;
289 :
290 : void SetMapIteratorValue(MapIterator* map_iter) const;
291 :
292 : mutable const EntryType* default_entry_;
293 :
294 : friend class ::google::protobuf::Arena;
295 : };
296 :
297 : class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
298 : public:
299 : explicit DynamicMapField(const Message* default_entry);
300 : DynamicMapField(const Message* default_entry, Arena* arena);
301 : ~DynamicMapField();
302 :
303 : // Implement MapFieldBase
304 : bool ContainsMapKey(const MapKey& map_key) const;
305 : bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
306 : bool DeleteMapValue(const MapKey& map_key);
307 :
308 : const Map<MapKey, MapValueRef>& GetMap() const;
309 : Map<MapKey, MapValueRef>* MutableMap();
310 :
311 : int size() const;
312 :
313 : private:
314 : Map<MapKey, MapValueRef> map_;
315 : const Message* default_entry_;
316 :
317 : // Implements MapFieldBase
318 : void SyncRepeatedFieldWithMapNoLock() const;
319 : void SyncMapWithRepeatedFieldNoLock() const;
320 : int SpaceUsedExcludingSelfNoLock() const;
321 : void SetMapIteratorValue(MapIterator* map_iter) const;
322 : };
323 :
324 : } // namespace internal
325 :
326 : class LIBPROTOBUF_EXPORT MapIterator {
327 : public:
328 0 : MapIterator(Message* message, const FieldDescriptor* field) {
329 0 : const Reflection* reflection = message->GetReflection();
330 0 : map_ = reflection->MapData(message, field);
331 0 : key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
332 0 : value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
333 0 : map_->InitializeIterator(this);
334 0 : }
335 : MapIterator(const MapIterator& other) {
336 : map_ = other.map_;
337 : map_->InitializeIterator(this);
338 : map_->CopyIterator(this, other);
339 : }
340 0 : ~MapIterator() {
341 0 : map_->DeleteIterator(this);
342 0 : }
343 : friend bool operator==(const MapIterator& a, const MapIterator& b) {
344 : return a.map_->EqualIterator(a, b);
345 : }
346 : friend bool operator!=(const MapIterator& a, const MapIterator& b) {
347 : return !a.map_->EqualIterator(a, b);
348 : }
349 : MapIterator& operator++() {
350 : map_->IncreaseIterator(this);
351 : return *this;
352 : }
353 : MapIterator operator++(int) {
354 : // iter_ is copied from Map<...>::iterator, no need to
355 : // copy from its self again. Use the same implementation
356 : // with operator++()
357 : map_->IncreaseIterator(this);
358 : return *this;
359 : }
360 : const MapKey& GetKey() {
361 : return key_;
362 : }
363 : const MapValueRef& GetValueRef() {
364 : return value_;
365 : }
366 : MapValueRef* MutableValueRef() {
367 : map_->SetMapDirty();
368 : return &value_;
369 : }
370 :
371 : private:
372 : template <typename Key, typename T>
373 : friend class internal::TypeDefinedMapFieldBase;
374 : friend class internal::DynamicMapField;
375 : template <typename Key, typename T,
376 : internal::WireFormatLite::FieldType kKeyFieldType,
377 : internal::WireFormatLite::FieldType kValueFieldType,
378 : int default_enum_value>
379 : friend class internal::MapField;
380 :
381 : // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
382 : // the iterator. It is allocated by MapField<...>::InitializeIterator() called
383 : // in constructor and deleted by MapField<...>::DeleteIterator() called in
384 : // destructor.
385 : void* iter_;
386 : // Point to a MapField to call helper methods implemented in MapField.
387 : // MapIterator does not own this object.
388 : internal::MapFieldBase* map_;
389 : MapKey key_;
390 : MapValueRef value_;
391 : };
392 :
393 : } // namespace protobuf
394 :
395 : } // namespace google
396 : #endif // GOOGLE_PROTOBUF_MAP_FIELD_H__
|