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 | |
44 | void MapFieldBase::Destruct() { |
45 | if (arena_ == nullptr) { |
46 | delete repeated_field_; |
47 | } |
48 | repeated_field_ = nullptr; |
49 | } |
50 | |
51 | const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { |
52 | ConstAccess(); |
53 | SyncRepeatedFieldWithMap(); |
54 | return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); |
55 | } |
56 | |
57 | RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { |
58 | MutableAccess(); |
59 | SyncRepeatedFieldWithMap(); |
60 | SetRepeatedDirty(); |
61 | return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); |
62 | } |
63 | |
64 | void 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 | |
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> >(arena: to_arena); |
78 | **to = std::move(**from); |
79 | if (from_arena == nullptr) { |
80 | delete *from; |
81 | } |
82 | *from = nullptr; |
83 | } |
84 | |
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(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 | |
104 | void MapFieldBase::UnsafeShallowSwap(MapFieldBase* other) { |
105 | GOOGLE_DCHECK_EQ(arena_, other->arena_); |
106 | InternalSwap(other); |
107 | } |
108 | |
109 | void 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 | |
115 | 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 | |
124 | size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const { |
125 | if (repeated_field_ != nullptr) { |
126 | return repeated_field_->SpaceUsedExcludingSelfLong(); |
127 | } else { |
128 | return 0; |
129 | } |
130 | } |
131 | |
132 | 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(m: std::memory_order_acquire); |
137 | return state != STATE_MODIFIED_REPEATED; |
138 | } |
139 | |
140 | bool MapFieldBase::IsRepeatedFieldValid() const { |
141 | ConstAccess(); |
142 | int state = state_.load(m: std::memory_order_acquire); |
143 | return state != STATE_MODIFIED_MAP; |
144 | } |
145 | |
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(i: STATE_MODIFIED_MAP, m: std::memory_order_relaxed); |
151 | } |
152 | |
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(i: STATE_MODIFIED_REPEATED, m: std::memory_order_relaxed); |
158 | } |
159 | |
160 | 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(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 | |
194 | void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { |
195 | if (repeated_field_ == nullptr) { |
196 | repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena: arena_); |
197 | } |
198 | } |
199 | |
200 | 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(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------------------ |
218 | DynamicMapField::DynamicMapField(const Message* default_entry) |
219 | : default_entry_(default_entry) {} |
220 | |
221 | DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) |
222 | : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena), |
223 | map_(arena), |
224 | default_entry_(default_entry) {} |
225 | |
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 | |
238 | int DynamicMapField::size() const { return GetMap().size(); } |
239 | |
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 | |
259 | bool 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 | |
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(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 | |
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(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 | |
315 | 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(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 | |
328 | bool 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 | |
343 | const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const { |
344 | MapFieldBase::SyncMapWithRepeatedField(); |
345 | return map_; |
346 | } |
347 | |
348 | Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() { |
349 | MapFieldBase::SyncMapWithRepeatedField(); |
350 | MapFieldBase::SetMapDirty(); |
351 | return &map_; |
352 | } |
353 | |
354 | 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(other: iter->first); |
360 | map_iter->value_.CopyFrom(other: iter->second); |
361 | } |
362 | |
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(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 | |
429 | void 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 | |
440 | 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> >(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 | |
520 | 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(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 | |
605 | 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 | |