• 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 #include <google/protobuf/port_def.inc>
37 
38 namespace google {
39 namespace protobuf {
40 namespace internal {
41 
~MapFieldBase()42 MapFieldBase::~MapFieldBase() {
43   if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
44 }
45 
GetRepeatedField() const46 const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
47   ConstAccess();
48   SyncRepeatedFieldWithMap();
49   return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
50 }
51 
MutableRepeatedField()52 RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
53   MutableAccess();
54   SyncRepeatedFieldWithMap();
55   SetRepeatedDirty();
56   return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
57 }
58 
SpaceUsedExcludingSelfLong() const59 size_t MapFieldBase::SpaceUsedExcludingSelfLong() const {
60   ConstAccess();
61   mutex_.Lock();
62   size_t size = SpaceUsedExcludingSelfNoLock();
63   mutex_.Unlock();
64   ConstAccess();
65   return size;
66 }
67 
SpaceUsedExcludingSelfNoLock() const68 size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
69   if (repeated_field_ != NULL) {
70     return repeated_field_->SpaceUsedExcludingSelfLong();
71   } else {
72     return 0;
73   }
74 }
75 
IsMapValid() const76 bool MapFieldBase::IsMapValid() const {
77   ConstAccess();
78   // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
79   // executed before state_ is checked.
80   int state = state_.load(std::memory_order_acquire);
81   return state != STATE_MODIFIED_REPEATED;
82 }
83 
IsRepeatedFieldValid() const84 bool MapFieldBase::IsRepeatedFieldValid() const {
85   ConstAccess();
86   int state = state_.load(std::memory_order_acquire);
87   return state != STATE_MODIFIED_MAP;
88 }
89 
SetMapDirty()90 void MapFieldBase::SetMapDirty() {
91   MutableAccess();
92   // These are called by (non-const) mutator functions. So by our API it's the
93   // callers responsibility to have these calls properly ordered.
94   state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
95 }
96 
SetRepeatedDirty()97 void MapFieldBase::SetRepeatedDirty() {
98   MutableAccess();
99   // These are called by (non-const) mutator functions. So by our API it's the
100   // callers responsibility to have these calls properly ordered.
101   state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
102 }
103 
SyncRepeatedFieldWithMap() const104 void MapFieldBase::SyncRepeatedFieldWithMap() const {
105   ConstAccess();
106   // acquire here matches with release below to ensure that we can only see a
107   // value of CLEAN after all previous changes have been synced.
108   switch (state_.load(std::memory_order_acquire)) {
109     case STATE_MODIFIED_MAP:
110       mutex_.Lock();
111       // Double check state, because another thread may have seen the same
112       // state and done the synchronization before the current thread.
113       if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) {
114         SyncRepeatedFieldWithMapNoLock();
115         state_.store(CLEAN, std::memory_order_release);
116       }
117       mutex_.Unlock();
118       ConstAccess();
119       break;
120     case CLEAN:
121       mutex_.Lock();
122       // Double check state
123       if (state_.load(std::memory_order_relaxed) == CLEAN) {
124         if (repeated_field_ == nullptr) {
125           if (arena_ == nullptr) {
126             repeated_field_ = new RepeatedPtrField<Message>();
127           } else {
128             repeated_field_ =
129                 Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
130           }
131         }
132         state_.store(CLEAN, std::memory_order_release);
133       }
134       mutex_.Unlock();
135       ConstAccess();
136       break;
137     default:
138       break;
139   }
140 }
141 
SyncRepeatedFieldWithMapNoLock() const142 void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
143   if (repeated_field_ == NULL) {
144     repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
145   }
146 }
147 
SyncMapWithRepeatedField() const148 void MapFieldBase::SyncMapWithRepeatedField() const {
149   ConstAccess();
150   // acquire here matches with release below to ensure that we can only see a
151   // value of CLEAN after all previous changes have been synced.
152   if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) {
153     mutex_.Lock();
154     // Double check state, because another thread may have seen the same state
155     // and done the synchronization before the current thread.
156     if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_REPEATED) {
157       SyncMapWithRepeatedFieldNoLock();
158       state_.store(CLEAN, std::memory_order_release);
159     }
160     mutex_.Unlock();
161     ConstAccess();
162   }
163 }
164 
165 // ------------------DynamicMapField------------------
DynamicMapField(const Message * default_entry)166 DynamicMapField::DynamicMapField(const Message* default_entry)
167     : default_entry_(default_entry) {}
168 
DynamicMapField(const Message * default_entry,Arena * arena)169 DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena)
170     : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
171       map_(arena),
172       default_entry_(default_entry) {}
173 
~DynamicMapField()174 DynamicMapField::~DynamicMapField() {
175   // DynamicMapField owns map values. Need to delete them before clearing
176   // the map.
177   for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
178        iter != map_.end(); ++iter) {
179     iter->second.DeleteData();
180   }
181   map_.clear();
182 }
183 
size() const184 int DynamicMapField::size() const { return GetMap().size(); }
185 
Clear()186 void DynamicMapField::Clear() {
187   Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
188   if (MapFieldBase::arena_ == nullptr) {
189     for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
190          iter != map->end(); ++iter) {
191       iter->second.DeleteData();
192     }
193   }
194 
195   map->clear();
196 
197   if (MapFieldBase::repeated_field_ != nullptr) {
198     MapFieldBase::repeated_field_->Clear();
199   }
200   // Data in map and repeated field are both empty, but we can't set status
201   // CLEAN which will invalidate previous reference to map.
202   MapFieldBase::SetMapDirty();
203 }
204 
ContainsMapKey(const MapKey & map_key) const205 bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const {
206   const Map<MapKey, MapValueRef>& map = GetMap();
207   Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
208   return iter != map.end();
209 }
210 
AllocateMapValue(MapValueRef * map_val)211 void DynamicMapField::AllocateMapValue(MapValueRef* map_val) {
212   const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
213   map_val->SetType(val_des->cpp_type());
214   // Allocate memory for the MapValueRef, and initialize to
215   // default value.
216   switch (val_des->cpp_type()) {
217 #define HANDLE_TYPE(CPPTYPE, TYPE)                           \
218   case FieldDescriptor::CPPTYPE_##CPPTYPE: {                 \
219     TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \
220     map_val->SetValue(value);                                \
221     break;                                                   \
222   }
223     HANDLE_TYPE(INT32, int32);
224     HANDLE_TYPE(INT64, int64);
225     HANDLE_TYPE(UINT32, uint32);
226     HANDLE_TYPE(UINT64, uint64);
227     HANDLE_TYPE(DOUBLE, double);
228     HANDLE_TYPE(FLOAT, float);
229     HANDLE_TYPE(BOOL, bool);
230     HANDLE_TYPE(STRING, std::string);
231     HANDLE_TYPE(ENUM, int32);
232 #undef HANDLE_TYPE
233     case FieldDescriptor::CPPTYPE_MESSAGE: {
234       const Message& message =
235           default_entry_->GetReflection()->GetMessage(*default_entry_, val_des);
236       Message* value = message.New(MapFieldBase::arena_);
237       map_val->SetValue(value);
238       break;
239     }
240   }
241 }
242 
InsertOrLookupMapValue(const MapKey & map_key,MapValueRef * val)243 bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key,
244                                              MapValueRef* val) {
245   // Always use mutable map because users may change the map value by
246   // MapValueRef.
247   Map<MapKey, MapValueRef>* map = MutableMap();
248   Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
249   if (iter == map->end()) {
250     MapValueRef& map_val = map_[map_key];
251     AllocateMapValue(&map_val);
252     val->CopyFrom(map_val);
253     return true;
254   }
255   // map_key is already in the map. Make sure (*map)[map_key] is not called.
256   // [] may reorder the map and iterators.
257   val->CopyFrom(iter->second);
258   return false;
259 }
260 
LookupMapValue(const MapKey & map_key,MapValueConstRef * val) const261 bool DynamicMapField::LookupMapValue(const MapKey& map_key,
262                                      MapValueConstRef* val) const {
263   const Map<MapKey, MapValueRef>& map = GetMap();
264   Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
265   if (iter == map.end()) {
266     return false;
267   }
268   // map_key is already in the map. Make sure (*map)[map_key] is not called.
269   // [] may reorder the map and iterators.
270   val->CopyFrom(iter->second);
271   return true;
272 }
273 
DeleteMapValue(const MapKey & map_key)274 bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
275   MapFieldBase::SyncMapWithRepeatedField();
276   Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
277   if (iter == map_.end()) {
278     return false;
279   }
280   // Set map dirty only if the delete is successful.
281   MapFieldBase::SetMapDirty();
282   if (MapFieldBase::arena_ == nullptr) {
283     iter->second.DeleteData();
284   }
285   map_.erase(iter);
286   return true;
287 }
288 
GetMap() const289 const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
290   MapFieldBase::SyncMapWithRepeatedField();
291   return map_;
292 }
293 
MutableMap()294 Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
295   MapFieldBase::SyncMapWithRepeatedField();
296   MapFieldBase::SetMapDirty();
297   return &map_;
298 }
299 
SetMapIteratorValue(MapIterator * map_iter) const300 void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
301   Map<MapKey, MapValueRef>::const_iterator iter =
302       TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
303           map_iter);
304   if (iter == map_.end()) return;
305   map_iter->key_.CopyFrom(iter->first);
306   map_iter->value_.CopyFrom(iter->second);
307 }
308 
MergeFrom(const MapFieldBase & other)309 void DynamicMapField::MergeFrom(const MapFieldBase& other) {
310   GOOGLE_DCHECK(IsMapValid() && other.IsMapValid());
311   Map<MapKey, MapValueRef>* map = MutableMap();
312   const DynamicMapField& other_field =
313       reinterpret_cast<const DynamicMapField&>(other);
314   for (Map<MapKey, MapValueRef>::const_iterator other_it =
315            other_field.map_.begin();
316        other_it != other_field.map_.end(); ++other_it) {
317     Map<MapKey, MapValueRef>::iterator iter = map->find(other_it->first);
318     MapValueRef* map_val;
319     if (iter == map->end()) {
320       map_val = &map_[other_it->first];
321       AllocateMapValue(map_val);
322     } else {
323       map_val = &iter->second;
324     }
325 
326     // Copy map value
327     const FieldDescriptor* field_descriptor =
328         default_entry_->GetDescriptor()->map_value();
329     switch (field_descriptor->cpp_type()) {
330       case FieldDescriptor::CPPTYPE_INT32: {
331         map_val->SetInt32Value(other_it->second.GetInt32Value());
332         break;
333       }
334       case FieldDescriptor::CPPTYPE_INT64: {
335         map_val->SetInt64Value(other_it->second.GetInt64Value());
336         break;
337       }
338       case FieldDescriptor::CPPTYPE_UINT32: {
339         map_val->SetUInt32Value(other_it->second.GetUInt32Value());
340         break;
341       }
342       case FieldDescriptor::CPPTYPE_UINT64: {
343         map_val->SetUInt64Value(other_it->second.GetUInt64Value());
344         break;
345       }
346       case FieldDescriptor::CPPTYPE_FLOAT: {
347         map_val->SetFloatValue(other_it->second.GetFloatValue());
348         break;
349       }
350       case FieldDescriptor::CPPTYPE_DOUBLE: {
351         map_val->SetDoubleValue(other_it->second.GetDoubleValue());
352         break;
353       }
354       case FieldDescriptor::CPPTYPE_BOOL: {
355         map_val->SetBoolValue(other_it->second.GetBoolValue());
356         break;
357       }
358       case FieldDescriptor::CPPTYPE_STRING: {
359         map_val->SetStringValue(other_it->second.GetStringValue());
360         break;
361       }
362       case FieldDescriptor::CPPTYPE_ENUM: {
363         map_val->SetEnumValue(other_it->second.GetEnumValue());
364         break;
365       }
366       case FieldDescriptor::CPPTYPE_MESSAGE: {
367         map_val->MutableMessageValue()->CopyFrom(
368             other_it->second.GetMessageValue());
369         break;
370       }
371     }
372   }
373 }
374 
Swap(MapFieldBase * other)375 void DynamicMapField::Swap(MapFieldBase* other) {
376   DynamicMapField* other_field = down_cast<DynamicMapField*>(other);
377   std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_);
378   map_.swap(other_field->map_);
379   // a relaxed swap of the atomic
380   auto other_state = other_field->state_.load(std::memory_order_relaxed);
381   auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed);
382   other_field->state_.store(this_state, std::memory_order_relaxed);
383   this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed);
384 }
385 
SyncRepeatedFieldWithMapNoLock() const386 void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
387   const Reflection* reflection = default_entry_->GetReflection();
388   const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key();
389   const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
390   if (MapFieldBase::repeated_field_ == NULL) {
391     if (MapFieldBase::arena_ == NULL) {
392       MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
393     } else {
394       MapFieldBase::repeated_field_ =
395           Arena::CreateMessage<RepeatedPtrField<Message> >(
396               MapFieldBase::arena_);
397     }
398   }
399 
400   MapFieldBase::repeated_field_->Clear();
401 
402   for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
403        it != map_.end(); ++it) {
404     Message* new_entry = default_entry_->New(MapFieldBase::arena_);
405     MapFieldBase::repeated_field_->AddAllocated(new_entry);
406     const MapKey& map_key = it->first;
407     switch (key_des->cpp_type()) {
408       case FieldDescriptor::CPPTYPE_STRING:
409         reflection->SetString(new_entry, key_des, map_key.GetStringValue());
410         break;
411       case FieldDescriptor::CPPTYPE_INT64:
412         reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
413         break;
414       case FieldDescriptor::CPPTYPE_INT32:
415         reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
416         break;
417       case FieldDescriptor::CPPTYPE_UINT64:
418         reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
419         break;
420       case FieldDescriptor::CPPTYPE_UINT32:
421         reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
422         break;
423       case FieldDescriptor::CPPTYPE_BOOL:
424         reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
425         break;
426       case FieldDescriptor::CPPTYPE_DOUBLE:
427       case FieldDescriptor::CPPTYPE_FLOAT:
428       case FieldDescriptor::CPPTYPE_ENUM:
429       case FieldDescriptor::CPPTYPE_MESSAGE:
430         GOOGLE_LOG(FATAL) << "Can't get here.";
431         break;
432     }
433     const MapValueRef& map_val = it->second;
434     switch (val_des->cpp_type()) {
435       case FieldDescriptor::CPPTYPE_STRING:
436         reflection->SetString(new_entry, val_des, map_val.GetStringValue());
437         break;
438       case FieldDescriptor::CPPTYPE_INT64:
439         reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
440         break;
441       case FieldDescriptor::CPPTYPE_INT32:
442         reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
443         break;
444       case FieldDescriptor::CPPTYPE_UINT64:
445         reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
446         break;
447       case FieldDescriptor::CPPTYPE_UINT32:
448         reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
449         break;
450       case FieldDescriptor::CPPTYPE_BOOL:
451         reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
452         break;
453       case FieldDescriptor::CPPTYPE_DOUBLE:
454         reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
455         break;
456       case FieldDescriptor::CPPTYPE_FLOAT:
457         reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
458         break;
459       case FieldDescriptor::CPPTYPE_ENUM:
460         reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
461         break;
462       case FieldDescriptor::CPPTYPE_MESSAGE: {
463         const Message& message = map_val.GetMessageValue();
464         reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
465         break;
466       }
467     }
468   }
469 }
470 
SyncMapWithRepeatedFieldNoLock() const471 void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
472   Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
473   const Reflection* reflection = default_entry_->GetReflection();
474   const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key();
475   const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
476   // DynamicMapField owns map values. Need to delete them before clearing
477   // the map.
478   if (MapFieldBase::arena_ == nullptr) {
479     for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
480          iter != map->end(); ++iter) {
481       iter->second.DeleteData();
482     }
483   }
484   map->clear();
485   for (RepeatedPtrField<Message>::iterator it =
486            MapFieldBase::repeated_field_->begin();
487        it != MapFieldBase::repeated_field_->end(); ++it) {
488     // MapKey type will be set later.
489     MapKey map_key;
490     switch (key_des->cpp_type()) {
491       case FieldDescriptor::CPPTYPE_STRING:
492         map_key.SetStringValue(reflection->GetString(*it, key_des));
493         break;
494       case FieldDescriptor::CPPTYPE_INT64:
495         map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
496         break;
497       case FieldDescriptor::CPPTYPE_INT32:
498         map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
499         break;
500       case FieldDescriptor::CPPTYPE_UINT64:
501         map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
502         break;
503       case FieldDescriptor::CPPTYPE_UINT32:
504         map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
505         break;
506       case FieldDescriptor::CPPTYPE_BOOL:
507         map_key.SetBoolValue(reflection->GetBool(*it, key_des));
508         break;
509       case FieldDescriptor::CPPTYPE_DOUBLE:
510       case FieldDescriptor::CPPTYPE_FLOAT:
511       case FieldDescriptor::CPPTYPE_ENUM:
512       case FieldDescriptor::CPPTYPE_MESSAGE:
513         GOOGLE_LOG(FATAL) << "Can't get here.";
514         break;
515     }
516 
517     if (MapFieldBase::arena_ == nullptr) {
518       // Remove existing map value with same key.
519       Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
520       if (iter != map->end()) {
521         iter->second.DeleteData();
522       }
523     }
524 
525     MapValueRef& map_val = (*map)[map_key];
526     map_val.SetType(val_des->cpp_type());
527     switch (val_des->cpp_type()) {
528 #define HANDLE_TYPE(CPPTYPE, TYPE, METHOD)                   \
529   case FieldDescriptor::CPPTYPE_##CPPTYPE: {                 \
530     TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \
531     *value = reflection->Get##METHOD(*it, val_des);          \
532     map_val.SetValue(value);                                 \
533     break;                                                   \
534   }
535       HANDLE_TYPE(INT32, int32, Int32);
536       HANDLE_TYPE(INT64, int64, Int64);
537       HANDLE_TYPE(UINT32, uint32, UInt32);
538       HANDLE_TYPE(UINT64, uint64, UInt64);
539       HANDLE_TYPE(DOUBLE, double, Double);
540       HANDLE_TYPE(FLOAT, float, Float);
541       HANDLE_TYPE(BOOL, bool, Bool);
542       HANDLE_TYPE(STRING, std::string, String);
543       HANDLE_TYPE(ENUM, int32, EnumValue);
544 #undef HANDLE_TYPE
545       case FieldDescriptor::CPPTYPE_MESSAGE: {
546         const Message& message = reflection->GetMessage(*it, val_des);
547         Message* value = message.New(MapFieldBase::arena_);
548         value->CopyFrom(message);
549         map_val.SetValue(value);
550         break;
551       }
552     }
553   }
554 }
555 
SpaceUsedExcludingSelfNoLock() const556 size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
557   size_t size = 0;
558   if (MapFieldBase::repeated_field_ != NULL) {
559     size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong();
560   }
561   size += sizeof(map_);
562   size_t map_size = map_.size();
563   if (map_size) {
564     Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
565     size += sizeof(it->first) * map_size;
566     size += sizeof(it->second) * map_size;
567     // If key is string, add the allocated space.
568     if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) {
569       size += sizeof(std::string) * map_size;
570     }
571     // Add the allocated space in MapValueRef.
572     switch (it->second.type()) {
573 #define HANDLE_TYPE(CPPTYPE, TYPE)           \
574   case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
575     size += sizeof(TYPE) * map_size;         \
576     break;                                   \
577   }
578       HANDLE_TYPE(INT32, int32);
579       HANDLE_TYPE(INT64, int64);
580       HANDLE_TYPE(UINT32, uint32);
581       HANDLE_TYPE(UINT64, uint64);
582       HANDLE_TYPE(DOUBLE, double);
583       HANDLE_TYPE(FLOAT, float);
584       HANDLE_TYPE(BOOL, bool);
585       HANDLE_TYPE(STRING, std::string);
586       HANDLE_TYPE(ENUM, int32);
587 #undef HANDLE_TYPE
588       case FieldDescriptor::CPPTYPE_MESSAGE: {
589         while (it != map_.end()) {
590           const Message& message = it->second.GetMessageValue();
591           size += message.GetReflection()->SpaceUsedLong(message);
592           ++it;
593         }
594         break;
595       }
596     }
597   }
598   return size;
599 }
600 
601 }  // namespace internal
602 }  // namespace protobuf
603 }  // namespace google
604