Line data Source code
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 : namespace google {
37 : namespace protobuf {
38 : namespace internal {
39 :
40 : ProtobufOnceType map_entry_default_instances_once_;
41 : Mutex* map_entry_default_instances_mutex_;
42 : vector<MessageLite*>* map_entry_default_instances_;
43 :
44 0 : void DeleteMapEntryDefaultInstances() {
45 0 : for (int i = 0; i < map_entry_default_instances_->size(); ++i) {
46 0 : delete map_entry_default_instances_->at(i);
47 : }
48 0 : delete map_entry_default_instances_mutex_;
49 0 : delete map_entry_default_instances_;
50 0 : }
51 :
52 0 : void InitMapEntryDefaultInstances() {
53 0 : map_entry_default_instances_mutex_ = new Mutex();
54 0 : map_entry_default_instances_ = new vector<MessageLite*>();
55 0 : OnShutdown(&DeleteMapEntryDefaultInstances);
56 0 : }
57 :
58 0 : void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
59 : ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
60 0 : &InitMapEntryDefaultInstances);
61 0 : MutexLock lock(map_entry_default_instances_mutex_);
62 0 : map_entry_default_instances_->push_back(default_instance);
63 0 : }
64 :
65 0 : MapFieldBase::~MapFieldBase() {
66 0 : if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
67 0 : }
68 :
69 0 : const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
70 0 : SyncRepeatedFieldWithMap();
71 0 : return *repeated_field_;
72 : }
73 :
74 0 : RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
75 0 : SyncRepeatedFieldWithMap();
76 0 : SetRepeatedDirty();
77 0 : return repeated_field_;
78 : }
79 :
80 0 : int MapFieldBase::SpaceUsedExcludingSelf() const {
81 0 : mutex_.Lock();
82 0 : int size = SpaceUsedExcludingSelfNoLock();
83 0 : mutex_.Unlock();
84 0 : return size;
85 : }
86 :
87 0 : int MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
88 0 : if (repeated_field_ != NULL) {
89 0 : return repeated_field_->SpaceUsedExcludingSelf();
90 : } else {
91 : return 0;
92 : }
93 : }
94 :
95 0 : void MapFieldBase::InitMetadataOnce() const {
96 0 : GOOGLE_CHECK(entry_descriptor_ != NULL);
97 0 : GOOGLE_CHECK(assign_descriptor_callback_ != NULL);
98 0 : (*assign_descriptor_callback_)();
99 0 : }
100 :
101 0 : void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
102 :
103 0 : void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
104 :
105 0 : void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
106 :
107 0 : void MapFieldBase::SyncRepeatedFieldWithMap() const {
108 : // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
109 : // executed before state_ is checked.
110 0 : Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
111 0 : if (state == STATE_MODIFIED_MAP) {
112 0 : mutex_.Lock();
113 : // Double check state, because another thread may have seen the same state
114 : // and done the synchronization before the current thread.
115 0 : if (state_ == STATE_MODIFIED_MAP) {
116 0 : SyncRepeatedFieldWithMapNoLock();
117 : // "Release" insures state_ can only be changed "after"
118 : // SyncRepeatedFieldWithMapNoLock is finished.
119 0 : google::protobuf::internal::Release_Store(&state_, CLEAN);
120 : }
121 0 : mutex_.Unlock();
122 : }
123 0 : }
124 :
125 0 : void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
126 0 : if (repeated_field_ == NULL) {
127 0 : repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
128 : }
129 0 : }
130 :
131 0 : void MapFieldBase::SyncMapWithRepeatedField() const {
132 : // "Acquire" insures the operation after SyncMapWithRepeatedField won't get
133 : // executed before state_ is checked.
134 0 : Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
135 0 : if (state == STATE_MODIFIED_REPEATED) {
136 0 : mutex_.Lock();
137 : // Double check state, because another thread may have seen the same state
138 : // and done the synchronization before the current thread.
139 0 : if (state_ == STATE_MODIFIED_REPEATED) {
140 0 : SyncMapWithRepeatedFieldNoLock();
141 : // "Release" insures state_ can only be changed "after"
142 : // SyncRepeatedFieldWithMapNoLock is finished.
143 0 : google::protobuf::internal::Release_Store(&state_, CLEAN);
144 : }
145 0 : mutex_.Unlock();
146 : }
147 0 : }
148 :
149 : // ------------------DynamicMapField------------------
150 0 : DynamicMapField::DynamicMapField(const Message* default_entry)
151 0 : : default_entry_(default_entry) {
152 0 : }
153 :
154 0 : DynamicMapField::DynamicMapField(const Message* default_entry,
155 : Arena* arena)
156 : : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
157 0 : default_entry_(default_entry) {
158 0 : }
159 :
160 0 : DynamicMapField::~DynamicMapField() {
161 : // DynamicMapField owns map values. Need to delete them before clearing
162 : // the map.
163 0 : for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
164 0 : iter != map_.end(); ++iter) {
165 0 : iter->second.DeleteData();
166 : }
167 0 : map_.clear();
168 0 : }
169 :
170 0 : int DynamicMapField::size() const {
171 0 : return GetMap().size();
172 : }
173 :
174 0 : bool DynamicMapField::ContainsMapKey(
175 : const MapKey& map_key) const {
176 0 : const Map<MapKey, MapValueRef>& map = GetMap();
177 0 : Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
178 0 : return iter != map.end();
179 : }
180 :
181 0 : bool DynamicMapField::InsertMapValue(
182 : const MapKey& map_key, MapValueRef* val) {
183 0 : bool result = false;
184 :
185 0 : MapValueRef& map_val = (*MutableMap())[map_key];
186 : // If map_val.data_ is not set, it is newly inserted by map_[map_key].
187 0 : if (map_val.data_ == NULL) {
188 0 : result = true;
189 0 : const FieldDescriptor* val_des =
190 0 : default_entry_->GetDescriptor()->FindFieldByName("value");
191 0 : map_val.SetType(val_des->cpp_type());
192 : // Allocate momery for the inserted MapValueRef, and initialize to
193 : // default value.
194 0 : switch (val_des->cpp_type()) {
195 : #define HANDLE_TYPE(CPPTYPE, TYPE) \
196 : case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
197 : TYPE * value = new TYPE(); \
198 : map_val.SetValue(value); \
199 : break; \
200 : }
201 0 : HANDLE_TYPE(INT32, int32);
202 0 : HANDLE_TYPE(INT64, int64);
203 0 : HANDLE_TYPE(UINT32, uint32);
204 0 : HANDLE_TYPE(UINT64, uint64);
205 0 : HANDLE_TYPE(DOUBLE, double);
206 0 : HANDLE_TYPE(FLOAT, float);
207 0 : HANDLE_TYPE(BOOL, bool);
208 0 : HANDLE_TYPE(STRING, string);
209 0 : HANDLE_TYPE(ENUM, int32);
210 : #undef HANDLE_TYPE
211 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
212 0 : const Message& message = default_entry_->GetReflection()->GetMessage(
213 0 : *default_entry_, val_des);
214 0 : Message* value = message.New();
215 0 : map_val.SetValue(value);
216 : break;
217 : }
218 : }
219 : }
220 0 : val->CopyFrom(map_val);
221 0 : return result;
222 : }
223 :
224 0 : bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
225 0 : MapFieldBase::SyncMapWithRepeatedField();
226 0 : Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
227 0 : if (iter == map_.end()) {
228 : return false;
229 : }
230 : // Set map dirty only if the delete is successful.
231 0 : MapFieldBase::SetMapDirty();
232 0 : iter->second.DeleteData();
233 0 : map_.erase(iter);
234 0 : return true;
235 : }
236 :
237 0 : const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
238 0 : MapFieldBase::SyncMapWithRepeatedField();
239 0 : return map_;
240 : }
241 :
242 0 : Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
243 0 : MapFieldBase::SyncMapWithRepeatedField();
244 0 : MapFieldBase::SetMapDirty();
245 0 : return &map_;
246 : }
247 :
248 0 : void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
249 : Map<MapKey, MapValueRef>::const_iterator iter =
250 : TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
251 0 : map_iter);
252 0 : if (iter == map_.end()) return;
253 0 : map_iter->key_.CopyFrom(iter->first);
254 0 : map_iter->value_.CopyFrom(iter->second);
255 : }
256 :
257 0 : void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
258 0 : const Reflection* reflection = default_entry_->GetReflection();
259 0 : const FieldDescriptor* key_des =
260 0 : default_entry_->GetDescriptor()->FindFieldByName("key");
261 0 : const FieldDescriptor* val_des =
262 0 : default_entry_->GetDescriptor()->FindFieldByName("value");
263 0 : if (MapFieldBase::repeated_field_ == NULL) {
264 0 : if (MapFieldBase::arena_ == NULL) {
265 0 : MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
266 : } else {
267 : MapFieldBase::repeated_field_ =
268 : Arena::CreateMessage<RepeatedPtrField<Message> >(
269 0 : MapFieldBase::arena_);
270 : }
271 : }
272 :
273 0 : MapFieldBase::repeated_field_->Clear();
274 :
275 0 : for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
276 0 : it != map_.end(); ++it) {
277 0 : Message* new_entry = default_entry_->New();
278 0 : MapFieldBase::repeated_field_->AddAllocated(new_entry);
279 0 : const MapKey& map_key = it->first;
280 0 : switch (key_des->cpp_type()) {
281 : case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
282 0 : reflection->SetString(new_entry, key_des, map_key.GetStringValue());
283 : break;
284 : case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
285 0 : reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
286 : break;
287 : case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
288 0 : reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
289 : break;
290 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
291 0 : reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
292 : break;
293 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
294 0 : reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
295 : break;
296 : case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
297 0 : reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
298 : break;
299 : case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
300 : case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
301 : case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
302 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
303 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
304 0 : break;
305 : }
306 0 : const MapValueRef& map_val = it->second;
307 0 : switch (val_des->cpp_type()) {
308 : case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
309 0 : reflection->SetString(new_entry, val_des, map_val.GetStringValue());
310 : break;
311 : case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
312 0 : reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
313 : break;
314 : case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
315 0 : reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
316 : break;
317 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
318 0 : reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
319 : break;
320 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
321 0 : reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
322 : break;
323 : case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
324 0 : reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
325 : break;
326 : case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
327 0 : reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
328 : break;
329 : case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
330 0 : reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
331 : break;
332 : case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
333 0 : reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
334 : break;
335 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
336 0 : const Message& message = map_val.GetMessageValue();
337 0 : reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
338 : break;
339 : }
340 : }
341 : }
342 0 : }
343 :
344 0 : void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
345 0 : Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
346 0 : const Reflection* reflection = default_entry_->GetReflection();
347 0 : const FieldDescriptor* key_des =
348 0 : default_entry_->GetDescriptor()->FindFieldByName("key");
349 0 : const FieldDescriptor* val_des =
350 0 : default_entry_->GetDescriptor()->FindFieldByName("value");
351 : // DynamicMapField owns map values. Need to delete them before clearing
352 : // the map.
353 0 : for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
354 0 : iter != map->end(); ++iter) {
355 0 : iter->second.DeleteData();
356 : }
357 0 : map->clear();
358 0 : for (RepeatedPtrField<Message>::iterator it =
359 0 : MapFieldBase::repeated_field_->begin();
360 0 : it != MapFieldBase::repeated_field_->end(); ++it) {
361 : MapKey map_key;
362 0 : switch (key_des->cpp_type()) {
363 : case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
364 0 : map_key.SetStringValue(reflection->GetString(*it, key_des));
365 0 : break;
366 : case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
367 0 : map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
368 : break;
369 : case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
370 0 : map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
371 : break;
372 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
373 0 : map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
374 : break;
375 : case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
376 0 : map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
377 : break;
378 : case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
379 0 : map_key.SetBoolValue(reflection->GetBool(*it, key_des));
380 : break;
381 : case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
382 : case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
383 : case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
384 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
385 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
386 0 : break;
387 : }
388 0 : MapValueRef& map_val = (*map)[map_key];
389 0 : map_val.SetType(val_des->cpp_type());
390 0 : switch (val_des->cpp_type()) {
391 : #define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \
392 : case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
393 : TYPE * value = new TYPE; \
394 : *value = reflection->Get##METHOD(*it, val_des); \
395 : map_val.SetValue(value); \
396 : break; \
397 : }
398 0 : HANDLE_TYPE(INT32, int32, Int32);
399 0 : HANDLE_TYPE(INT64, int64, Int64);
400 0 : HANDLE_TYPE(UINT32, uint32, UInt32);
401 0 : HANDLE_TYPE(UINT64, uint64, UInt64);
402 0 : HANDLE_TYPE(DOUBLE, double, Double);
403 0 : HANDLE_TYPE(FLOAT, float, Float);
404 0 : HANDLE_TYPE(BOOL, bool, Bool);
405 0 : HANDLE_TYPE(STRING, string, String);
406 0 : HANDLE_TYPE(ENUM, int32, EnumValue);
407 : #undef HANDLE_TYPE
408 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
409 0 : const Message& message = reflection->GetMessage(*it, val_des);
410 0 : Message* value = message.New();
411 0 : value->CopyFrom(message);
412 0 : map_val.SetValue(value);
413 : break;
414 : }
415 : }
416 0 : }
417 0 : }
418 :
419 0 : int DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
420 0 : int size = 0;
421 0 : if (MapFieldBase::repeated_field_ != NULL) {
422 0 : size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
423 : }
424 0 : size += sizeof(map_);
425 0 : int map_size = map_.size();
426 0 : if (map_size) {
427 0 : Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
428 0 : size += sizeof(it->first) * map_size;
429 0 : size += sizeof(it->second) * map_size;
430 : // If key is string, add the allocated space.
431 0 : if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
432 0 : size += sizeof(string) * map_size;
433 : }
434 : // Add the allocated space in MapValueRef.
435 0 : switch (it->second.type()) {
436 : #define HANDLE_TYPE(CPPTYPE, TYPE) \
437 : case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
438 : size += sizeof(TYPE) * map_size; \
439 : break; \
440 : }
441 0 : HANDLE_TYPE(INT32, int32);
442 0 : HANDLE_TYPE(INT64, int64);
443 0 : HANDLE_TYPE(UINT32, uint32);
444 0 : HANDLE_TYPE(UINT64, uint64);
445 0 : HANDLE_TYPE(DOUBLE, double);
446 0 : HANDLE_TYPE(FLOAT, float);
447 0 : HANDLE_TYPE(BOOL, bool);
448 0 : HANDLE_TYPE(STRING, string);
449 0 : HANDLE_TYPE(ENUM, int32);
450 : #undef HANDLE_TYPE
451 : case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
452 0 : while (it != map_.end()) {
453 0 : const Message& message = it->second.GetMessageValue();
454 0 : size += message.GetReflection()->SpaceUsed(message);
455 : ++it;
456 : }
457 : break;
458 : }
459 : }
460 : }
461 0 : return size;
462 : }
463 :
464 : } // namespace internal
465 : } // namespace protobuf
466 : } // namespace google
|