diff options
Diffstat (limited to 'NorthstarDedicatedTest/include/protobuf/map_field.cc')
-rw-r--r-- | NorthstarDedicatedTest/include/protobuf/map_field.cc | 647 |
1 files changed, 647 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/include/protobuf/map_field.cc b/NorthstarDedicatedTest/include/protobuf/map_field.cc new file mode 100644 index 00000000..74a486e5 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/map_field.cc @@ -0,0 +1,647 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map_field.h> +#include <map_field_inl.h> + +#include <vector> + +#include <port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +MapFieldBase::~MapFieldBase() { + if (repeated_field_ != nullptr && arena_ == nullptr) delete repeated_field_; +} + +const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { + ConstAccess(); + SyncRepeatedFieldWithMap(); + return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); +} + +RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { + MutableAccess(); + SyncRepeatedFieldWithMap(); + SetRepeatedDirty(); + return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); +} + +void MapFieldBase::SwapState(MapFieldBase* other) { + // a relaxed swap of the atomic + auto other_state = other->state_.load(std::memory_order_relaxed); + auto this_state = state_.load(std::memory_order_relaxed); + other->state_.store(this_state, std::memory_order_relaxed); + state_.store(other_state, std::memory_order_relaxed); +} + +void SwapRepeatedPtrToNull(RepeatedPtrField<Message>** from, + RepeatedPtrField<Message>** to, Arena* from_arena, + Arena* to_arena) { + GOOGLE_DCHECK(*from != nullptr); + GOOGLE_DCHECK(*to == nullptr); + *to = Arena::CreateMessage<RepeatedPtrField<Message> >(to_arena); + **to = std::move(**from); + if (from_arena == nullptr) { + delete *from; + } + *from = nullptr; +} + +void MapFieldBase::Swap(MapFieldBase* other) { + if (arena_ == other->arena_) { + InternalSwap(other); + return; + } + if (repeated_field_ != nullptr || other->repeated_field_ != nullptr) { + if (repeated_field_ == nullptr) { + SwapRepeatedPtrToNull(&other->repeated_field_, &repeated_field_, + other->arena_, arena_); + } else if (other->repeated_field_ == nullptr) { + SwapRepeatedPtrToNull(&repeated_field_, &other->repeated_field_, arena_, + other->arena_); + } else { + repeated_field_->Swap(other->repeated_field_); + } + } + SwapState(other); +} + +void MapFieldBase::UnsafeShallowSwap(MapFieldBase* other) { + GOOGLE_DCHECK_EQ(arena_, other->arena_); + InternalSwap(other); +} + +void MapFieldBase::InternalSwap(MapFieldBase* other) { + std::swap(arena_, other->arena_); + std::swap(repeated_field_, other->repeated_field_); + SwapState(other); +} + +size_t MapFieldBase::SpaceUsedExcludingSelfLong() const { + ConstAccess(); + mutex_.Lock(); + size_t size = SpaceUsedExcludingSelfNoLock(); + mutex_.Unlock(); + ConstAccess(); + return size; +} + +size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const { + if (repeated_field_ != nullptr) { + return repeated_field_->SpaceUsedExcludingSelfLong(); + } else { + return 0; + } +} + +bool MapFieldBase::IsMapValid() const { + ConstAccess(); + // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get + // executed before state_ is checked. + int state = state_.load(std::memory_order_acquire); + return state != STATE_MODIFIED_REPEATED; +} + +bool MapFieldBase::IsRepeatedFieldValid() const { + ConstAccess(); + int state = state_.load(std::memory_order_acquire); + return state != STATE_MODIFIED_MAP; +} + +void MapFieldBase::SetMapDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); +} + +void MapFieldBase::SetRepeatedDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed); +} + +void MapFieldBase::SyncRepeatedFieldWithMap() const { + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + switch (state_.load(std::memory_order_acquire)) { + case STATE_MODIFIED_MAP: + mutex_.Lock(); + // Double check state, because another thread may have seen the same + // state and done the synchronization before the current thread. + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) { + SyncRepeatedFieldWithMapNoLock(); + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + case CLEAN: + mutex_.Lock(); + // Double check state + if (state_.load(std::memory_order_relaxed) == CLEAN) { + if (repeated_field_ == nullptr) { + repeated_field_ = + Arena::CreateMessage<RepeatedPtrField<Message> >(arena_); + } + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + default: + break; + } +} + +void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { + if (repeated_field_ == nullptr) { + repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_); + } +} + +void MapFieldBase::SyncMapWithRepeatedField() const { + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) { + mutex_.Lock(); + // Double check state, because another thread may have seen the same state + // and done the synchronization before the current thread. + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_REPEATED) { + SyncMapWithRepeatedFieldNoLock(); + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + } +} + +// ------------------DynamicMapField------------------ +DynamicMapField::DynamicMapField(const Message* default_entry) + : default_entry_(default_entry) {} + +DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) + : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena), + map_(arena), + default_entry_(default_entry) {} + +DynamicMapField::~DynamicMapField() { + if (arena_ != nullptr) return; + // DynamicMapField owns map values. Need to delete them before clearing the + // map. + for (auto& kv : map_) { + kv.second.DeleteData(); + } + map_.clear(); +} + +int DynamicMapField::size() const { return GetMap().size(); } + +void DynamicMapField::Clear() { + Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_; + if (MapFieldBase::arena_ == nullptr) { + for (Map<MapKey, MapValueRef>::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + } + + map->clear(); + + if (MapFieldBase::repeated_field_ != nullptr) { + MapFieldBase::repeated_field_->Clear(); + } + // Data in map and repeated field are both empty, but we can't set status + // CLEAN which will invalidate previous reference to map. + MapFieldBase::SetMapDirty(); +} + +bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const { + const Map<MapKey, MapValueRef>& map = GetMap(); + Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key); + return iter != map.end(); +} + +void DynamicMapField::AllocateMapValue(MapValueRef* map_val) { + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + map_val->SetType(val_des->cpp_type()); + // Allocate memory for the MapValueRef, and initialize to + // default value. + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \ + map_val->SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = + default_entry_->GetReflection()->GetMessage(*default_entry_, val_des); + Message* value = message.New(MapFieldBase::arena_); + map_val->SetValue(value); + break; + } + } +} + +bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { + // Always use mutable map because users may change the map value by + // MapValueRef. + Map<MapKey, MapValueRef>* map = MutableMap(); + Map<MapKey, MapValueRef>::iterator iter = map->find(map_key); + if (iter == map->end()) { + MapValueRef& map_val = map_[map_key]; + AllocateMapValue(&map_val); + val->CopyFrom(map_val); + return true; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return false; +} + +bool DynamicMapField::LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const { + const Map<MapKey, MapValueRef>& map = GetMap(); + Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key); + if (iter == map.end()) { + return false; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return true; +} + +bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { + MapFieldBase::SyncMapWithRepeatedField(); + Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key); + if (iter == map_.end()) { + return false; + } + // Set map dirty only if the delete is successful. + MapFieldBase::SetMapDirty(); + if (MapFieldBase::arena_ == nullptr) { + iter->second.DeleteData(); + } + map_.erase(iter); + return true; +} + +const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const { + MapFieldBase::SyncMapWithRepeatedField(); + return map_; +} + +Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() { + MapFieldBase::SyncMapWithRepeatedField(); + MapFieldBase::SetMapDirty(); + return &map_; +} + +void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const { + Map<MapKey, MapValueRef>::const_iterator iter = + TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator( + map_iter); + if (iter == map_.end()) return; + map_iter->key_.CopyFrom(iter->first); + map_iter->value_.CopyFrom(iter->second); +} + +void DynamicMapField::MergeFrom(const MapFieldBase& other) { + GOOGLE_DCHECK(IsMapValid() && other.IsMapValid()); + Map<MapKey, MapValueRef>* map = MutableMap(); + const DynamicMapField& other_field = + reinterpret_cast<const DynamicMapField&>(other); + for (Map<MapKey, MapValueRef>::const_iterator other_it = + other_field.map_.begin(); + other_it != other_field.map_.end(); ++other_it) { + Map<MapKey, MapValueRef>::iterator iter = map->find(other_it->first); + MapValueRef* map_val; + if (iter == map->end()) { + map_val = &map_[other_it->first]; + AllocateMapValue(map_val); + } else { + map_val = &iter->second; + } + + // Copy map value + const FieldDescriptor* field_descriptor = + default_entry_->GetDescriptor()->map_value(); + switch (field_descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + map_val->SetInt32Value(other_it->second.GetInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_INT64: { + map_val->SetInt64Value(other_it->second.GetInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT32: { + map_val->SetUInt32Value(other_it->second.GetUInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT64: { + map_val->SetUInt64Value(other_it->second.GetUInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_FLOAT: { + map_val->SetFloatValue(other_it->second.GetFloatValue()); + break; + } + case FieldDescriptor::CPPTYPE_DOUBLE: { + map_val->SetDoubleValue(other_it->second.GetDoubleValue()); + break; + } + case FieldDescriptor::CPPTYPE_BOOL: { + map_val->SetBoolValue(other_it->second.GetBoolValue()); + break; + } + case FieldDescriptor::CPPTYPE_STRING: { + map_val->SetStringValue(other_it->second.GetStringValue()); + break; + } + case FieldDescriptor::CPPTYPE_ENUM: { + map_val->SetEnumValue(other_it->second.GetEnumValue()); + break; + } + case FieldDescriptor::CPPTYPE_MESSAGE: { + map_val->MutableMessageValue()->CopyFrom( + other_it->second.GetMessageValue()); + break; + } + } + } +} + +void DynamicMapField::Swap(MapFieldBase* other) { + DynamicMapField* other_field = down_cast<DynamicMapField*>(other); + std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_); + map_.swap(other_field->map_); + // a relaxed swap of the atomic + auto other_state = other_field->state_.load(std::memory_order_relaxed); + auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed); + other_field->state_.store(this_state, std::memory_order_relaxed); + this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed); +} + +void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + if (MapFieldBase::repeated_field_ == nullptr) { + MapFieldBase::repeated_field_ = + Arena::CreateMessage<RepeatedPtrField<Message> >(MapFieldBase::arena_); + } + + MapFieldBase::repeated_field_->Clear(); + + for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin(); + it != map_.end(); ++it) { + Message* new_entry = default_entry_->New(MapFieldBase::arena_); + MapFieldBase::repeated_field_->AddAllocated(new_entry); + const MapKey& map_key = it->first; + switch (key_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, key_des, map_key.GetStringValue()); + break; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value()); + break; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, key_des, map_key.GetBoolValue()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + const MapValueRef& map_val = it->second; + switch (val_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, val_des, map_val.GetStringValue()); + break; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value()); + break; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, val_des, map_val.GetBoolValue()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue()); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue()); + break; + case FieldDescriptor::CPPTYPE_ENUM: + reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue()); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = map_val.GetMessageValue(); + reflection->MutableMessage(new_entry, val_des)->CopyFrom(message); + break; + } + } + } +} + +void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const { + Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_; + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + // DynamicMapField owns map values. Need to delete them before clearing + // the map. + if (MapFieldBase::arena_ == nullptr) { + for (Map<MapKey, MapValueRef>::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + } + map->clear(); + for (RepeatedPtrField<Message>::iterator it = + MapFieldBase::repeated_field_->begin(); + it != MapFieldBase::repeated_field_->end(); ++it) { + // MapKey type will be set later. + MapKey map_key; + switch (key_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + map_key.SetStringValue(reflection->GetString(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_INT64: + map_key.SetInt64Value(reflection->GetInt64(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_INT32: + map_key.SetInt32Value(reflection->GetInt32(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_UINT64: + map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_UINT32: + map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_BOOL: + map_key.SetBoolValue(reflection->GetBool(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + + if (MapFieldBase::arena_ == nullptr) { + // Remove existing map value with same key. + Map<MapKey, MapValueRef>::iterator iter = map->find(map_key); + if (iter != map->end()) { + iter->second.DeleteData(); + } + } + + MapValueRef& map_val = (*map)[map_key]; + map_val.SetType(val_des->cpp_type()); + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \ + *value = reflection->Get##METHOD(*it, val_des); \ + map_val.SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t, Int32); + HANDLE_TYPE(INT64, int64_t, Int64); + HANDLE_TYPE(UINT32, uint32_t, UInt32); + HANDLE_TYPE(UINT64, uint64_t, UInt64); + HANDLE_TYPE(DOUBLE, double, Double); + HANDLE_TYPE(FLOAT, float, Float); + HANDLE_TYPE(BOOL, bool, Bool); + HANDLE_TYPE(STRING, std::string, String); + HANDLE_TYPE(ENUM, int32_t, EnumValue); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = reflection->GetMessage(*it, val_des); + Message* value = message.New(MapFieldBase::arena_); + value->CopyFrom(message); + map_val.SetValue(value); + break; + } + } + } +} + +size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const { + size_t size = 0; + if (MapFieldBase::repeated_field_ != nullptr) { + size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong(); + } + size += sizeof(map_); + size_t map_size = map_.size(); + if (map_size) { + Map<MapKey, MapValueRef>::const_iterator it = map_.begin(); + size += sizeof(it->first) * map_size; + size += sizeof(it->second) * map_size; + // If key is string, add the allocated space. + if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) { + size += sizeof(std::string) * map_size; + } + // Add the allocated space in MapValueRef. + switch (it->second.type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + size += sizeof(TYPE) * map_size; \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + while (it != map_.end()) { + const Message& message = it->second.GetMessageValue(); + size += message.GetReflection()->SpaceUsedLong(message); + ++it; + } + break; + } + } + } + return size; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <port_undef.inc> |