• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <google/protobuf/map_field.h>
32 #include <google/protobuf/map_field_inl.h>
33 
34 #include <vector>
35 
36 namespace google {
37 namespace protobuf {
38 namespace internal {
39 
40 ProtobufOnceType map_entry_default_instances_once_;
41 Mutex* map_entry_default_instances_mutex_;
42 vector<MessageLite*>* map_entry_default_instances_;
43 
DeleteMapEntryDefaultInstances()44 void DeleteMapEntryDefaultInstances() {
45   for (int i = 0; i < map_entry_default_instances_->size(); ++i) {
46     delete map_entry_default_instances_->at(i);
47   }
48   delete map_entry_default_instances_mutex_;
49   delete map_entry_default_instances_;
50 }
51 
InitMapEntryDefaultInstances()52 void InitMapEntryDefaultInstances() {
53   map_entry_default_instances_mutex_ = new Mutex();
54   map_entry_default_instances_ = new vector<MessageLite*>();
55   OnShutdown(&DeleteMapEntryDefaultInstances);
56 }
57 
RegisterMapEntryDefaultInstance(MessageLite * default_instance)58 void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
59   ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
60                  &InitMapEntryDefaultInstances);
61   MutexLock lock(map_entry_default_instances_mutex_);
62   map_entry_default_instances_->push_back(default_instance);
63 }
64 
~MapFieldBase()65 MapFieldBase::~MapFieldBase() {
66   if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
67 }
68 
GetRepeatedField() const69 const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
70   SyncRepeatedFieldWithMap();
71   return *repeated_field_;
72 }
73 
MutableRepeatedField()74 RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
75   SyncRepeatedFieldWithMap();
76   SetRepeatedDirty();
77   return repeated_field_;
78 }
79 
SpaceUsedExcludingSelf() const80 int MapFieldBase::SpaceUsedExcludingSelf() const {
81   mutex_.Lock();
82   int size = SpaceUsedExcludingSelfNoLock();
83   mutex_.Unlock();
84   return size;
85 }
86 
SpaceUsedExcludingSelfNoLock() const87 int MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
88   if (repeated_field_ != NULL) {
89     return repeated_field_->SpaceUsedExcludingSelf();
90   } else {
91     return 0;
92   }
93 }
94 
InitMetadataOnce() const95 void MapFieldBase::InitMetadataOnce() const {
96   GOOGLE_CHECK(entry_descriptor_ != NULL);
97   GOOGLE_CHECK(assign_descriptor_callback_ != NULL);
98   (*assign_descriptor_callback_)();
99 }
100 
SetMapDirty()101 void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
102 
SetRepeatedDirty()103 void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
104 
MutableRepeatedPtrField() const105 void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
106 
SyncRepeatedFieldWithMap() const107 void MapFieldBase::SyncRepeatedFieldWithMap() const {
108   // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
109   // executed before state_ is checked.
110   Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
111   if (state == STATE_MODIFIED_MAP) {
112     mutex_.Lock();
113     // Double check state, because another thread may have seen the same state
114     // and done the synchronization before the current thread.
115     if (state_ == STATE_MODIFIED_MAP) {
116       SyncRepeatedFieldWithMapNoLock();
117       // "Release" insures state_ can only be changed "after"
118       // SyncRepeatedFieldWithMapNoLock is finished.
119       google::protobuf::internal::Release_Store(&state_, CLEAN);
120     }
121     mutex_.Unlock();
122   }
123 }
124 
SyncRepeatedFieldWithMapNoLock() const125 void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
126   if (repeated_field_ == NULL) {
127     repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
128   }
129 }
130 
SyncMapWithRepeatedField() const131 void MapFieldBase::SyncMapWithRepeatedField() const {
132   // "Acquire" insures the operation after SyncMapWithRepeatedField won't get
133   // executed before state_ is checked.
134   Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
135   if (state == STATE_MODIFIED_REPEATED) {
136     mutex_.Lock();
137     // Double check state, because another thread may have seen the same state
138     // and done the synchronization before the current thread.
139     if (state_ == STATE_MODIFIED_REPEATED) {
140       SyncMapWithRepeatedFieldNoLock();
141       // "Release" insures state_ can only be changed "after"
142       // SyncRepeatedFieldWithMapNoLock is finished.
143       google::protobuf::internal::Release_Store(&state_, CLEAN);
144     }
145     mutex_.Unlock();
146   }
147 }
148 
149 // ------------------DynamicMapField------------------
DynamicMapField(const Message * default_entry)150 DynamicMapField::DynamicMapField(const Message* default_entry)
151     : default_entry_(default_entry) {
152 }
153 
DynamicMapField(const Message * default_entry,Arena * arena)154 DynamicMapField::DynamicMapField(const Message* default_entry,
155                                  Arena* arena)
156     : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
157       default_entry_(default_entry) {
158 }
159 
~DynamicMapField()160 DynamicMapField::~DynamicMapField() {
161   // DynamicMapField owns map values. Need to delete them before clearing
162   // the map.
163   for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
164        iter != map_.end(); ++iter) {
165     iter->second.DeleteData();
166   }
167   map_.clear();
168 }
169 
size() const170 int DynamicMapField::size() const {
171   return GetMap().size();
172 }
173 
ContainsMapKey(const MapKey & map_key) const174 bool DynamicMapField::ContainsMapKey(
175     const MapKey& map_key) const {
176   const Map<MapKey, MapValueRef>& map = GetMap();
177   Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
178   return iter != map.end();
179 }
180 
InsertOrLookupMapValue(const MapKey & map_key,MapValueRef * val)181 bool DynamicMapField::InsertOrLookupMapValue(
182     const MapKey& map_key, MapValueRef* val) {
183   // Always use mutable map because users may change the map value by
184   // MapValueRef.
185   Map<MapKey, MapValueRef>* map = MutableMap();
186   Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
187   if (iter == map->end()) {
188     // Insert
189     MapValueRef& map_val = (*map)[map_key];
190     const FieldDescriptor* val_des =
191         default_entry_->GetDescriptor()->FindFieldByName("value");
192     map_val.SetType(val_des->cpp_type());
193     // Allocate memory for the inserted MapValueRef, and initialize to
194     // default value.
195     switch (val_des->cpp_type()) {
196 #define HANDLE_TYPE(CPPTYPE, TYPE)                              \
197       case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
198         TYPE * value = new TYPE();                              \
199         map_val.SetValue(value);                                \
200         break;                                                  \
201       }
202       HANDLE_TYPE(INT32, int32);
203       HANDLE_TYPE(INT64, int64);
204       HANDLE_TYPE(UINT32, uint32);
205       HANDLE_TYPE(UINT64, uint64);
206       HANDLE_TYPE(DOUBLE, double);
207       HANDLE_TYPE(FLOAT, float);
208       HANDLE_TYPE(BOOL, bool);
209       HANDLE_TYPE(STRING, string);
210       HANDLE_TYPE(ENUM, int32);
211 #undef HANDLE_TYPE
212       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
213         const Message& message = default_entry_->GetReflection()->GetMessage(
214             *default_entry_, val_des);
215         Message* value = message.New();
216         map_val.SetValue(value);
217         break;
218       }
219     }
220     val->CopyFrom(map_val);
221     return true;
222   }
223   // map_key is already in the map. Make sure (*map)[map_key] is not called.
224   // [] may reorder the map and iterators.
225   val->CopyFrom(iter->second);
226   return false;
227 }
228 
DeleteMapValue(const MapKey & map_key)229 bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
230   MapFieldBase::SyncMapWithRepeatedField();
231   Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
232   if (iter == map_.end()) {
233     return false;
234   }
235   // Set map dirty only if the delete is successful.
236   MapFieldBase::SetMapDirty();
237   iter->second.DeleteData();
238   map_.erase(iter);
239   return true;
240 }
241 
GetMap() const242 const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
243   MapFieldBase::SyncMapWithRepeatedField();
244   return map_;
245 }
246 
MutableMap()247 Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
248   MapFieldBase::SyncMapWithRepeatedField();
249   MapFieldBase::SetMapDirty();
250   return &map_;
251 }
252 
SetMapIteratorValue(MapIterator * map_iter) const253 void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
254   Map<MapKey, MapValueRef>::const_iterator iter =
255       TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
256           map_iter);
257   if (iter == map_.end()) return;
258   map_iter->key_.CopyFrom(iter->first);
259   map_iter->value_.CopyFrom(iter->second);
260 }
261 
SyncRepeatedFieldWithMapNoLock() const262 void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
263   const Reflection* reflection = default_entry_->GetReflection();
264   const FieldDescriptor* key_des =
265       default_entry_->GetDescriptor()->FindFieldByName("key");
266   const FieldDescriptor* val_des =
267       default_entry_->GetDescriptor()->FindFieldByName("value");
268   if (MapFieldBase::repeated_field_ == NULL) {
269     if (MapFieldBase::arena_ == NULL) {
270       MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
271     } else {
272       MapFieldBase::repeated_field_ =
273           Arena::CreateMessage<RepeatedPtrField<Message> >(
274               MapFieldBase::arena_);
275     }
276   }
277 
278   MapFieldBase::repeated_field_->Clear();
279 
280   for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
281        it != map_.end(); ++it) {
282     Message* new_entry = default_entry_->New();
283     MapFieldBase::repeated_field_->AddAllocated(new_entry);
284     const MapKey& map_key = it->first;
285     switch (key_des->cpp_type()) {
286       case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
287         reflection->SetString(new_entry, key_des, map_key.GetStringValue());
288         break;
289       case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
290         reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
291         break;
292       case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
293         reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
294         break;
295       case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
296         reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
297         break;
298       case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
299         reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
300         break;
301       case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
302         reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
303         break;
304       case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
305       case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
306       case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
307       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
308         GOOGLE_LOG(FATAL) << "Can't get here.";
309         break;
310     }
311     const MapValueRef& map_val = it->second;
312     switch (val_des->cpp_type()) {
313       case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
314         reflection->SetString(new_entry, val_des, map_val.GetStringValue());
315         break;
316       case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
317         reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
318         break;
319       case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
320         reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
321         break;
322       case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
323         reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
324         break;
325       case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
326         reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
327         break;
328       case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
329         reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
330         break;
331       case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
332         reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
333         break;
334       case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
335         reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
336         break;
337       case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
338         reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
339         break;
340       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
341         const Message& message = map_val.GetMessageValue();
342         reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
343         break;
344       }
345     }
346   }
347 }
348 
SyncMapWithRepeatedFieldNoLock() const349 void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
350   Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
351   const Reflection* reflection = default_entry_->GetReflection();
352   const FieldDescriptor* key_des =
353       default_entry_->GetDescriptor()->FindFieldByName("key");
354   const FieldDescriptor* val_des =
355       default_entry_->GetDescriptor()->FindFieldByName("value");
356   // DynamicMapField owns map values. Need to delete them before clearing
357   // the map.
358   for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
359        iter != map->end(); ++iter) {
360     iter->second.DeleteData();
361   }
362   map->clear();
363   for (RepeatedPtrField<Message>::iterator it =
364            MapFieldBase::repeated_field_->begin();
365        it != MapFieldBase::repeated_field_->end(); ++it) {
366     MapKey map_key;
367     switch (key_des->cpp_type()) {
368       case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
369         map_key.SetStringValue(reflection->GetString(*it, key_des));
370         break;
371       case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
372         map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
373         break;
374       case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
375         map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
376         break;
377       case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
378         map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
379         break;
380       case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
381         map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
382         break;
383       case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
384         map_key.SetBoolValue(reflection->GetBool(*it, key_des));
385         break;
386       case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
387       case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
388       case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
389       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
390         GOOGLE_LOG(FATAL) << "Can't get here.";
391         break;
392     }
393     MapValueRef& map_val = (*map)[map_key];
394     map_val.SetType(val_des->cpp_type());
395     switch (val_des->cpp_type()) {
396 #define HANDLE_TYPE(CPPTYPE, TYPE, METHOD)                      \
397       case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
398         TYPE * value = new TYPE;                                \
399         *value = reflection->Get##METHOD(*it, val_des);         \
400             map_val.SetValue(value);                            \
401             break;                                              \
402       }
403       HANDLE_TYPE(INT32, int32, Int32);
404       HANDLE_TYPE(INT64, int64, Int64);
405       HANDLE_TYPE(UINT32, uint32, UInt32);
406       HANDLE_TYPE(UINT64, uint64, UInt64);
407       HANDLE_TYPE(DOUBLE, double, Double);
408       HANDLE_TYPE(FLOAT, float, Float);
409       HANDLE_TYPE(BOOL, bool, Bool);
410       HANDLE_TYPE(STRING, string, String);
411       HANDLE_TYPE(ENUM, int32, EnumValue);
412 #undef HANDLE_TYPE
413       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
414         const Message& message = reflection->GetMessage(*it, val_des);
415         Message* value = message.New();
416         value->CopyFrom(message);
417         map_val.SetValue(value);
418         break;
419       }
420     }
421   }
422 }
423 
SpaceUsedExcludingSelfNoLock() const424 int DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
425   int size = 0;
426   if (MapFieldBase::repeated_field_ != NULL) {
427     size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
428   }
429   size += sizeof(map_);
430   int map_size = map_.size();
431   if (map_size) {
432     Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
433     size += sizeof(it->first) * map_size;
434     size += sizeof(it->second) * map_size;
435     // If key is string, add the allocated space.
436     if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
437       size += sizeof(string) * map_size;
438     }
439     // Add the allocated space in MapValueRef.
440     switch (it->second.type()) {
441 #define HANDLE_TYPE(CPPTYPE, TYPE)                              \
442       case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
443         size += sizeof(TYPE) * map_size;                        \
444         break;                                                  \
445       }
446       HANDLE_TYPE(INT32, int32);
447       HANDLE_TYPE(INT64, int64);
448       HANDLE_TYPE(UINT32, uint32);
449       HANDLE_TYPE(UINT64, uint64);
450       HANDLE_TYPE(DOUBLE, double);
451       HANDLE_TYPE(FLOAT, float);
452       HANDLE_TYPE(BOOL, bool);
453       HANDLE_TYPE(STRING, string);
454       HANDLE_TYPE(ENUM, int32);
455 #undef HANDLE_TYPE
456       case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
457         while (it != map_.end()) {
458           const Message& message = it->second.GetMessageValue();
459           size += message.GetReflection()->SpaceUsed(message);
460           ++it;
461         }
462         break;
463       }
464     }
465   }
466   return size;
467 }
468 
469 }  // namespace internal
470 }  // namespace protobuf
471 }  // namespace google
472