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