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