From f157a5651c79a7a36e242af216a5d5b383ba8af2 Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Fri, 14 Nov 2014 11:50:31 -0800 Subject: Down-integrate from internal code base (C++ maps support). --- src/google/protobuf/map_field_inl.h | 269 ++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 src/google/protobuf/map_field_inl.h (limited to 'src/google/protobuf/map_field_inl.h') diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h new file mode 100644 index 00000000..6f17df95 --- /dev/null +++ b/src/google/protobuf/map_field_inl.h @@ -0,0 +1,269 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +template +MapField::MapField() + : default_entry_(NULL) { + MapFieldBase::base_map_ = new Map; + SetDefaultEnumValue(); +} + +template +MapField::MapField( + const Message* default_entry) + : default_entry_(down_cast(default_entry)) { + MapFieldBase::base_map_ = new Map; + SetDefaultEnumValue(); +} + +template +MapField::~MapField() { + delete reinterpret_cast*>(MapFieldBase::base_map_); +} + +template +int MapField::size() const { + SyncMapWithRepeatedField(); + return GetInternalMap().size(); +} + +template +void MapField::Clear() { + SyncMapWithRepeatedField(); + MutableInternalMap()->clear(); + SetMapDirty(); +} + +template +const Map& +MapField::GetMap() const { + SyncMapWithRepeatedField(); + return GetInternalMap(); +} + +template +Map* +MapField::MutableMap() { + SyncMapWithRepeatedField(); + Map* result = MutableInternalMap(); + SetMapDirty(); + return result; +} + +template +void MapField::MergeFrom( + const MapField& other) { + SyncMapWithRepeatedField(); + other.SyncMapWithRepeatedField(); + + Map* map = MutableInternalMap(); + const Map& other_map = other.GetInternalMap(); + for (typename Map::const_iterator it = other_map.begin(); + it != other_map.end(); ++it) { + (*map)[it->first] = it->second; + } + SetMapDirty(); +} + +template +void MapField::Swap( + MapField* other) { + std::swap(repeated_field_, other->repeated_field_); + std::swap(base_map_, other->base_map_); + std::swap(state_, other->state_); +} + +template +void +MapField::SetEntryDescriptor( + const Descriptor** descriptor) { + entry_descriptor_ = descriptor; +} + +template +void +MapField::SetAssignDescriptorCallback(void (*callback)()) { + assign_descriptor_callback_ = callback; +} + +template +void MapField::SetDefaultEnumValue() { + MutableInternalMap()->SetDefaultEnumValue(default_enum_value); +} + +template +MapEntry* +MapField::NewEntry() const { + // The MapEntry instance created here is only used in generated code for + // parsing. It doesn't have default instance, descriptor or reflection, + // because these are not needed in parsing and will prevent us from using it + // for parsing MessageLite. + return new EntryType(); +} + +template +MapEntry* +MapField::NewEntryWrapper( + const Key& key, const T& t) const { + return EntryType::Wrap(key, t); +} + +template +MapEntry* +MapField::NewEnumEntryWrapper( + const Key& key, const T t) const { + return EntryType::EnumWrap(key, t); +} + +template +const Map& MapField::GetInternalMap() const { + return *reinterpret_cast*>(MapFieldBase::base_map_); +} + +template +Map* MapField::MutableInternalMap() { + return reinterpret_cast*>(MapFieldBase::base_map_); +} + +template +void MapField::SyncRepeatedFieldWithMapNoLock() const { + if (repeated_field_ == NULL) { + repeated_field_ = new RepeatedPtrField(); + } + const Map& map = + *static_cast*>(MapFieldBase::base_map_); + RepeatedPtrField* repeated_field = + reinterpret_cast*>(repeated_field_); + + repeated_field->Clear(); + + for (typename Map::const_iterator it = map.begin(); + it != map.end(); ++it) { + InitDefaultEntryOnce(); + GOOGLE_CHECK(default_entry_ != NULL); + EntryType* new_entry = down_cast(default_entry_->New()); + repeated_field->AddAllocated(new_entry); + new_entry->set_key(it->first); + new_entry->set_value(it->second); + } +} + +template +void MapField::SyncMapWithRepeatedFieldNoLock() const { + Map* map = reinterpret_cast*>(MapFieldBase::base_map_); + RepeatedPtrField* repeated_field = + reinterpret_cast*>(repeated_field_); + map->clear(); + for (typename RepeatedPtrField::iterator it = + repeated_field->begin(); it != repeated_field->end(); ++it) { + // Cast is needed because Map's api and internal storage is different when + // value is enum. For enum, we cannot cast an int to enum. Thus, we have to + // copy value. For other types, they have same exposed api type and internal + // stored type. We should not introduce value copy for them. We achieve this + // by casting to value for enum while casting to reference for other types. + (*map)[it->key()] = static_cast(it->value()); + } +} + +template +int MapField::SpaceUsedExcludingSelfNoLock() const { + int size = 0; + if (repeated_field_ != NULL) { + size += repeated_field_->SpaceUsedExcludingSelf(); + } + Map* map = reinterpret_cast*>(MapFieldBase::base_map_); + size += sizeof(*map); + for (typename Map::iterator it = map->begin(); + it != map->end(); ++it) { + size += KeyHandler::SpaceUsedInMap(it->first); + size += ValHandler::SpaceUsedInMap(it->second); + } + return size; +} + +template +void MapField::InitDefaultEntryOnce() const { + if (default_entry_ == NULL) { + InitMetadataOnce(); + GOOGLE_CHECK(*entry_descriptor_ != NULL); + default_entry_ = down_cast( + MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_)); + } +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ -- cgit v1.2.3