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