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