Home | History | Annotate | Download | only in protobuf
      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