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
40namespace google {
41namespace protobuf {
42namespace internal {
43
44void MapFieldBase::Destruct() {
45 if (arena_ == nullptr) {
46 delete repeated_field_;
47 }
48 repeated_field_ = nullptr;
49}
50
51const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
52 ConstAccess();
53 SyncRepeatedFieldWithMap();
54 return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
55}
56
57RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
58 MutableAccess();
59 SyncRepeatedFieldWithMap();
60 SetRepeatedDirty();
61 return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
62}
63
64void MapFieldBase::SwapState(MapFieldBase* other) {
65 // a relaxed swap of the atomic
66 auto other_state = other->state_.load(m: std::memory_order_relaxed);
67 auto this_state = state_.load(m: std::memory_order_relaxed);
68 other->state_.store(i: this_state, m: std::memory_order_relaxed);
69 state_.store(i: other_state, m: std::memory_order_relaxed);
70}
71
72void 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> >(arena: to_arena);
78 **to = std::move(**from);
79 if (from_arena == nullptr) {
80 delete *from;
81 }
82 *from = nullptr;
83}
84
85void 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(from: &other->repeated_field_, to: &repeated_field_,
93 from_arena: other->arena_, to_arena: arena_);
94 } else if (other->repeated_field_ == nullptr) {
95 SwapRepeatedPtrToNull(from: &repeated_field_, to: &other->repeated_field_, from_arena: arena_,
96 to_arena: other->arena_);
97 } else {
98 repeated_field_->Swap(other: other->repeated_field_);
99 }
100 }
101 SwapState(other);
102}
103
104void MapFieldBase::UnsafeShallowSwap(MapFieldBase* other) {
105 GOOGLE_DCHECK_EQ(arena_, other->arena_);
106 InternalSwap(other);
107}
108
109void MapFieldBase::InternalSwap(MapFieldBase* other) {
110 std::swap(a&: arena_, b&: other->arena_);
111 std::swap(a&: repeated_field_, b&: other->repeated_field_);
112 SwapState(other);
113}
114
115size_t MapFieldBase::SpaceUsedExcludingSelfLong() const {
116 ConstAccess();
117 mutex_.Lock();
118 size_t size = SpaceUsedExcludingSelfNoLock();
119 mutex_.Unlock();
120 ConstAccess();
121 return size;
122}
123
124size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
125 if (repeated_field_ != nullptr) {
126 return repeated_field_->SpaceUsedExcludingSelfLong();
127 } else {
128 return 0;
129 }
130}
131
132bool 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(m: std::memory_order_acquire);
137 return state != STATE_MODIFIED_REPEATED;
138}
139
140bool MapFieldBase::IsRepeatedFieldValid() const {
141 ConstAccess();
142 int state = state_.load(m: std::memory_order_acquire);
143 return state != STATE_MODIFIED_MAP;
144}
145
146void 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(i: STATE_MODIFIED_MAP, m: std::memory_order_relaxed);
151}
152
153void 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(i: STATE_MODIFIED_REPEATED, m: std::memory_order_relaxed);
158}
159
160void 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(m: 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(m: std::memory_order_relaxed) == STATE_MODIFIED_MAP) {
170 SyncRepeatedFieldWithMapNoLock();
171 state_.store(i: CLEAN, m: 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(m: std::memory_order_relaxed) == CLEAN) {
180 if (repeated_field_ == nullptr) {
181 repeated_field_ =
182 Arena::CreateMessage<RepeatedPtrField<Message> >(arena: arena_);
183 }
184 state_.store(i: CLEAN, m: std::memory_order_release);
185 }
186 mutex_.Unlock();
187 ConstAccess();
188 break;
189 default:
190 break;
191 }
192}
193
194void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
195 if (repeated_field_ == nullptr) {
196 repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena: arena_);
197 }
198}
199
200void 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(m: 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(m: std::memory_order_relaxed) == STATE_MODIFIED_REPEATED) {
209 SyncMapWithRepeatedFieldNoLock();
210 state_.store(i: CLEAN, m: std::memory_order_release);
211 }
212 mutex_.Unlock();
213 ConstAccess();
214 }
215}
216
217// ------------------DynamicMapField------------------
218DynamicMapField::DynamicMapField(const Message* default_entry)
219 : default_entry_(default_entry) {}
220
221DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena)
222 : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
223 map_(arena),
224 default_entry_(default_entry) {}
225
226DynamicMapField::~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
238int DynamicMapField::size() const { return GetMap().size(); }
239
240void 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
259bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const {
260 const Map<MapKey, MapValueRef>& map = GetMap();
261 Map<MapKey, MapValueRef>::const_iterator iter = map.find(key: map_key);
262 return iter != map.end();
263}
264
265void 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(message: *default_entry_, field: val_des);
290 Message* value = message.New(arena: MapFieldBase::arena_);
291 map_val->SetValue(value);
292 break;
293 }
294 }
295}
296
297bool 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(key: map_key);
303 if (iter == map->end()) {
304 MapValueRef& map_val = map_[map_key];
305 AllocateMapValue(map_val: &map_val);
306 val->CopyFrom(other: 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(other: iter->second);
312 return false;
313}
314
315bool 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(key: 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(other: iter->second);
325 return true;
326}
327
328bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
329 MapFieldBase::SyncMapWithRepeatedField();
330 Map<MapKey, MapValueRef>::iterator iter = map_.find(key: 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(pos: iter);
340 return true;
341}
342
343const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
344 MapFieldBase::SyncMapWithRepeatedField();
345 return map_;
346}
347
348Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
349 MapFieldBase::SyncMapWithRepeatedField();
350 MapFieldBase::SetMapDirty();
351 return &map_;
352}
353
354void 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(other: iter->first);
360 map_iter->value_.CopyFrom(other: iter->second);
361}
362
363void 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(key: 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 from: other_it->second.GetMessageValue());
423 break;
424 }
425 }
426 }
427}
428
429void DynamicMapField::Swap(MapFieldBase* other) {
430 DynamicMapField* other_field = down_cast<DynamicMapField*>(f: other);
431 std::swap(a&: this->MapFieldBase::repeated_field_, b&: other_field->repeated_field_);
432 map_.swap(other&: other_field->map_);
433 // a relaxed swap of the atomic
434 auto other_state = other_field->state_.load(m: std::memory_order_relaxed);
435 auto this_state = this->MapFieldBase::state_.load(m: std::memory_order_relaxed);
436 other_field->state_.store(i: this_state, m: std::memory_order_relaxed);
437 this->MapFieldBase::state_.store(i: other_state, m: std::memory_order_relaxed);
438}
439
440void 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> >(arena: 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(arena: MapFieldBase::arena_);
454 MapFieldBase::repeated_field_->AddAllocated(value: new_entry);
455 const MapKey& map_key = it->first;
456 switch (key_des->cpp_type()) {
457 case FieldDescriptor::CPPTYPE_STRING:
458 reflection->SetString(message: new_entry, field: key_des, value: map_key.GetStringValue());
459 break;
460 case FieldDescriptor::CPPTYPE_INT64:
461 reflection->SetInt64(message: new_entry, field: key_des, value: map_key.GetInt64Value());
462 break;
463 case FieldDescriptor::CPPTYPE_INT32:
464 reflection->SetInt32(message: new_entry, field: key_des, value: map_key.GetInt32Value());
465 break;
466 case FieldDescriptor::CPPTYPE_UINT64:
467 reflection->SetUInt64(message: new_entry, field: key_des, value: map_key.GetUInt64Value());
468 break;
469 case FieldDescriptor::CPPTYPE_UINT32:
470 reflection->SetUInt32(message: new_entry, field: key_des, value: map_key.GetUInt32Value());
471 break;
472 case FieldDescriptor::CPPTYPE_BOOL:
473 reflection->SetBool(message: new_entry, field: key_des, value: 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(message: new_entry, field: val_des, value: map_val.GetStringValue());
486 break;
487 case FieldDescriptor::CPPTYPE_INT64:
488 reflection->SetInt64(message: new_entry, field: val_des, value: map_val.GetInt64Value());
489 break;
490 case FieldDescriptor::CPPTYPE_INT32:
491 reflection->SetInt32(message: new_entry, field: val_des, value: map_val.GetInt32Value());
492 break;
493 case FieldDescriptor::CPPTYPE_UINT64:
494 reflection->SetUInt64(message: new_entry, field: val_des, value: map_val.GetUInt64Value());
495 break;
496 case FieldDescriptor::CPPTYPE_UINT32:
497 reflection->SetUInt32(message: new_entry, field: val_des, value: map_val.GetUInt32Value());
498 break;
499 case FieldDescriptor::CPPTYPE_BOOL:
500 reflection->SetBool(message: new_entry, field: val_des, value: map_val.GetBoolValue());
501 break;
502 case FieldDescriptor::CPPTYPE_DOUBLE:
503 reflection->SetDouble(message: new_entry, field: val_des, value: map_val.GetDoubleValue());
504 break;
505 case FieldDescriptor::CPPTYPE_FLOAT:
506 reflection->SetFloat(message: new_entry, field: val_des, value: map_val.GetFloatValue());
507 break;
508 case FieldDescriptor::CPPTYPE_ENUM:
509 reflection->SetEnumValue(message: new_entry, field: val_des, value: map_val.GetEnumValue());
510 break;
511 case FieldDescriptor::CPPTYPE_MESSAGE: {
512 const Message& message = map_val.GetMessageValue();
513 reflection->MutableMessage(message: new_entry, field: val_des)->CopyFrom(from: message);
514 break;
515 }
516 }
517 }
518}
519
520void 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(message: *it, field: key_des));
542 break;
543 case FieldDescriptor::CPPTYPE_INT64:
544 map_key.SetInt64Value(reflection->GetInt64(message: *it, field: key_des));
545 break;
546 case FieldDescriptor::CPPTYPE_INT32:
547 map_key.SetInt32Value(reflection->GetInt32(message: *it, field: key_des));
548 break;
549 case FieldDescriptor::CPPTYPE_UINT64:
550 map_key.SetUInt64Value(reflection->GetUInt64(message: *it, field: key_des));
551 break;
552 case FieldDescriptor::CPPTYPE_UINT32:
553 map_key.SetUInt32Value(reflection->GetUInt32(message: *it, field: key_des));
554 break;
555 case FieldDescriptor::CPPTYPE_BOOL:
556 map_key.SetBoolValue(reflection->GetBool(message: *it, field: 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(key: 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(message: *it, field: val_des);
596 Message* value = message.New(arena: MapFieldBase::arena_);
597 value->CopyFrom(from: message);
598 map_val.SetValue(value);
599 break;
600 }
601 }
602 }
603}
604
605size_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