| Index: third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| index 56d6b2990d1e219f61f1343c83d33dcbd4e451d7..eee024ee073910754be1897244a7448c7a97dc09 100644
|
| --- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| @@ -1,6 +1,6 @@
|
| // Protocol Buffers - Google's data interchange format
|
| // Copyright 2008 Google Inc. All rights reserved.
|
| -// http://code.google.com/p/protobuf/
|
| +// 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
|
| @@ -33,18 +33,31 @@
|
| // Sanjay Ghemawat, Jeff Dean, and others.
|
|
|
| #include <algorithm>
|
| +#include <set>
|
| +
|
| +#include <google/protobuf/stubs/logging.h>
|
| +#include <google/protobuf/stubs/common.h>
|
| #include <google/protobuf/descriptor.pb.h>
|
| -#include <google/protobuf/generated_message_reflection.h>
|
| #include <google/protobuf/descriptor.h>
|
| -#include <google/protobuf/repeated_field.h>
|
| #include <google/protobuf/extension_set.h>
|
| +#include <google/protobuf/generated_message_reflection.h>
|
| #include <google/protobuf/generated_message_util.h>
|
| -#include <google/protobuf/stubs/common.h>
|
| +#include <google/protobuf/map_field.h>
|
| +#include <google/protobuf/repeated_field.h>
|
| +
|
| +
|
| +#define GOOGLE_PROTOBUF_HAS_ONEOF
|
|
|
| namespace google {
|
| namespace protobuf {
|
| namespace internal {
|
|
|
| +namespace {
|
| +bool IsMapFieldInApi(const FieldDescriptor* field) {
|
| + return field->is_map();
|
| +}
|
| +} // anonymous namespace
|
| +
|
| bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
| const string& name,
|
| int* value) {
|
| @@ -59,6 +72,12 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
|
| return (d == NULL ? GetEmptyString() : d->name());
|
| }
|
|
|
| +namespace {
|
| +inline bool SupportsArenas(const Descriptor* descriptor) {
|
| + return descriptor->file()->options().cc_enable_arenas();
|
| +}
|
| +} // anonymous namespace
|
| +
|
| // ===================================================================
|
| // Helpers for reporting usage errors (e.g. trying to use GetInt32() on
|
| // a string field).
|
| @@ -162,13 +181,48 @@ GeneratedMessageReflection::GeneratedMessageReflection(
|
| int extensions_offset,
|
| const DescriptorPool* descriptor_pool,
|
| MessageFactory* factory,
|
| - int object_size)
|
| + int object_size,
|
| + int arena_offset,
|
| + int is_default_instance_offset)
|
| + : descriptor_ (descriptor),
|
| + default_instance_ (default_instance),
|
| + offsets_ (offsets),
|
| + has_bits_offset_ (has_bits_offset),
|
| + unknown_fields_offset_(unknown_fields_offset),
|
| + extensions_offset_(extensions_offset),
|
| + arena_offset_ (arena_offset),
|
| + is_default_instance_offset_(is_default_instance_offset),
|
| + object_size_ (object_size),
|
| + descriptor_pool_ ((descriptor_pool == NULL) ?
|
| + DescriptorPool::generated_pool() :
|
| + descriptor_pool),
|
| + message_factory_ (factory) {
|
| +}
|
| +
|
| +GeneratedMessageReflection::GeneratedMessageReflection(
|
| + const Descriptor* descriptor,
|
| + const Message* default_instance,
|
| + const int offsets[],
|
| + int has_bits_offset,
|
| + int unknown_fields_offset,
|
| + int extensions_offset,
|
| + const void* default_oneof_instance,
|
| + int oneof_case_offset,
|
| + const DescriptorPool* descriptor_pool,
|
| + MessageFactory* factory,
|
| + int object_size,
|
| + int arena_offset,
|
| + int is_default_instance_offset)
|
| : descriptor_ (descriptor),
|
| default_instance_ (default_instance),
|
| + default_oneof_instance_ (default_oneof_instance),
|
| offsets_ (offsets),
|
| has_bits_offset_ (has_bits_offset),
|
| + oneof_case_offset_(oneof_case_offset),
|
| unknown_fields_offset_(unknown_fields_offset),
|
| extensions_offset_(extensions_offset),
|
| + arena_offset_ (arena_offset),
|
| + is_default_instance_offset_(is_default_instance_offset),
|
| object_size_ (object_size),
|
| descriptor_pool_ ((descriptor_pool == NULL) ?
|
| DescriptorPool::generated_pool() :
|
| @@ -178,14 +232,45 @@ GeneratedMessageReflection::GeneratedMessageReflection(
|
|
|
| GeneratedMessageReflection::~GeneratedMessageReflection() {}
|
|
|
| +namespace {
|
| +UnknownFieldSet* empty_unknown_field_set_ = NULL;
|
| +GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
|
| +
|
| +void DeleteEmptyUnknownFieldSet() {
|
| + delete empty_unknown_field_set_;
|
| + empty_unknown_field_set_ = NULL;
|
| +}
|
| +
|
| +void InitEmptyUnknownFieldSet() {
|
| + empty_unknown_field_set_ = new UnknownFieldSet;
|
| + internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
|
| +}
|
| +
|
| +const UnknownFieldSet& GetEmptyUnknownFieldSet() {
|
| + ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet);
|
| + return *empty_unknown_field_set_;
|
| +}
|
| +} // namespace
|
| +
|
| const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
|
| const Message& message) const {
|
| + if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
| + return GetEmptyUnknownFieldSet();
|
| + }
|
| + if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
|
| + return GetInternalMetadataWithArena(message).unknown_fields();
|
| + }
|
| const void* ptr = reinterpret_cast<const uint8*>(&message) +
|
| unknown_fields_offset_;
|
| return *reinterpret_cast<const UnknownFieldSet*>(ptr);
|
| }
|
| +
|
| UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
|
| Message* message) const {
|
| + if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
|
| + return MutableInternalMetadataWithArena(message)->
|
| + mutable_unknown_fields();
|
| + }
|
| void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
|
| return reinterpret_cast<UnknownFieldSet*>(ptr);
|
| }
|
| @@ -234,14 +319,23 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| break;
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - // We don't know which subclass of RepeatedPtrFieldBase the type is,
|
| - // so we use RepeatedPtrFieldBase directly.
|
| - total_size +=
|
| - GetRaw<RepeatedPtrFieldBase>(message, field)
|
| - .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
| + if (IsMapFieldInApi(field)) {
|
| + total_size +=
|
| + GetRaw<MapFieldBase>(message, field).SpaceUsedExcludingSelf();
|
| + } else {
|
| + // We don't know which subclass of RepeatedPtrFieldBase the type is,
|
| + // so we use RepeatedPtrFieldBase directly.
|
| + total_size +=
|
| + GetRaw<RepeatedPtrFieldBase>(message, field)
|
| + .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
| + }
|
| +
|
| break;
|
| }
|
| } else {
|
| + if (field->containing_oneof() && !HasOneofField(message, field)) {
|
| + continue;
|
| + }
|
| switch (field->cpp_type()) {
|
| case FieldDescriptor::CPPTYPE_INT32 :
|
| case FieldDescriptor::CPPTYPE_INT64 :
|
| @@ -258,12 +352,13 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - const string* ptr = GetField<const string*>(message, field);
|
| -
|
| // Initially, the string points to the default value stored in
|
| // the prototype. Only count the string if it has been changed
|
| // from the default value.
|
| - const string* default_ptr = DefaultRaw<const string*>(field);
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + const string* ptr =
|
| + &GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
|
|
| if (ptr != default_ptr) {
|
| // string fields are represented by just a pointer, so also
|
| @@ -294,6 +389,204 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| return total_size;
|
| }
|
|
|
| +void GeneratedMessageReflection::SwapField(
|
| + Message* message1,
|
| + Message* message2,
|
| + const FieldDescriptor* field) const {
|
| + if (field->is_repeated()) {
|
| + switch (field->cpp_type()) {
|
| +#define SWAP_ARRAYS(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
|
| + MutableRaw<RepeatedField<TYPE> >(message2, field)); \
|
| + break;
|
| +
|
| + SWAP_ARRAYS(INT32 , int32 );
|
| + SWAP_ARRAYS(INT64 , int64 );
|
| + SWAP_ARRAYS(UINT32, uint32);
|
| + SWAP_ARRAYS(UINT64, uint64);
|
| + SWAP_ARRAYS(FLOAT , float );
|
| + SWAP_ARRAYS(DOUBLE, double);
|
| + SWAP_ARRAYS(BOOL , bool );
|
| + SWAP_ARRAYS(ENUM , int );
|
| +#undef SWAP_ARRAYS
|
| +
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + if (IsMapFieldInApi(field)) {
|
| + MutableRaw<MapFieldBase>(message1, field)->
|
| + MutableRepeatedField()->
|
| + Swap<GenericTypeHandler<google::protobuf::Message> >(
|
| + MutableRaw<MapFieldBase>(message2, field)->
|
| + MutableRepeatedField());
|
| + } else {
|
| + MutableRaw<RepeatedPtrFieldBase>(message1, field)->
|
| + Swap<GenericTypeHandler<google::protobuf::Message> >(
|
| + MutableRaw<RepeatedPtrFieldBase>(message2, field));
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
| + }
|
| + } else {
|
| + switch (field->cpp_type()) {
|
| +#define SWAP_VALUES(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + std::swap(*MutableRaw<TYPE>(message1, field), \
|
| + *MutableRaw<TYPE>(message2, field)); \
|
| + break;
|
| +
|
| + SWAP_VALUES(INT32 , int32 );
|
| + SWAP_VALUES(INT64 , int64 );
|
| + SWAP_VALUES(UINT32, uint32);
|
| + SWAP_VALUES(UINT64, uint64);
|
| + SWAP_VALUES(FLOAT , float );
|
| + SWAP_VALUES(DOUBLE, double);
|
| + SWAP_VALUES(BOOL , bool );
|
| + SWAP_VALUES(ENUM , int );
|
| +#undef SWAP_VALUES
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + std::swap(*MutableRaw<Message*>(message1, field),
|
| + *MutableRaw<Message*>(message2, field));
|
| + break;
|
| +
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + switch (field->options().ctype()) {
|
| + default: // TODO(kenton): Support other string reps.
|
| + case FieldOptions::STRING:
|
| + MutableRaw<ArenaStringPtr>(message1, field)->Swap(
|
| + MutableRaw<ArenaStringPtr>(message2, field));
|
| + break;
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
| + }
|
| + }
|
| +}
|
| +
|
| +void GeneratedMessageReflection::SwapOneofField(
|
| + Message* message1,
|
| + Message* message2,
|
| + const OneofDescriptor* oneof_descriptor) const {
|
| + uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
|
| + uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
|
| +
|
| + int32 temp_int32;
|
| + int64 temp_int64;
|
| + uint32 temp_uint32;
|
| + uint64 temp_uint64;
|
| + float temp_float;
|
| + double temp_double;
|
| + bool temp_bool;
|
| + int temp_int;
|
| + Message* temp_message = NULL;
|
| + string temp_string;
|
| +
|
| + // Stores message1's oneof field to a temp variable.
|
| + const FieldDescriptor* field1 = NULL;
|
| + if (oneof_case1 > 0) {
|
| + field1 = descriptor_->FindFieldByNumber(oneof_case1);
|
| + //oneof_descriptor->field(oneof_case1);
|
| + switch (field1->cpp_type()) {
|
| +#define GET_TEMP_VALUE(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + temp_##TYPE = GetField<TYPE>(*message1, field1); \
|
| + break;
|
| +
|
| + GET_TEMP_VALUE(INT32 , int32 );
|
| + GET_TEMP_VALUE(INT64 , int64 );
|
| + GET_TEMP_VALUE(UINT32, uint32);
|
| + GET_TEMP_VALUE(UINT64, uint64);
|
| + GET_TEMP_VALUE(FLOAT , float );
|
| + GET_TEMP_VALUE(DOUBLE, double);
|
| + GET_TEMP_VALUE(BOOL , bool );
|
| + GET_TEMP_VALUE(ENUM , int );
|
| +#undef GET_TEMP_VALUE
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + temp_message = ReleaseMessage(message1, field1);
|
| + break;
|
| +
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + temp_string = GetString(*message1, field1);
|
| + break;
|
| +
|
| + default:
|
| + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
|
| + }
|
| + }
|
| +
|
| + // Sets message1's oneof field from the message2's oneof field.
|
| + if (oneof_case2 > 0) {
|
| + const FieldDescriptor* field2 =
|
| + descriptor_->FindFieldByNumber(oneof_case2);
|
| + switch (field2->cpp_type()) {
|
| +#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + SetField<TYPE>(message1, field2, GetField<TYPE>(*message2, field2)); \
|
| + break;
|
| +
|
| + SET_ONEOF_VALUE1(INT32 , int32 );
|
| + SET_ONEOF_VALUE1(INT64 , int64 );
|
| + SET_ONEOF_VALUE1(UINT32, uint32);
|
| + SET_ONEOF_VALUE1(UINT64, uint64);
|
| + SET_ONEOF_VALUE1(FLOAT , float );
|
| + SET_ONEOF_VALUE1(DOUBLE, double);
|
| + SET_ONEOF_VALUE1(BOOL , bool );
|
| + SET_ONEOF_VALUE1(ENUM , int );
|
| +#undef SET_ONEOF_VALUE1
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + SetAllocatedMessage(message1,
|
| + ReleaseMessage(message2, field2),
|
| + field2);
|
| + break;
|
| +
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + SetString(message1, field2, GetString(*message2, field2));
|
| + break;
|
| +
|
| + default:
|
| + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type();
|
| + }
|
| + } else {
|
| + ClearOneof(message1, oneof_descriptor);
|
| + }
|
| +
|
| + // Sets message2's oneof field from the temp variable.
|
| + if (oneof_case1 > 0) {
|
| + switch (field1->cpp_type()) {
|
| +#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + SetField<TYPE>(message2, field1, temp_##TYPE); \
|
| + break;
|
| +
|
| + SET_ONEOF_VALUE2(INT32 , int32 );
|
| + SET_ONEOF_VALUE2(INT64 , int64 );
|
| + SET_ONEOF_VALUE2(UINT32, uint32);
|
| + SET_ONEOF_VALUE2(UINT64, uint64);
|
| + SET_ONEOF_VALUE2(FLOAT , float );
|
| + SET_ONEOF_VALUE2(DOUBLE, double);
|
| + SET_ONEOF_VALUE2(BOOL , bool );
|
| + SET_ONEOF_VALUE2(ENUM , int );
|
| +#undef SET_ONEOF_VALUE2
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + SetAllocatedMessage(message2, temp_message, field1);
|
| + break;
|
| +
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + SetString(message2, field1, temp_string);
|
| + break;
|
| +
|
| + default:
|
| + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
|
| + }
|
| + } else {
|
| + ClearOneof(message2, oneof_descriptor);
|
| + }
|
| +}
|
| +
|
| void GeneratedMessageReflection::Swap(
|
| Message* message1,
|
| Message* message2) const {
|
| @@ -315,86 +608,96 @@ void GeneratedMessageReflection::Swap(
|
| << "\"). Note that the exact same class is required; not just the same "
|
| "descriptor.";
|
|
|
| - uint32* has_bits1 = MutableHasBits(message1);
|
| - uint32* has_bits2 = MutableHasBits(message2);
|
| - int has_bits_size = (descriptor_->field_count() + 31) / 32;
|
| + // Check that both messages are in the same arena (or both on the heap). We
|
| + // need to copy all data if not, due to ownership semantics.
|
| + if (GetArena(message1) != GetArena(message2)) {
|
| + // Slow copy path.
|
| + // Use our arena as temp space, if available.
|
| + Message* temp = message1->New(GetArena(message1));
|
| + temp->MergeFrom(*message1);
|
| + message1->CopyFrom(*message2);
|
| + message2->CopyFrom(*temp);
|
| + if (GetArena(message1) == NULL) {
|
| + delete temp;
|
| + }
|
| + return;
|
| + }
|
| +
|
| + if (has_bits_offset_ != -1) {
|
| + uint32* has_bits1 = MutableHasBits(message1);
|
| + uint32* has_bits2 = MutableHasBits(message2);
|
| + int has_bits_size = (descriptor_->field_count() + 31) / 32;
|
|
|
| - for (int i = 0; i < has_bits_size; i++) {
|
| - std::swap(has_bits1[i], has_bits2[i]);
|
| + for (int i = 0; i < has_bits_size; i++) {
|
| + std::swap(has_bits1[i], has_bits2[i]);
|
| + }
|
| }
|
|
|
| for (int i = 0; i < descriptor_->field_count(); i++) {
|
| const FieldDescriptor* field = descriptor_->field(i);
|
| - if (field->is_repeated()) {
|
| - switch (field->cpp_type()) {
|
| -#define SWAP_ARRAYS(CPPTYPE, TYPE) \
|
| - case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| - MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
|
| - MutableRaw<RepeatedField<TYPE> >(message2, field)); \
|
| - break;
|
| + if (!field->containing_oneof()) {
|
| + SwapField(message1, message2, field);
|
| + }
|
| + }
|
|
|
| - SWAP_ARRAYS(INT32 , int32 );
|
| - SWAP_ARRAYS(INT64 , int64 );
|
| - SWAP_ARRAYS(UINT32, uint32);
|
| - SWAP_ARRAYS(UINT64, uint64);
|
| - SWAP_ARRAYS(FLOAT , float );
|
| - SWAP_ARRAYS(DOUBLE, double);
|
| - SWAP_ARRAYS(BOOL , bool );
|
| - SWAP_ARRAYS(ENUM , int );
|
| -#undef SWAP_ARRAYS
|
| + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
| + SwapOneofField(message1, message2, descriptor_->oneof_decl(i));
|
| + }
|
|
|
| - case FieldDescriptor::CPPTYPE_STRING:
|
| - case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
|
| - MutableRaw<RepeatedPtrFieldBase>(message2, field));
|
| - break;
|
| + if (extensions_offset_ != -1) {
|
| + MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
|
| + }
|
|
|
| - default:
|
| - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
| - }
|
| - } else {
|
| - switch (field->cpp_type()) {
|
| -#define SWAP_VALUES(CPPTYPE, TYPE) \
|
| - case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| - std::swap(*MutableRaw<TYPE>(message1, field), \
|
| - *MutableRaw<TYPE>(message2, field)); \
|
| - break;
|
| + MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
|
| +}
|
|
|
| - SWAP_VALUES(INT32 , int32 );
|
| - SWAP_VALUES(INT64 , int64 );
|
| - SWAP_VALUES(UINT32, uint32);
|
| - SWAP_VALUES(UINT64, uint64);
|
| - SWAP_VALUES(FLOAT , float );
|
| - SWAP_VALUES(DOUBLE, double);
|
| - SWAP_VALUES(BOOL , bool );
|
| - SWAP_VALUES(ENUM , int );
|
| -#undef SWAP_VALUES
|
| - case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - std::swap(*MutableRaw<Message*>(message1, field),
|
| - *MutableRaw<Message*>(message2, field));
|
| - break;
|
| +void GeneratedMessageReflection::SwapFields(
|
| + Message* message1,
|
| + Message* message2,
|
| + const vector<const FieldDescriptor*>& fields) const {
|
| + if (message1 == message2) return;
|
|
|
| - case FieldDescriptor::CPPTYPE_STRING:
|
| - switch (field->options().ctype()) {
|
| - default: // TODO(kenton): Support other string reps.
|
| - case FieldOptions::STRING:
|
| - std::swap(*MutableRaw<string*>(message1, field),
|
| - *MutableRaw<string*>(message2, field));
|
| - break;
|
| - }
|
| - break;
|
| + // TODO(kenton): Other Reflection methods should probably check this too.
|
| + GOOGLE_CHECK_EQ(message1->GetReflection(), this)
|
| + << "First argument to SwapFields() (of type \""
|
| + << message1->GetDescriptor()->full_name()
|
| + << "\") is not compatible with this reflection object (which is for type \""
|
| + << descriptor_->full_name()
|
| + << "\"). Note that the exact same class is required; not just the same "
|
| + "descriptor.";
|
| + GOOGLE_CHECK_EQ(message2->GetReflection(), this)
|
| + << "Second argument to SwapFields() (of type \""
|
| + << message2->GetDescriptor()->full_name()
|
| + << "\") is not compatible with this reflection object (which is for type \""
|
| + << descriptor_->full_name()
|
| + << "\"). Note that the exact same class is required; not just the same "
|
| + "descriptor.";
|
|
|
| - default:
|
| - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
| + std::set<int> swapped_oneof;
|
| +
|
| + for (int i = 0; i < fields.size(); i++) {
|
| + const FieldDescriptor* field = fields[i];
|
| + if (field->is_extension()) {
|
| + MutableExtensionSet(message1)->SwapExtension(
|
| + MutableExtensionSet(message2),
|
| + field->number());
|
| + } else {
|
| + if (field->containing_oneof()) {
|
| + int oneof_index = field->containing_oneof()->index();
|
| + // Only swap the oneof field once.
|
| + if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) {
|
| + continue;
|
| + }
|
| + swapped_oneof.insert(oneof_index);
|
| + SwapOneofField(message1, message2, field->containing_oneof());
|
| + } else {
|
| + // Swap has bit.
|
| + SwapBit(message1, message2, field);
|
| + // Swap field.
|
| + SwapField(message1, message2, field);
|
| }
|
| }
|
| }
|
| -
|
| - if (extensions_offset_ != -1) {
|
| - MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
|
| - }
|
| -
|
| - MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
|
| }
|
|
|
| // -------------------------------------------------------------------
|
| @@ -407,7 +710,11 @@ bool GeneratedMessageReflection::HasField(const Message& message,
|
| if (field->is_extension()) {
|
| return GetExtensionSet(message).Has(field->number());
|
| } else {
|
| - return HasBit(message, field);
|
| + if (field->containing_oneof()) {
|
| + return HasOneofField(message, field);
|
| + } else {
|
| + return HasBit(message, field);
|
| + }
|
| }
|
| }
|
|
|
| @@ -436,7 +743,11 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
|
|
|
| case FieldDescriptor::CPPTYPE_STRING:
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - return GetRaw<RepeatedPtrFieldBase>(message, field).size();
|
| + if (IsMapFieldInApi(field)) {
|
| + return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
|
| + } else {
|
| + return GetRaw<RepeatedPtrFieldBase>(message, field).size();
|
| + }
|
| }
|
|
|
| GOOGLE_LOG(FATAL) << "Can't get here.";
|
| @@ -451,6 +762,11 @@ void GeneratedMessageReflection::ClearField(
|
| if (field->is_extension()) {
|
| MutableExtensionSet(message)->ClearExtension(field->number());
|
| } else if (!field->is_repeated()) {
|
| + if (field->containing_oneof()) {
|
| + ClearOneofField(message, field);
|
| + return;
|
| + }
|
| +
|
| if (HasBit(*message, field)) {
|
| ClearBit(message, field);
|
|
|
| @@ -479,23 +795,28 @@ void GeneratedMessageReflection::ClearField(
|
| case FieldDescriptor::CPPTYPE_STRING: {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| - case FieldOptions::STRING:
|
| - const string* default_ptr = DefaultRaw<const string*>(field);
|
| - string** value = MutableRaw<string*>(message, field);
|
| - if (*value != default_ptr) {
|
| - if (field->has_default_value()) {
|
| - (*value)->assign(field->default_value_string());
|
| - } else {
|
| - (*value)->clear();
|
| - }
|
| - }
|
| + case FieldOptions::STRING: {
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
|
| + GetArena(message));
|
| break;
|
| + }
|
| }
|
| break;
|
| }
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - (*MutableRaw<Message*>(message, field))->Clear();
|
| + if (has_bits_offset_ == -1) {
|
| + // Proto3 does not have has-bits and we need to set a message field
|
| + // to NULL in order to indicate its un-presence.
|
| + if (GetArena(message) == NULL) {
|
| + delete *MutableRaw<Message*>(message, field);
|
| + }
|
| + *MutableRaw<Message*>(message, field) = NULL;
|
| + } else {
|
| + (*MutableRaw<Message*>(message, field))->Clear();
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -527,10 +848,16 @@ void GeneratedMessageReflection::ClearField(
|
| }
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE: {
|
| - // We don't know which subclass of RepeatedPtrFieldBase the type is,
|
| - // so we use RepeatedPtrFieldBase directly.
|
| - MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| - ->Clear<GenericTypeHandler<Message> >();
|
| + if (IsMapFieldInApi(field)) {
|
| + MutableRaw<MapFieldBase>(message, field)
|
| + ->MutableRepeatedField()
|
| + ->Clear<GenericTypeHandler<Message> >();
|
| + } else {
|
| + // We don't know which subclass of RepeatedPtrFieldBase the type is,
|
| + // so we use RepeatedPtrFieldBase directly.
|
| + MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| + ->Clear<GenericTypeHandler<Message> >();
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -572,8 +899,14 @@ void GeneratedMessageReflection::RemoveLast(
|
| break;
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| + if (IsMapFieldInApi(field)) {
|
| + MutableRaw<MapFieldBase>(message, field)
|
| + ->MutableRepeatedField()
|
| + ->RemoveLast<GenericTypeHandler<Message> >();
|
| + } else {
|
| + MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| ->RemoveLast<GenericTypeHandler<Message> >();
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -588,8 +921,14 @@ Message* GeneratedMessageReflection::ReleaseLast(
|
| return static_cast<Message*>(
|
| MutableExtensionSet(message)->ReleaseLast(field->number()));
|
| } else {
|
| - return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| + if (IsMapFieldInApi(field)) {
|
| + return MutableRaw<MapFieldBase>(message, field)
|
| + ->MutableRepeatedField()
|
| + ->ReleaseLast<GenericTypeHandler<Message> >();
|
| + } else {
|
| + return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| ->ReleaseLast<GenericTypeHandler<Message> >();
|
| + }
|
| }
|
| }
|
|
|
| @@ -623,8 +962,14 @@ void GeneratedMessageReflection::SwapElements(
|
|
|
| case FieldDescriptor::CPPTYPE_STRING:
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| + if (IsMapFieldInApi(field)) {
|
| + MutableRaw<MapFieldBase>(message, field)
|
| + ->MutableRepeatedField()
|
| + ->SwapElements(index1, index2);
|
| + } else {
|
| + MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| ->SwapElements(index1, index2);
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -648,6 +993,7 @@ void GeneratedMessageReflection::ListFields(
|
| // Optimization: The default instance never has any fields set.
|
| if (&message == default_instance_) return;
|
|
|
| + output->reserve(descriptor_->field_count());
|
| for (int i = 0; i < descriptor_->field_count(); i++) {
|
| const FieldDescriptor* field = descriptor_->field(i);
|
| if (field->is_repeated()) {
|
| @@ -655,7 +1001,11 @@ void GeneratedMessageReflection::ListFields(
|
| output->push_back(field);
|
| }
|
| } else {
|
| - if (HasBit(message, field)) {
|
| + if (field->containing_oneof()) {
|
| + if (HasOneofField(message, field)) {
|
| + output->push_back(field);
|
| + }
|
| + } else if (HasBit(message, field)) {
|
| output->push_back(field);
|
| }
|
| }
|
| @@ -667,7 +1017,7 @@ void GeneratedMessageReflection::ListFields(
|
| }
|
|
|
| // ListFields() must sort output by field number.
|
| - sort(output->begin(), output->end(), FieldNumberSorter());
|
| + std::sort(output->begin(), output->end(), FieldNumberSorter());
|
| }
|
|
|
| // -------------------------------------------------------------------
|
| @@ -754,8 +1104,11 @@ string GeneratedMessageReflection::GetString(
|
| } else {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| - case FieldOptions::STRING:
|
| - return *GetField<const string*>(message, field);
|
| + case FieldOptions::STRING: {
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
| + }
|
| }
|
|
|
| GOOGLE_LOG(FATAL) << "Can't get here.";
|
| @@ -773,8 +1126,11 @@ const string& GeneratedMessageReflection::GetStringReference(
|
| } else {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| - case FieldOptions::STRING:
|
| - return *GetField<const string*>(message, field);
|
| + case FieldOptions::STRING: {
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
| + }
|
| }
|
|
|
| GOOGLE_LOG(FATAL) << "Can't get here.";
|
| @@ -794,12 +1150,15 @@ void GeneratedMessageReflection::SetString(
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - string** ptr = MutableField<string*>(message, field);
|
| - if (*ptr == DefaultRaw<const string*>(field)) {
|
| - *ptr = new string(value);
|
| - } else {
|
| - (*ptr)->assign(value);
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + if (field->containing_oneof() && !HasOneofField(*message, field)) {
|
| + ClearOneof(message, field->containing_oneof());
|
| + MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault(
|
| + default_ptr);
|
| }
|
| + MutableField<ArenaStringPtr>(message, field)->Set(default_ptr,
|
| + value, GetArena(message));
|
| break;
|
| }
|
| }
|
| @@ -881,42 +1240,80 @@ void GeneratedMessageReflection::AddString(
|
|
|
| // -------------------------------------------------------------------
|
|
|
| +inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
|
| + return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
| +}
|
| +
|
| const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
|
| const Message& message, const FieldDescriptor* field) const {
|
| - USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
|
| + // Usage checked by GetEnumValue.
|
| + int value = GetEnumValue(message, field);
|
| + return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
|
| +}
|
|
|
| - int value;
|
| +int GeneratedMessageReflection::GetEnumValue(
|
| + const Message& message, const FieldDescriptor* field) const {
|
| + USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
|
| +
|
| + int32 value;
|
| if (field->is_extension()) {
|
| value = GetExtensionSet(message).GetEnum(
|
| field->number(), field->default_value_enum()->number());
|
| } else {
|
| value = GetField<int>(message, field);
|
| }
|
| - const EnumValueDescriptor* result =
|
| - field->enum_type()->FindValueByNumber(value);
|
| - GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
|
| - << field->full_name() << " of type "
|
| - << field->enum_type()->full_name() << ".";
|
| - return result;
|
| + return value;
|
| }
|
|
|
| void GeneratedMessageReflection::SetEnum(
|
| Message* message, const FieldDescriptor* field,
|
| const EnumValueDescriptor* value) const {
|
| - USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
|
| + // Usage checked by SetEnumValue.
|
| USAGE_CHECK_ENUM_VALUE(SetEnum);
|
| + SetEnumValueInternal(message, field, value->number());
|
| +}
|
| +
|
| +void GeneratedMessageReflection::SetEnumValue(
|
| + Message* message, const FieldDescriptor* field,
|
| + int value) const {
|
| + USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
|
| + if (!CreateUnknownEnumValues(descriptor_->file())) {
|
| + // Check that the value is valid if we don't support direct storage of
|
| + // unknown enum values.
|
| + const EnumValueDescriptor* value_desc =
|
| + field->enum_type()->FindValueByNumber(value);
|
| + if (value_desc == NULL) {
|
| + GOOGLE_LOG(DFATAL) << "SetEnumValue accepts only valid integer values: value "
|
| + << value << " unexpected for field " << field->full_name();
|
| + // In production builds, DFATAL will not terminate the program, so we have
|
| + // to do something reasonable: just set the default value.
|
| + value = field->default_value_enum()->number();
|
| + }
|
| + }
|
| + SetEnumValueInternal(message, field, value);
|
| +}
|
|
|
| +void GeneratedMessageReflection::SetEnumValueInternal(
|
| + Message* message, const FieldDescriptor* field,
|
| + int value) const {
|
| if (field->is_extension()) {
|
| MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
|
| - value->number(), field);
|
| + value, field);
|
| } else {
|
| - SetField<int>(message, field, value->number());
|
| + SetField<int>(message, field, value);
|
| }
|
| }
|
|
|
| const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
|
| const Message& message, const FieldDescriptor* field, int index) const {
|
| - USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
|
| + // Usage checked by GetRepeatedEnumValue.
|
| + int value = GetRepeatedEnumValue(message, field, index);
|
| + return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
|
| +}
|
| +
|
| +int GeneratedMessageReflection::GetRepeatedEnumValue(
|
| + const Message& message, const FieldDescriptor* field, int index) const {
|
| + USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
|
|
|
| int value;
|
| if (field->is_extension()) {
|
| @@ -924,41 +1321,89 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
|
| } else {
|
| value = GetRepeatedField<int>(message, field, index);
|
| }
|
| - const EnumValueDescriptor* result =
|
| - field->enum_type()->FindValueByNumber(value);
|
| - GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
|
| - << field->full_name() << " of type "
|
| - << field->enum_type()->full_name() << ".";
|
| - return result;
|
| + return value;
|
| }
|
|
|
| void GeneratedMessageReflection::SetRepeatedEnum(
|
| Message* message,
|
| const FieldDescriptor* field, int index,
|
| const EnumValueDescriptor* value) const {
|
| - USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
|
| + // Usage checked by SetRepeatedEnumValue.
|
| USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
|
| + SetRepeatedEnumValueInternal(message, field, index, value->number());
|
| +}
|
|
|
| +void GeneratedMessageReflection::SetRepeatedEnumValue(
|
| + Message* message,
|
| + const FieldDescriptor* field, int index,
|
| + int value) const {
|
| + USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
|
| + if (!CreateUnknownEnumValues(descriptor_->file())) {
|
| + // Check that the value is valid if we don't support direct storage of
|
| + // unknown enum values.
|
| + const EnumValueDescriptor* value_desc =
|
| + field->enum_type()->FindValueByNumber(value);
|
| + if (value_desc == NULL) {
|
| + GOOGLE_LOG(DFATAL) << "SetRepeatedEnumValue accepts only valid integer values: "
|
| + << "value " << value << " unexpected for field "
|
| + << field->full_name();
|
| + // In production builds, DFATAL will not terminate the program, so we have
|
| + // to do something reasonable: just set the default value.
|
| + value = field->default_value_enum()->number();
|
| + }
|
| + }
|
| + SetRepeatedEnumValueInternal(message, field, index, value);
|
| +}
|
| +
|
| +void GeneratedMessageReflection::SetRepeatedEnumValueInternal(
|
| + Message* message,
|
| + const FieldDescriptor* field, int index,
|
| + int value) const {
|
| if (field->is_extension()) {
|
| MutableExtensionSet(message)->SetRepeatedEnum(
|
| - field->number(), index, value->number());
|
| + field->number(), index, value);
|
| } else {
|
| - SetRepeatedField<int>(message, field, index, value->number());
|
| + SetRepeatedField<int>(message, field, index, value);
|
| }
|
| }
|
|
|
| void GeneratedMessageReflection::AddEnum(
|
| Message* message, const FieldDescriptor* field,
|
| const EnumValueDescriptor* value) const {
|
| - USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
|
| + // Usage checked by AddEnumValue.
|
| USAGE_CHECK_ENUM_VALUE(AddEnum);
|
| + AddEnumValueInternal(message, field, value->number());
|
| +}
|
| +
|
| +void GeneratedMessageReflection::AddEnumValue(
|
| + Message* message, const FieldDescriptor* field,
|
| + int value) const {
|
| + USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
|
| + if (!CreateUnknownEnumValues(descriptor_->file())) {
|
| + // Check that the value is valid if we don't support direct storage of
|
| + // unknown enum values.
|
| + const EnumValueDescriptor* value_desc =
|
| + field->enum_type()->FindValueByNumber(value);
|
| + if (value_desc == NULL) {
|
| + GOOGLE_LOG(DFATAL) << "AddEnumValue accepts only valid integer values: value "
|
| + << value << " unexpected for field " << field->full_name();
|
| + // In production builds, DFATAL will not terminate the program, so we have
|
| + // to do something reasonable: just set the default value.
|
| + value = field->default_value_enum()->number();
|
| + }
|
| + }
|
| + AddEnumValueInternal(message, field, value);
|
| +}
|
|
|
| +void GeneratedMessageReflection::AddEnumValueInternal(
|
| + Message* message, const FieldDescriptor* field,
|
| + int value) const {
|
| if (field->is_extension()) {
|
| MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
|
| field->options().packed(),
|
| - value->number(), field);
|
| + value, field);
|
| } else {
|
| - AddField<int>(message, field, value->number());
|
| + AddField<int>(message, field, value);
|
| }
|
| }
|
|
|
| @@ -997,17 +1442,91 @@ Message* GeneratedMessageReflection::MutableMessage(
|
| MutableExtensionSet(message)->MutableMessage(field, factory));
|
| } else {
|
| Message* result;
|
| - Message** result_holder = MutableField<Message*>(message, field);
|
| + Message** result_holder = MutableRaw<Message*>(message, field);
|
| +
|
| + if (field->containing_oneof()) {
|
| + if (!HasOneofField(*message, field)) {
|
| + ClearOneof(message, field->containing_oneof());
|
| + result_holder = MutableField<Message*>(message, field);
|
| + const Message* default_message = DefaultRaw<const Message*>(field);
|
| + *result_holder = default_message->New(message->GetArena());
|
| + }
|
| + } else {
|
| + SetBit(message, field);
|
| + }
|
| +
|
| if (*result_holder == NULL) {
|
| const Message* default_message = DefaultRaw<const Message*>(field);
|
| - *result_holder = default_message->New();
|
| + *result_holder = default_message->New(message->GetArena());
|
| }
|
| result = *result_holder;
|
| return result;
|
| }
|
| }
|
|
|
| -Message* GeneratedMessageReflection::ReleaseMessage(
|
| +void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage(
|
| + Message* message,
|
| + Message* sub_message,
|
| + const FieldDescriptor* field) const {
|
| + USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
|
| +
|
| + if (field->is_extension()) {
|
| + MutableExtensionSet(message)->SetAllocatedMessage(
|
| + field->number(), field->type(), field, sub_message);
|
| + } else {
|
| + if (field->containing_oneof()) {
|
| + if (sub_message == NULL) {
|
| + ClearOneof(message, field->containing_oneof());
|
| + return;
|
| + }
|
| + ClearOneof(message, field->containing_oneof());
|
| + *MutableRaw<Message*>(message, field) = sub_message;
|
| + SetOneofCase(message, field);
|
| + return;
|
| + }
|
| +
|
| + if (sub_message == NULL) {
|
| + ClearBit(message, field);
|
| + } else {
|
| + SetBit(message, field);
|
| + }
|
| + Message** sub_message_holder = MutableRaw<Message*>(message, field);
|
| + if (GetArena(message) == NULL) {
|
| + delete *sub_message_holder;
|
| + }
|
| + *sub_message_holder = sub_message;
|
| + }
|
| +}
|
| +
|
| +void GeneratedMessageReflection::SetAllocatedMessage(
|
| + Message* message,
|
| + Message* sub_message,
|
| + const FieldDescriptor* field) const {
|
| + // If message and sub-message are in different memory ownership domains
|
| + // (different arenas, or one is on heap and one is not), then we may need to
|
| + // do a copy.
|
| + if (sub_message != NULL &&
|
| + sub_message->GetArena() != message->GetArena()) {
|
| + if (sub_message->GetArena() == NULL && message->GetArena() != NULL) {
|
| + // Case 1: parent is on an arena and child is heap-allocated. We can add
|
| + // the child to the arena's Own() list to free on arena destruction, then
|
| + // set our pointer.
|
| + message->GetArena()->Own(sub_message);
|
| + UnsafeArenaSetAllocatedMessage(message, sub_message, field);
|
| + } else {
|
| + // Case 2: all other cases. We need to make a copy. MutableMessage() will
|
| + // either get the existing message object, or instantiate a new one as
|
| + // appropriate w.r.t. our arena.
|
| + Message* sub_message_copy = MutableMessage(message, field);
|
| + sub_message_copy->CopyFrom(*sub_message);
|
| + }
|
| + } else {
|
| + // Same memory ownership domains.
|
| + UnsafeArenaSetAllocatedMessage(message, sub_message, field);
|
| + }
|
| +}
|
| +
|
| +Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
|
| Message* message,
|
| const FieldDescriptor* field,
|
| MessageFactory* factory) const {
|
| @@ -1020,6 +1539,13 @@ Message* GeneratedMessageReflection::ReleaseMessage(
|
| MutableExtensionSet(message)->ReleaseMessage(field, factory));
|
| } else {
|
| ClearBit(message, field);
|
| + if (field->containing_oneof()) {
|
| + if (HasOneofField(*message, field)) {
|
| + *MutableOneofCase(message, field->containing_oneof()) = 0;
|
| + } else {
|
| + return NULL;
|
| + }
|
| + }
|
| Message** result = MutableRaw<Message*>(message, field);
|
| Message* ret = *result;
|
| *result = NULL;
|
| @@ -1027,6 +1553,19 @@ Message* GeneratedMessageReflection::ReleaseMessage(
|
| }
|
| }
|
|
|
| +Message* GeneratedMessageReflection::ReleaseMessage(
|
| + Message* message,
|
| + const FieldDescriptor* field,
|
| + MessageFactory* factory) const {
|
| + Message* released = UnsafeArenaReleaseMessage(message, field, factory);
|
| + if (GetArena(message) != NULL && released != NULL) {
|
| + Message* copy_from_arena = released->New();
|
| + copy_from_arena->CopyFrom(*released);
|
| + released = copy_from_arena;
|
| + }
|
| + return released;
|
| +}
|
| +
|
| const Message& GeneratedMessageReflection::GetRepeatedMessage(
|
| const Message& message, const FieldDescriptor* field, int index) const {
|
| USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
|
| @@ -1035,8 +1574,14 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
|
| return static_cast<const Message&>(
|
| GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
|
| } else {
|
| - return GetRaw<RepeatedPtrFieldBase>(message, field)
|
| - .Get<GenericTypeHandler<Message> >(index);
|
| + if (IsMapFieldInApi(field)) {
|
| + return GetRaw<MapFieldBase>(message, field)
|
| + .GetRepeatedField()
|
| + .Get<GenericTypeHandler<Message> >(index);
|
| + } else {
|
| + return GetRaw<RepeatedPtrFieldBase>(message, field)
|
| + .Get<GenericTypeHandler<Message> >(index);
|
| + }
|
| }
|
| }
|
|
|
| @@ -1049,8 +1594,14 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
|
| MutableExtensionSet(message)->MutableRepeatedMessage(
|
| field->number(), index));
|
| } else {
|
| - return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| + if (IsMapFieldInApi(field)) {
|
| + return MutableRaw<MapFieldBase>(message, field)
|
| + ->MutableRepeatedField()
|
| + ->Mutable<GenericTypeHandler<Message> >(index);
|
| + } else {
|
| + return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
| ->Mutable<GenericTypeHandler<Message> >(index);
|
| + }
|
| }
|
| }
|
|
|
| @@ -1065,11 +1616,18 @@ Message* GeneratedMessageReflection::AddMessage(
|
| return static_cast<Message*>(
|
| MutableExtensionSet(message)->AddMessage(field, factory));
|
| } else {
|
| + Message* result = NULL;
|
| +
|
| // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
|
| // know how to allocate one.
|
| - RepeatedPtrFieldBase* repeated =
|
| - MutableRaw<RepeatedPtrFieldBase>(message, field);
|
| - Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
|
| + RepeatedPtrFieldBase* repeated = NULL;
|
| + if (IsMapFieldInApi(field)) {
|
| + repeated =
|
| + MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
|
| + } else {
|
| + repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
|
| + }
|
| + result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
|
| if (result == NULL) {
|
| // We must allocate a new object.
|
| const Message* prototype;
|
| @@ -1078,13 +1636,36 @@ Message* GeneratedMessageReflection::AddMessage(
|
| } else {
|
| prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
|
| }
|
| - result = prototype->New();
|
| - repeated->AddAllocated<GenericTypeHandler<Message> >(result);
|
| + result = prototype->New(message->GetArena());
|
| + // We can guarantee here that repeated and result are either both heap
|
| + // allocated or arena owned. So it is safe to call the unsafe version
|
| + // of AddAllocated.
|
| + repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
|
| }
|
| +
|
| return result;
|
| }
|
| }
|
|
|
| +void GeneratedMessageReflection::AddAllocatedMessage(
|
| + Message* message, const FieldDescriptor* field,
|
| + Message* new_entry) const {
|
| + USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
|
| +
|
| + if (field->is_extension()) {
|
| + MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
|
| + } else {
|
| + RepeatedPtrFieldBase* repeated = NULL;
|
| + if (IsMapFieldInApi(field)) {
|
| + repeated =
|
| + MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
|
| + } else {
|
| + repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
|
| + }
|
| + repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry);
|
| + }
|
| +}
|
| +
|
| void* GeneratedMessageReflection::MutableRawRepeatedField(
|
| Message* message, const FieldDescriptor* field,
|
| FieldDescriptor::CppType cpptype,
|
| @@ -1097,11 +1678,122 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
|
| GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
|
| if (desc != NULL)
|
| GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
|
| - if (field->is_extension())
|
| + if (field->is_extension()) {
|
| return MutableExtensionSet(message)->MutableRawRepeatedField(
|
| - field->number());
|
| - else
|
| + field->number(), field->type(), field->is_packed(), field);
|
| + } else {
|
| + // Trigger transform for MapField
|
| + if (IsMapFieldInApi(field)) {
|
| + return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
|
| + offsets_[field->index()])
|
| + ->MutableRepeatedField();
|
| + }
|
| return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
| + }
|
| +}
|
| +
|
| +const void* GeneratedMessageReflection::GetRawRepeatedField(
|
| + const Message& message, const FieldDescriptor* field,
|
| + FieldDescriptor::CppType cpptype,
|
| + int ctype, const Descriptor* desc) const {
|
| + USAGE_CHECK_REPEATED("GetRawRepeatedField");
|
| + if (field->cpp_type() != cpptype)
|
| + ReportReflectionUsageTypeError(descriptor_,
|
| + field, "GetRawRepeatedField", cpptype);
|
| + if (ctype >= 0)
|
| + GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
|
| + if (desc != NULL)
|
| + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
|
| + if (field->is_extension()) {
|
| + // Should use extension_set::GetRawRepeatedField. However, the required
|
| + // parameter "default repeated value" is not very easy to get here.
|
| + // Map is not supported in extensions, it is acceptable to use
|
| + // extension_set::MutableRawRepeatedField which does not change the message.
|
| + return MutableExtensionSet(const_cast<Message*>(&message))
|
| + ->MutableRawRepeatedField(
|
| + field->number(), field->type(), field->is_packed(), field);
|
| + } else {
|
| + // Trigger transform for MapField
|
| + if (IsMapFieldInApi(field)) {
|
| + return &(reinterpret_cast<const MapFieldBase*>(
|
| + reinterpret_cast<const uint8*>(&message) +
|
| + offsets_[field->index()])->GetRepeatedField());
|
| + }
|
| + return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()];
|
| + }
|
| +}
|
| +
|
| +const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
|
| + const Message& message,
|
| + const OneofDescriptor* oneof_descriptor) const {
|
| + uint32 field_number = GetOneofCase(message, oneof_descriptor);
|
| + if (field_number == 0) {
|
| + return NULL;
|
| + }
|
| + return descriptor_->FindFieldByNumber(field_number);
|
| +}
|
| +
|
| +bool GeneratedMessageReflection::ContainsMapKey(
|
| + const Message& message,
|
| + const FieldDescriptor* field,
|
| + const MapKey& key) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "LookupMapValue",
|
| + "Field is not a map field.");
|
| + return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
|
| +}
|
| +
|
| +bool GeneratedMessageReflection::InsertOrLookupMapValue(
|
| + Message* message,
|
| + const FieldDescriptor* field,
|
| + const MapKey& key,
|
| + MapValueRef* val) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "InsertOrLookupMapValue",
|
| + "Field is not a map field.");
|
| + val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
|
| + return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val);
|
| +}
|
| +
|
| +bool GeneratedMessageReflection::DeleteMapValue(
|
| + Message* message,
|
| + const FieldDescriptor* field,
|
| + const MapKey& key) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "DeleteMapValue",
|
| + "Field is not a map field.");
|
| + return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
|
| +}
|
| +
|
| +MapIterator GeneratedMessageReflection::MapBegin(
|
| + Message* message,
|
| + const FieldDescriptor* field) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "MapBegin",
|
| + "Field is not a map field.");
|
| + MapIterator iter(message, field);
|
| + GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
|
| + return iter;
|
| +}
|
| +
|
| +MapIterator GeneratedMessageReflection::MapEnd(
|
| + Message* message,
|
| + const FieldDescriptor* field) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "MapEnd",
|
| + "Field is not a map field.");
|
| + MapIterator iter(message, field);
|
| + GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
|
| + return iter;
|
| +}
|
| +
|
| +int GeneratedMessageReflection::MapSize(
|
| + const Message& message,
|
| + const FieldDescriptor* field) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "MapSize",
|
| + "Field is not a map field.");
|
| + return GetRaw<MapFieldBase>(message, field).size();
|
| }
|
|
|
| // -----------------------------------------------------------------------------
|
| @@ -1142,6 +1834,10 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
|
| return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
|
| }
|
|
|
| +bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
|
| + return CreateUnknownEnumValues(descriptor_->file());
|
| +}
|
| +
|
| // ===================================================================
|
| // Some private helpers.
|
|
|
| @@ -1150,37 +1846,70 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
|
| template <typename Type>
|
| inline const Type& GeneratedMessageReflection::GetRaw(
|
| const Message& message, const FieldDescriptor* field) const {
|
| + if (field->containing_oneof() && !HasOneofField(message, field)) {
|
| + return DefaultRaw<Type>(field);
|
| + }
|
| + int index = field->containing_oneof() ?
|
| + descriptor_->field_count() + field->containing_oneof()->index() :
|
| + field->index();
|
| const void* ptr = reinterpret_cast<const uint8*>(&message) +
|
| - offsets_[field->index()];
|
| + offsets_[index];
|
| return *reinterpret_cast<const Type*>(ptr);
|
| }
|
|
|
| template <typename Type>
|
| inline Type* GeneratedMessageReflection::MutableRaw(
|
| Message* message, const FieldDescriptor* field) const {
|
| - void* ptr = reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
| + int index = field->containing_oneof() ?
|
| + descriptor_->field_count() + field->containing_oneof()->index() :
|
| + field->index();
|
| + void* ptr = reinterpret_cast<uint8*>(message) + offsets_[index];
|
| return reinterpret_cast<Type*>(ptr);
|
| }
|
|
|
| template <typename Type>
|
| inline const Type& GeneratedMessageReflection::DefaultRaw(
|
| const FieldDescriptor* field) const {
|
| - const void* ptr = reinterpret_cast<const uint8*>(default_instance_) +
|
| - offsets_[field->index()];
|
| + const void* ptr = field->containing_oneof() ?
|
| + reinterpret_cast<const uint8*>(default_oneof_instance_) +
|
| + offsets_[field->index()] :
|
| + reinterpret_cast<const uint8*>(default_instance_) +
|
| + offsets_[field->index()];
|
| return *reinterpret_cast<const Type*>(ptr);
|
| }
|
|
|
| inline const uint32* GeneratedMessageReflection::GetHasBits(
|
| const Message& message) const {
|
| + if (has_bits_offset_ == -1) { // proto3 with no has-bits.
|
| + return NULL;
|
| + }
|
| const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
|
| return reinterpret_cast<const uint32*>(ptr);
|
| }
|
| inline uint32* GeneratedMessageReflection::MutableHasBits(
|
| Message* message) const {
|
| + if (has_bits_offset_ == -1) {
|
| + return NULL;
|
| + }
|
| void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
|
| return reinterpret_cast<uint32*>(ptr);
|
| }
|
|
|
| +inline uint32 GeneratedMessageReflection::GetOneofCase(
|
| + const Message& message,
|
| + const OneofDescriptor* oneof_descriptor) const {
|
| + const void* ptr = reinterpret_cast<const uint8*>(&message)
|
| + + oneof_case_offset_;
|
| + return reinterpret_cast<const uint32*>(ptr)[oneof_descriptor->index()];
|
| +}
|
| +
|
| +inline uint32* GeneratedMessageReflection::MutableOneofCase(
|
| + Message* message,
|
| + const OneofDescriptor* oneof_descriptor) const {
|
| + void* ptr = reinterpret_cast<uint8*>(message) + oneof_case_offset_;
|
| + return &(reinterpret_cast<uint32*>(ptr)[oneof_descriptor->index()]);
|
| +}
|
| +
|
| inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
|
| const Message& message) const {
|
| GOOGLE_DCHECK_NE(extensions_offset_, -1);
|
| @@ -1195,23 +1924,196 @@ inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
|
| return reinterpret_cast<ExtensionSet*>(ptr);
|
| }
|
|
|
| +inline Arena* GeneratedMessageReflection::GetArena(Message* message) const {
|
| + if (arena_offset_ == kNoArenaPointer) {
|
| + return NULL;
|
| + }
|
| +
|
| + if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
|
| + // zero-overhead arena pointer overloading UnknownFields
|
| + return GetInternalMetadataWithArena(*message).arena();
|
| + }
|
| +
|
| + // Baseline case: message class has a dedicated arena pointer.
|
| + void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
|
| + return *reinterpret_cast<Arena**>(ptr);
|
| +}
|
| +
|
| +inline const InternalMetadataWithArena&
|
| +GeneratedMessageReflection::GetInternalMetadataWithArena(
|
| + const Message& message) const {
|
| + const void* ptr = reinterpret_cast<const uint8*>(&message) + arena_offset_;
|
| + return *reinterpret_cast<const InternalMetadataWithArena*>(ptr);
|
| +}
|
| +
|
| +inline InternalMetadataWithArena*
|
| +GeneratedMessageReflection::MutableInternalMetadataWithArena(
|
| + Message* message) const {
|
| + void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
|
| + return reinterpret_cast<InternalMetadataWithArena*>(ptr);
|
| +}
|
| +
|
| +inline bool
|
| +GeneratedMessageReflection::GetIsDefaultInstance(
|
| + const Message& message) const {
|
| + if (is_default_instance_offset_ == kHasNoDefaultInstanceField) {
|
| + return false;
|
| + }
|
| + const void* ptr = reinterpret_cast<const uint8*>(&message) +
|
| + is_default_instance_offset_;
|
| + return *reinterpret_cast<const bool*>(ptr);
|
| +}
|
| +
|
| // Simple accessors for manipulating has_bits_.
|
| inline bool GeneratedMessageReflection::HasBit(
|
| const Message& message, const FieldDescriptor* field) const {
|
| + if (has_bits_offset_ == -1) {
|
| + // proto3: no has-bits. All fields present except messages, which are
|
| + // present only if their message-field pointer is non-NULL.
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + return !GetIsDefaultInstance(message) &&
|
| + GetRaw<const Message*>(message, field) != NULL;
|
| + } else {
|
| + // Non-message field (and non-oneof, since that was handled in HasField()
|
| + // before calling us), and singular (again, checked in HasField). So, this
|
| + // field must be a scalar.
|
| +
|
| + // Scalar primitive (numeric or string/bytes) fields are present if
|
| + // their value is non-zero (numeric) or non-empty (string/bytes). N.B.:
|
| + // we must use this definition here, rather than the "scalar fields
|
| + // always present" in the proto3 docs, because MergeFrom() semantics
|
| + // require presence as "present on wire", and reflection-based merge
|
| + // (which uses HasField()) needs to be consistent with this.
|
| + switch (field->cpp_type()) {
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + switch (field->options().ctype()) {
|
| + default: {
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + return GetField<ArenaStringPtr>(message, field).Get(
|
| + default_ptr).size() > 0;
|
| + }
|
| + }
|
| + return false;
|
| + case FieldDescriptor::CPPTYPE_BOOL:
|
| + return GetRaw<bool>(message, field) != false;
|
| + case FieldDescriptor::CPPTYPE_INT32:
|
| + return GetRaw<int32>(message, field) != 0;
|
| + case FieldDescriptor::CPPTYPE_INT64:
|
| + return GetRaw<int64>(message, field) != 0;
|
| + case FieldDescriptor::CPPTYPE_UINT32:
|
| + return GetRaw<uint32>(message, field) != 0;
|
| + case FieldDescriptor::CPPTYPE_UINT64:
|
| + return GetRaw<uint64>(message, field) != 0;
|
| + case FieldDescriptor::CPPTYPE_FLOAT:
|
| + return GetRaw<float>(message, field) != 0.0;
|
| + case FieldDescriptor::CPPTYPE_DOUBLE:
|
| + return GetRaw<double>(message, field) != 0.0;
|
| + case FieldDescriptor::CPPTYPE_ENUM:
|
| + return GetRaw<int>(message, field) != 0;
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + // handled above; avoid warning
|
| + GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
|
| + break;
|
| + }
|
| + }
|
| + }
|
| return GetHasBits(message)[field->index() / 32] &
|
| (1 << (field->index() % 32));
|
| }
|
|
|
| inline void GeneratedMessageReflection::SetBit(
|
| Message* message, const FieldDescriptor* field) const {
|
| + if (has_bits_offset_ == -1) {
|
| + return;
|
| + }
|
| MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
|
| }
|
|
|
| inline void GeneratedMessageReflection::ClearBit(
|
| Message* message, const FieldDescriptor* field) const {
|
| + if (has_bits_offset_ == -1) {
|
| + return;
|
| + }
|
| MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
|
| }
|
|
|
| +inline void GeneratedMessageReflection::SwapBit(
|
| + Message* message1, Message* message2, const FieldDescriptor* field) const {
|
| + if (has_bits_offset_ == -1) {
|
| + return;
|
| + }
|
| + bool temp_has_bit = HasBit(*message1, field);
|
| + if (HasBit(*message2, field)) {
|
| + SetBit(message1, field);
|
| + } else {
|
| + ClearBit(message1, field);
|
| + }
|
| + if (temp_has_bit) {
|
| + SetBit(message2, field);
|
| + } else {
|
| + ClearBit(message2, field);
|
| + }
|
| +}
|
| +
|
| +inline bool GeneratedMessageReflection::HasOneof(
|
| + const Message& message, const OneofDescriptor* oneof_descriptor) const {
|
| + return (GetOneofCase(message, oneof_descriptor) > 0);
|
| +}
|
| +
|
| +inline bool GeneratedMessageReflection::HasOneofField(
|
| + const Message& message, const FieldDescriptor* field) const {
|
| + return (GetOneofCase(message, field->containing_oneof()) == field->number());
|
| +}
|
| +
|
| +inline void GeneratedMessageReflection::SetOneofCase(
|
| + Message* message, const FieldDescriptor* field) const {
|
| + *MutableOneofCase(message, field->containing_oneof()) = field->number();
|
| +}
|
| +
|
| +inline void GeneratedMessageReflection::ClearOneofField(
|
| + Message* message, const FieldDescriptor* field) const {
|
| + if (HasOneofField(*message, field)) {
|
| + ClearOneof(message, field->containing_oneof());
|
| + }
|
| +}
|
| +
|
| +inline void GeneratedMessageReflection::ClearOneof(
|
| + Message* message, const OneofDescriptor* oneof_descriptor) const {
|
| + // TODO(jieluo): Consider to cache the unused object instead of deleting
|
| + // it. It will be much faster if an aplication switches a lot from
|
| + // a few oneof fields. Time/space tradeoff
|
| + uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
|
| + if (oneof_case > 0) {
|
| + const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
|
| + if (GetArena(message) == NULL) {
|
| + switch (field->cpp_type()) {
|
| + case FieldDescriptor::CPPTYPE_STRING: {
|
| + switch (field->options().ctype()) {
|
| + default: // TODO(kenton): Support other string reps.
|
| + case FieldOptions::STRING: {
|
| + const string* default_ptr =
|
| + &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + MutableField<ArenaStringPtr>(message, field)->
|
| + Destroy(default_ptr, GetArena(message));
|
| + break;
|
| + }
|
| + }
|
| + break;
|
| + }
|
| +
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + delete *MutableRaw<Message*>(message, field);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + *MutableOneofCase(message, oneof_descriptor) = 0;
|
| + }
|
| +}
|
| +
|
| // Template implementations of basic accessors. Inline because each
|
| // template instance is only called from one location. These are
|
| // used for all types except messages.
|
| @@ -1224,14 +2126,19 @@ inline const Type& GeneratedMessageReflection::GetField(
|
| template <typename Type>
|
| inline void GeneratedMessageReflection::SetField(
|
| Message* message, const FieldDescriptor* field, const Type& value) const {
|
| + if (field->containing_oneof() && !HasOneofField(*message, field)) {
|
| + ClearOneof(message, field->containing_oneof());
|
| + }
|
| *MutableRaw<Type>(message, field) = value;
|
| - SetBit(message, field);
|
| + field->containing_oneof() ?
|
| + SetOneofCase(message, field) : SetBit(message, field);
|
| }
|
|
|
| template <typename Type>
|
| inline Type* GeneratedMessageReflection::MutableField(
|
| Message* message, const FieldDescriptor* field) const {
|
| - SetBit(message, field);
|
| + field->containing_oneof() ?
|
| + SetOneofCase(message, field) : SetBit(message, field);
|
| return MutableRaw<Type>(message, field);
|
| }
|
|
|
| @@ -1276,6 +2183,92 @@ inline Type* GeneratedMessageReflection::AddField(
|
| return repeated->Add();
|
| }
|
|
|
| +MessageFactory* GeneratedMessageReflection::GetMessageFactory() const {
|
| + return message_factory_;
|
| +}
|
| +
|
| +void* GeneratedMessageReflection::RepeatedFieldData(
|
| + Message* message, const FieldDescriptor* field,
|
| + FieldDescriptor::CppType cpp_type,
|
| + const Descriptor* message_type) const {
|
| + GOOGLE_CHECK(field->is_repeated());
|
| + GOOGLE_CHECK(field->cpp_type() == cpp_type ||
|
| + (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
|
| + cpp_type == FieldDescriptor::CPPTYPE_INT32))
|
| + << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
|
| + << "the actual field type (for enums T should be the generated enum "
|
| + << "type or int32).";
|
| + if (message_type != NULL) {
|
| + GOOGLE_CHECK_EQ(message_type, field->message_type());
|
| + }
|
| + if (field->is_extension()) {
|
| + return MutableExtensionSet(message)->MutableRawRepeatedField(
|
| + field->number(), field->type(), field->is_packed(), field);
|
| + } else {
|
| + return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
| + }
|
| +}
|
| +
|
| +MapFieldBase* GeneratedMessageReflection::MapData(
|
| + Message* message, const FieldDescriptor* field) const {
|
| + USAGE_CHECK(IsMapFieldInApi(field),
|
| + "GetMapData",
|
| + "Field is not a map field.");
|
| + return MutableRaw<MapFieldBase>(message, field);
|
| +}
|
| +
|
| +GeneratedMessageReflection*
|
| +GeneratedMessageReflection::NewGeneratedMessageReflection(
|
| + const Descriptor* descriptor,
|
| + const Message* default_instance,
|
| + const int offsets[],
|
| + int has_bits_offset,
|
| + int unknown_fields_offset,
|
| + int extensions_offset,
|
| + const void* default_oneof_instance,
|
| + int oneof_case_offset,
|
| + int object_size,
|
| + int arena_offset,
|
| + int is_default_instance_offset) {
|
| + return new GeneratedMessageReflection(descriptor,
|
| + default_instance,
|
| + offsets,
|
| + has_bits_offset,
|
| + unknown_fields_offset,
|
| + extensions_offset,
|
| + default_oneof_instance,
|
| + oneof_case_offset,
|
| + DescriptorPool::generated_pool(),
|
| + MessageFactory::generated_factory(),
|
| + object_size,
|
| + arena_offset,
|
| + is_default_instance_offset);
|
| +}
|
| +
|
| +GeneratedMessageReflection*
|
| +GeneratedMessageReflection::NewGeneratedMessageReflection(
|
| + const Descriptor* descriptor,
|
| + const Message* default_instance,
|
| + const int offsets[],
|
| + int has_bits_offset,
|
| + int unknown_fields_offset,
|
| + int extensions_offset,
|
| + int object_size,
|
| + int arena_offset,
|
| + int is_default_instance_offset) {
|
| + return new GeneratedMessageReflection(descriptor,
|
| + default_instance,
|
| + offsets,
|
| + has_bits_offset,
|
| + unknown_fields_offset,
|
| + extensions_offset,
|
| + DescriptorPool::generated_pool(),
|
| + MessageFactory::generated_factory(),
|
| + object_size,
|
| + arena_offset,
|
| + is_default_instance_offset);
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace protobuf
|
| } // namespace google
|
|
|