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 for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
176 iter != map->end(); ++iter) {
177 iter->second.DeleteData();
178 }
179 map->clear();
180
181 if (MapFieldBase::repeated_field_ != nullptr) {
182 MapFieldBase::repeated_field_->Clear();
183 }
184 // Data in map and repeated field are both empty, but we can't set status
185 // CLEAN which will invalidate previous reference to map.
186 MapFieldBase::SetMapDirty();
187 }
188
ContainsMapKey(const MapKey & map_key) const189 bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const {
190 const Map<MapKey, MapValueRef>& map = GetMap();
191 Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
192 return iter != map.end();
193 }
194
AllocateMapValue(MapValueRef * map_val)195 void DynamicMapField::AllocateMapValue(MapValueRef* map_val) {
196 const FieldDescriptor* val_des =
197 default_entry_->GetDescriptor()->FindFieldByName("value");
198 map_val->SetType(val_des->cpp_type());
199 // Allocate memory for the MapValueRef, and initialize to
200 // default value.
201 switch (val_des->cpp_type()) {
202 #define HANDLE_TYPE(CPPTYPE, TYPE) \
203 case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
204 TYPE* value = new TYPE(); \
205 map_val->SetValue(value); \
206 break; \
207 }
208 HANDLE_TYPE(INT32, int32);
209 HANDLE_TYPE(INT64, int64);
210 HANDLE_TYPE(UINT32, uint32);
211 HANDLE_TYPE(UINT64, uint64);
212 HANDLE_TYPE(DOUBLE, double);
213 HANDLE_TYPE(FLOAT, float);
214 HANDLE_TYPE(BOOL, bool);
215 HANDLE_TYPE(STRING, std::string);
216 HANDLE_TYPE(ENUM, int32);
217 #undef HANDLE_TYPE
218 case FieldDescriptor::CPPTYPE_MESSAGE: {
219 const Message& message =
220 default_entry_->GetReflection()->GetMessage(*default_entry_, val_des);
221 Message* value = message.New();
222 map_val->SetValue(value);
223 break;
224 }
225 }
226 }
227
InsertOrLookupMapValue(const MapKey & map_key,MapValueRef * val)228 bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key,
229 MapValueRef* val) {
230 // Always use mutable map because users may change the map value by
231 // MapValueRef.
232 Map<MapKey, MapValueRef>* map = MutableMap();
233 Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
234 if (iter == map->end()) {
235 MapValueRef& map_val = map_[map_key];
236 AllocateMapValue(&map_val);
237 val->CopyFrom(map_val);
238 return true;
239 }
240 // map_key is already in the map. Make sure (*map)[map_key] is not called.
241 // [] may reorder the map and iterators.
242 val->CopyFrom(iter->second);
243 return false;
244 }
245
DeleteMapValue(const MapKey & map_key)246 bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
247 MapFieldBase::SyncMapWithRepeatedField();
248 Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
249 if (iter == map_.end()) {
250 return false;
251 }
252 // Set map dirty only if the delete is successful.
253 MapFieldBase::SetMapDirty();
254 iter->second.DeleteData();
255 map_.erase(iter);
256 return true;
257 }
258
GetMap() const259 const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
260 MapFieldBase::SyncMapWithRepeatedField();
261 return map_;
262 }
263
MutableMap()264 Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
265 MapFieldBase::SyncMapWithRepeatedField();
266 MapFieldBase::SetMapDirty();
267 return &map_;
268 }
269
SetMapIteratorValue(MapIterator * map_iter) const270 void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
271 Map<MapKey, MapValueRef>::const_iterator iter =
272 TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
273 map_iter);
274 if (iter == map_.end()) return;
275 map_iter->key_.CopyFrom(iter->first);
276 map_iter->value_.CopyFrom(iter->second);
277 }
278
MergeFrom(const MapFieldBase & other)279 void DynamicMapField::MergeFrom(const MapFieldBase& other) {
280 GOOGLE_DCHECK(IsMapValid() && other.IsMapValid());
281 Map<MapKey, MapValueRef>* map = MutableMap();
282 const DynamicMapField& other_field =
283 reinterpret_cast<const DynamicMapField&>(other);
284 for (Map<MapKey, MapValueRef>::const_iterator other_it =
285 other_field.map_.begin();
286 other_it != other_field.map_.end(); ++other_it) {
287 Map<MapKey, MapValueRef>::iterator iter = map->find(other_it->first);
288 MapValueRef* map_val;
289 if (iter == map->end()) {
290 map_val = &map_[other_it->first];
291 AllocateMapValue(map_val);
292 } else {
293 map_val = &iter->second;
294 }
295
296 // Copy map value
297 const FieldDescriptor* field_descriptor =
298 default_entry_->GetDescriptor()->FindFieldByName("value");
299 switch (field_descriptor->cpp_type()) {
300 case FieldDescriptor::CPPTYPE_INT32: {
301 map_val->SetInt32Value(other_it->second.GetInt32Value());
302 break;
303 }
304 case FieldDescriptor::CPPTYPE_INT64: {
305 map_val->SetInt64Value(other_it->second.GetInt64Value());
306 break;
307 }
308 case FieldDescriptor::CPPTYPE_UINT32: {
309 map_val->SetUInt32Value(other_it->second.GetUInt32Value());
310 break;
311 }
312 case FieldDescriptor::CPPTYPE_UINT64: {
313 map_val->SetUInt64Value(other_it->second.GetUInt64Value());
314 break;
315 }
316 case FieldDescriptor::CPPTYPE_FLOAT: {
317 map_val->SetFloatValue(other_it->second.GetFloatValue());
318 break;
319 }
320 case FieldDescriptor::CPPTYPE_DOUBLE: {
321 map_val->SetDoubleValue(other_it->second.GetDoubleValue());
322 break;
323 }
324 case FieldDescriptor::CPPTYPE_BOOL: {
325 map_val->SetBoolValue(other_it->second.GetBoolValue());
326 break;
327 }
328 case FieldDescriptor::CPPTYPE_STRING: {
329 map_val->SetStringValue(other_it->second.GetStringValue());
330 break;
331 }
332 case FieldDescriptor::CPPTYPE_ENUM: {
333 map_val->SetEnumValue(other_it->second.GetEnumValue());
334 break;
335 }
336 case FieldDescriptor::CPPTYPE_MESSAGE: {
337 map_val->MutableMessageValue()->CopyFrom(
338 other_it->second.GetMessageValue());
339 break;
340 }
341 }
342 }
343 }
344
Swap(MapFieldBase * other)345 void DynamicMapField::Swap(MapFieldBase* other) {
346 DynamicMapField* other_field = down_cast<DynamicMapField*>(other);
347 std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_);
348 map_.swap(other_field->map_);
349 // a relaxed swap of the atomic
350 auto other_state = other_field->state_.load(std::memory_order_relaxed);
351 auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed);
352 other_field->state_.store(this_state, std::memory_order_relaxed);
353 this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed);
354 }
355
SyncRepeatedFieldWithMapNoLock() const356 void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
357 const Reflection* reflection = default_entry_->GetReflection();
358 const FieldDescriptor* key_des =
359 default_entry_->GetDescriptor()->FindFieldByName("key");
360 const FieldDescriptor* val_des =
361 default_entry_->GetDescriptor()->FindFieldByName("value");
362 if (MapFieldBase::repeated_field_ == NULL) {
363 if (MapFieldBase::arena_ == NULL) {
364 MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
365 } else {
366 MapFieldBase::repeated_field_ =
367 Arena::CreateMessage<RepeatedPtrField<Message> >(
368 MapFieldBase::arena_);
369 }
370 }
371
372 MapFieldBase::repeated_field_->Clear();
373
374 for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
375 it != map_.end(); ++it) {
376 Message* new_entry = default_entry_->New();
377 MapFieldBase::repeated_field_->AddAllocated(new_entry);
378 const MapKey& map_key = it->first;
379 switch (key_des->cpp_type()) {
380 case FieldDescriptor::CPPTYPE_STRING:
381 reflection->SetString(new_entry, key_des, map_key.GetStringValue());
382 break;
383 case FieldDescriptor::CPPTYPE_INT64:
384 reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
385 break;
386 case FieldDescriptor::CPPTYPE_INT32:
387 reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
388 break;
389 case FieldDescriptor::CPPTYPE_UINT64:
390 reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
391 break;
392 case FieldDescriptor::CPPTYPE_UINT32:
393 reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
394 break;
395 case FieldDescriptor::CPPTYPE_BOOL:
396 reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
397 break;
398 case FieldDescriptor::CPPTYPE_DOUBLE:
399 case FieldDescriptor::CPPTYPE_FLOAT:
400 case FieldDescriptor::CPPTYPE_ENUM:
401 case FieldDescriptor::CPPTYPE_MESSAGE:
402 GOOGLE_LOG(FATAL) << "Can't get here.";
403 break;
404 }
405 const MapValueRef& map_val = it->second;
406 switch (val_des->cpp_type()) {
407 case FieldDescriptor::CPPTYPE_STRING:
408 reflection->SetString(new_entry, val_des, map_val.GetStringValue());
409 break;
410 case FieldDescriptor::CPPTYPE_INT64:
411 reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
412 break;
413 case FieldDescriptor::CPPTYPE_INT32:
414 reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
415 break;
416 case FieldDescriptor::CPPTYPE_UINT64:
417 reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
418 break;
419 case FieldDescriptor::CPPTYPE_UINT32:
420 reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
421 break;
422 case FieldDescriptor::CPPTYPE_BOOL:
423 reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
424 break;
425 case FieldDescriptor::CPPTYPE_DOUBLE:
426 reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
427 break;
428 case FieldDescriptor::CPPTYPE_FLOAT:
429 reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
430 break;
431 case FieldDescriptor::CPPTYPE_ENUM:
432 reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
433 break;
434 case FieldDescriptor::CPPTYPE_MESSAGE: {
435 const Message& message = map_val.GetMessageValue();
436 reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
437 break;
438 }
439 }
440 }
441 }
442
SyncMapWithRepeatedFieldNoLock() const443 void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
444 Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
445 const Reflection* reflection = default_entry_->GetReflection();
446 const FieldDescriptor* key_des =
447 default_entry_->GetDescriptor()->FindFieldByName("key");
448 const FieldDescriptor* val_des =
449 default_entry_->GetDescriptor()->FindFieldByName("value");
450 // DynamicMapField owns map values. Need to delete them before clearing
451 // the map.
452 for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
453 iter != map->end(); ++iter) {
454 iter->second.DeleteData();
455 }
456 map->clear();
457 for (RepeatedPtrField<Message>::iterator it =
458 MapFieldBase::repeated_field_->begin();
459 it != MapFieldBase::repeated_field_->end(); ++it) {
460 MapKey map_key;
461 switch (key_des->cpp_type()) {
462 case FieldDescriptor::CPPTYPE_STRING:
463 map_key.SetStringValue(reflection->GetString(*it, key_des));
464 break;
465 case FieldDescriptor::CPPTYPE_INT64:
466 map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
467 break;
468 case FieldDescriptor::CPPTYPE_INT32:
469 map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
470 break;
471 case FieldDescriptor::CPPTYPE_UINT64:
472 map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
473 break;
474 case FieldDescriptor::CPPTYPE_UINT32:
475 map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
476 break;
477 case FieldDescriptor::CPPTYPE_BOOL:
478 map_key.SetBoolValue(reflection->GetBool(*it, key_des));
479 break;
480 case FieldDescriptor::CPPTYPE_DOUBLE:
481 case FieldDescriptor::CPPTYPE_FLOAT:
482 case FieldDescriptor::CPPTYPE_ENUM:
483 case FieldDescriptor::CPPTYPE_MESSAGE:
484 GOOGLE_LOG(FATAL) << "Can't get here.";
485 break;
486 }
487
488 // Remove existing map value with same key.
489 Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
490 if (iter != map->end()) {
491 iter->second.DeleteData();
492 }
493
494 MapValueRef& map_val = (*map)[map_key];
495 map_val.SetType(val_des->cpp_type());
496 switch (val_des->cpp_type()) {
497 #define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \
498 case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
499 TYPE* value = new TYPE; \
500 *value = reflection->Get##METHOD(*it, val_des); \
501 map_val.SetValue(value); \
502 break; \
503 }
504 HANDLE_TYPE(INT32, int32, Int32);
505 HANDLE_TYPE(INT64, int64, Int64);
506 HANDLE_TYPE(UINT32, uint32, UInt32);
507 HANDLE_TYPE(UINT64, uint64, UInt64);
508 HANDLE_TYPE(DOUBLE, double, Double);
509 HANDLE_TYPE(FLOAT, float, Float);
510 HANDLE_TYPE(BOOL, bool, Bool);
511 HANDLE_TYPE(STRING, std::string, String);
512 HANDLE_TYPE(ENUM, int32, EnumValue);
513 #undef HANDLE_TYPE
514 case FieldDescriptor::CPPTYPE_MESSAGE: {
515 const Message& message = reflection->GetMessage(*it, val_des);
516 Message* value = message.New();
517 value->CopyFrom(message);
518 map_val.SetValue(value);
519 break;
520 }
521 }
522 }
523 }
524
SpaceUsedExcludingSelfNoLock() const525 size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
526 size_t size = 0;
527 if (MapFieldBase::repeated_field_ != NULL) {
528 size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong();
529 }
530 size += sizeof(map_);
531 size_t map_size = map_.size();
532 if (map_size) {
533 Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
534 size += sizeof(it->first) * map_size;
535 size += sizeof(it->second) * map_size;
536 // If key is string, add the allocated space.
537 if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) {
538 size += sizeof(std::string) * map_size;
539 }
540 // Add the allocated space in MapValueRef.
541 switch (it->second.type()) {
542 #define HANDLE_TYPE(CPPTYPE, TYPE) \
543 case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
544 size += sizeof(TYPE) * map_size; \
545 break; \
546 }
547 HANDLE_TYPE(INT32, int32);
548 HANDLE_TYPE(INT64, int64);
549 HANDLE_TYPE(UINT32, uint32);
550 HANDLE_TYPE(UINT64, uint64);
551 HANDLE_TYPE(DOUBLE, double);
552 HANDLE_TYPE(FLOAT, float);
553 HANDLE_TYPE(BOOL, bool);
554 HANDLE_TYPE(STRING, std::string);
555 HANDLE_TYPE(ENUM, int32);
556 #undef HANDLE_TYPE
557 case FieldDescriptor::CPPTYPE_MESSAGE: {
558 while (it != map_.end()) {
559 const Message& message = it->second.GetMessageValue();
560 size += message.GetReflection()->SpaceUsedLong(message);
561 ++it;
562 }
563 break;
564 }
565 }
566 }
567 return size;
568 }
569
570 } // namespace internal
571 } // namespace protobuf
572 } // namespace google
573