blob: f78a4f407a2f3fd50018076aa85e957cb91f564f [file] [log] [blame]
// 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_ENTRY_H__
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
namespace protobuf {
class Arena;
namespace internal {
template <typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class MapField;
}
}
namespace protobuf {
namespace internal {
// Register all MapEntry default instances so we can delete them in
// ShutdownProtobufLibrary().
void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
MessageLite* default_instance);
// This is the common base class for MapEntry. It is used by MapFieldBase in
// reflection api, in which the static type of key and value is unknown.
class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
public:
::google::protobuf::Metadata GetMetadata() const {
::google::protobuf::Metadata metadata;
metadata.descriptor = descriptor_;
metadata.reflection = reflection_;
return metadata;
}
protected:
MapEntryBase() : descriptor_(NULL), reflection_(NULL) { }
virtual ~MapEntryBase() {}
const Descriptor* descriptor_;
const Reflection* reflection_;
};
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
// google::protobuf::Reflection. In order to let it work with generated message
// reflection, its internal layout is the same as generated message with the
// same fields. However, in order to decide the internal layout of key/value, we
// need to know both their cpp type in generated api and proto type.
//
// cpp type | proto type | internal layout
// int32 TYPE_INT32 int32
// int32 TYPE_FIXED32 int32
// FooEnum TYPE_ENUM int
// FooMessage TYPE_MESSAGE FooMessage*
//
// The internal layouts of primitive types can be inferred from its proto type,
// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
// get internal layout.
// Moreover, default_enum_value is used to initialize enum field in proto2.
template <typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
// Handlers for key/value wire type. Provide utilities to parse/serialize
// key/value.
typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
// Define key/value's internal stored type. Message is the only one whose
// internal stored type cannot be inferred from its proto type.
static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
typedef typename KeyWireHandler::CppType KeyInternalType;
typedef typename ValueWireHandler::CppType ValueInternalType;
typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
KeyCppType;
typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
ValCppType;
// Abbreviation for MapEntry
typedef typename google::protobuf::internal::MapEntry<
Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
// Abbreviation for MapEntryLite
typedef typename google::protobuf::internal::MapEntryLite<
Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
EntryLiteType;
public:
~MapEntry() {
if (this == default_instance_) {
delete reflection_;
}
}
// accessors ======================================================
virtual inline const KeyCppType& key() const {
return entry_lite_.key();
}
inline KeyCppType* mutable_key() {
return entry_lite_.mutable_key();
}
virtual inline const ValCppType& value() const {
return entry_lite_.value();
}
inline ValCppType* mutable_value() {
return entry_lite_.mutable_value();
}
// implements Message =============================================
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
return entry_lite_.MergePartialFromCodedStream(input);
}
int ByteSize() const {
return entry_lite_.ByteSize();
}
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
entry_lite_.SerializeWithCachedSizes(output);
}
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
return entry_lite_.SerializeWithCachedSizesToArray(output);
}
int GetCachedSize() const {
return entry_lite_.GetCachedSize();
}
bool IsInitialized() const {
return entry_lite_.IsInitialized();
}
Message* New() const {
MapEntry* entry = new MapEntry;
entry->descriptor_ = descriptor_;
entry->reflection_ = reflection_;
entry->set_default_instance(default_instance_);
return entry;
}
Message* New(Arena* arena) const {
MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
entry->descriptor_ = descriptor_;
entry->reflection_ = reflection_;
entry->set_default_instance(default_instance_);
return entry;
}
int SpaceUsed() const {
int size = sizeof(MapEntry);
size += entry_lite_.SpaceUsed();
return size;
}
void CopyFrom(const ::google::protobuf::Message& from) {
Clear();
MergeFrom(from);
}
void MergeFrom(const ::google::protobuf::Message& from) {
GOOGLE_CHECK_NE(&from, this);
const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
if (source == NULL) {
ReflectionOps::Merge(from, this);
} else {
MergeFrom(*source);
}
}
void CopyFrom(const MapEntry& from) {
Clear();
MergeFrom(from);
}
void MergeFrom(const MapEntry& from) {
entry_lite_.MergeFrom(from.entry_lite_);
}
void Clear() {
entry_lite_.Clear();
}
void InitAsDefaultInstance() {
entry_lite_.InitAsDefaultInstance();
}
Arena* GetArena() const {
return entry_lite_.GetArena();
}
// Create default MapEntry instance for given descriptor. Descriptor has to be
// given when creating default MapEntry instance because different map field
// may have the same type and MapEntry class. The given descriptor is needed
// to distinguish instances of the same MapEntry class.
static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
MapEntry* entry = new MapEntry;
const Reflection* reflection = new GeneratedMessageReflection(
descriptor, entry, offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
entry->descriptor_ = descriptor;
entry->reflection_ = reflection;
entry->set_default_instance(entry);
entry->InitAsDefaultInstance();
RegisterMapEntryDefaultInstance(entry);
return entry;
}
private:
MapEntry() : default_instance_(NULL), entry_lite_() {}
explicit MapEntry(Arena* arena)
: default_instance_(NULL), entry_lite_(arena) {}
inline Arena* GetArenaNoVirtual() const {
return entry_lite_.GetArenaNoVirtual();
}
void set_default_instance(MapEntry* default_instance) {
default_instance_ = default_instance;
entry_lite_.set_default_instance(&default_instance->entry_lite_);
}
static int offsets_[2];
UnknownFieldSet _unknown_fields_;
MapEntry* default_instance_;
EntryLiteType entry_lite_;
friend class ::google::protobuf::Arena;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
WireFormatLite::FieldType, int default_enum>
friend class LIBPROTOBUF_EXPORT internal::MapField;
friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
};
template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
default_enum_value>::offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
};
} // namespace internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__