| 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 2313181cc995220fe39ce23236e365b467e05276..08742232237ef2e8994b58c6ea48936b40aad1a5 100644
|
| --- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
|
| @@ -44,6 +44,7 @@
|
| #include <google/protobuf/generated_message_util.h>
|
| #include <google/protobuf/map_field.h>
|
| #include <google/protobuf/repeated_field.h>
|
| +// #include "google/protobuf/bridge/compatibility_mode_support.h"
|
|
|
|
|
| #define GOOGLE_PROTOBUF_HAS_ONEOF
|
| @@ -84,6 +85,22 @@ inline bool SupportsArenas(const Descriptor* descriptor) {
|
|
|
| namespace {
|
|
|
| +template <class To>
|
| +To* GetPointerAtOffset(Message* message, uint32 offset) {
|
| + return reinterpret_cast<To*>(reinterpret_cast<char*>(message) + offset);
|
| +}
|
| +
|
| +template <class To>
|
| +const To* GetConstPointerAtOffset(const Message* message, uint32 offset) {
|
| + return reinterpret_cast<const To*>(reinterpret_cast<const char*>(message) +
|
| + offset);
|
| +}
|
| +
|
| +template <class To>
|
| +const To& GetConstRefAtOffset(const Message& message, uint32 offset) {
|
| + return *GetConstPointerAtOffset<To>(&message, offset);
|
| +}
|
| +
|
| void ReportReflectionUsageError(
|
| const Descriptor* descriptor, const FieldDescriptor* field,
|
| const char* method, const char* description) {
|
| @@ -173,61 +190,24 @@ static void ReportReflectionUsageEnumTypeError(
|
| // ===================================================================
|
|
|
| GeneratedMessageReflection::GeneratedMessageReflection(
|
| - const Descriptor* descriptor,
|
| - const Message* default_instance,
|
| - const int offsets[],
|
| - int has_bits_offset,
|
| - int unknown_fields_offset,
|
| - int extensions_offset,
|
| - const DescriptorPool* descriptor_pool,
|
| - MessageFactory* factory,
|
| - 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() :
|
| - descriptor_pool),
|
| - message_factory_ (factory) {
|
| + const Descriptor* descriptor, const ReflectionSchema& schema,
|
| + const DescriptorPool* pool, MessageFactory* factory)
|
| + : descriptor_(descriptor),
|
| + schema_(schema),
|
| + descriptor_pool_((pool == NULL) ? DescriptorPool::generated_pool()
|
| + : pool),
|
| + message_factory_(factory),
|
| + // TODO(haberman) remove this when upb is using our table driven.
|
| + default_instance_(schema_.default_instance_),
|
| + default_oneof_instance_(schema_.default_oneof_instance_),
|
| + offsets_(schema_.offsets_),
|
| + has_bits_indices_(schema_.has_bit_indices_),
|
| + has_bits_offset_(schema_.has_bits_offset_),
|
| + oneof_case_offset_(schema_.oneof_case_offset_),
|
| + unknown_fields_offset_(-1),
|
| + extensions_offset_(schema_.extensions_offset_),
|
| + arena_offset_(schema_.metadata_offset_),
|
| + object_size_(schema_.object_size_) {
|
| }
|
|
|
| GeneratedMessageReflection::~GeneratedMessageReflection() {}
|
| @@ -255,39 +235,33 @@ const UnknownFieldSet& GetEmptyUnknownFieldSet() {
|
| const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
|
| const Message& message) const {
|
| if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
| + // We have to ensure that any mutations made to the return value of
|
| + // MutableUnknownFields() are not reflected here.
|
| return GetEmptyUnknownFieldSet();
|
| - }
|
| - if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
|
| + } else {
|
| 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);
|
| + return MutableInternalMetadataWithArena(message)->mutable_unknown_fields();
|
| }
|
|
|
| int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| // object_size_ already includes the in-memory representation of each field
|
| // in the message, so we only need to account for additional memory used by
|
| // the fields.
|
| - int total_size = object_size_;
|
| + int total_size = schema_.GetObjectSize();
|
|
|
| total_size += GetUnknownFields(message).SpaceUsedExcludingSelf();
|
|
|
| - if (extensions_offset_ != -1) {
|
| + if (schema_.HasExtensionSet()) {
|
| total_size += GetExtensionSet(message).SpaceUsedExcludingSelf();
|
| }
|
|
|
| - for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const int field_count = descriptor_->field_count();
|
| + for (int i = 0; i < field_count; i++) {
|
| const FieldDescriptor* field = descriptor_->field(i);
|
|
|
| if (field->is_repeated()) {
|
| @@ -356,9 +330,9 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| // the prototype. Only count the string if it has been changed
|
| // from the default value.
|
| const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + &DefaultRaw<ArenaStringPtr>(field).Get();
|
| const string* ptr =
|
| - &GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
| + &GetField<ArenaStringPtr>(message, field).Get();
|
|
|
| if (ptr != default_ptr) {
|
| // string fields are represented by just a pointer, so also
|
| @@ -372,7 +346,7 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
| }
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - if (&message == default_instance_) {
|
| + if (schema_.IsDefaultInstance(message)) {
|
| // For singular fields, the prototype just stores a pointer to the
|
| // external type's prototype, so there is no extra memory usage.
|
| } else {
|
| @@ -494,9 +468,9 @@ void GeneratedMessageReflection::SwapField(
|
| string1->Swap(string2);
|
| } else {
|
| const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| - const string temp = string1->Get(default_ptr);
|
| - string1->Set(default_ptr, string2->Get(default_ptr), arena1);
|
| + &DefaultRaw<ArenaStringPtr>(field).Get();
|
| + const string temp = string1->Get();
|
| + string1->Set(default_ptr, string2->Get(), arena1);
|
| string2->Set(default_ptr, temp, arena2);
|
| }
|
| }
|
| @@ -657,16 +631,16 @@ void GeneratedMessageReflection::Swap(
|
| // 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);
|
| + temp->MergeFrom(*message2);
|
| + message2->CopyFrom(*message1);
|
| + Swap(message1, temp);
|
| if (GetArena(message1) == NULL) {
|
| delete temp;
|
| }
|
| return;
|
| }
|
|
|
| - if (has_bits_offset_ != -1) {
|
| + if (schema_.HasHasbits()) {
|
| uint32* has_bits1 = MutableHasBits(message1);
|
| uint32* has_bits2 = MutableHasBits(message2);
|
| int has_bits_size = (descriptor_->field_count() + 31) / 32;
|
| @@ -676,18 +650,20 @@ void GeneratedMessageReflection::Swap(
|
| }
|
| }
|
|
|
| - for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const int field_count = descriptor_->field_count();
|
| + for (int i = 0; i < field_count; i++) {
|
| const FieldDescriptor* field = descriptor_->field(i);
|
| if (!field->containing_oneof()) {
|
| SwapField(message1, message2, field);
|
| }
|
| }
|
|
|
| - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
| + const int oneof_decl_count = descriptor_->oneof_decl_count();
|
| + for (int i = 0; i < oneof_decl_count; i++) {
|
| SwapOneofField(message1, message2, descriptor_->oneof_decl(i));
|
| }
|
|
|
| - if (extensions_offset_ != -1) {
|
| + if (schema_.HasExtensionSet()) {
|
| MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
|
| }
|
|
|
| @@ -697,7 +673,7 @@ void GeneratedMessageReflection::Swap(
|
| void GeneratedMessageReflection::SwapFields(
|
| Message* message1,
|
| Message* message2,
|
| - const vector<const FieldDescriptor*>& fields) const {
|
| + const std::vector<const FieldDescriptor*>& fields) const {
|
| if (message1 == message2) return;
|
|
|
| // TODO(kenton): Other Reflection methods should probably check this too.
|
| @@ -718,7 +694,8 @@ void GeneratedMessageReflection::SwapFields(
|
|
|
| std::set<int> swapped_oneof;
|
|
|
| - for (int i = 0; i < fields.size(); i++) {
|
| + const int fields_size = static_cast<int>(fields.size());
|
| + for (int i = 0; i < fields_size; i++) {
|
| const FieldDescriptor* field = fields[i];
|
| if (field->is_extension()) {
|
| MutableExtensionSet(message1)->SwapExtension(
|
| @@ -840,9 +817,9 @@ void GeneratedMessageReflection::ClearField(
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| - MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
|
| - GetArena(message));
|
| + &DefaultRaw<ArenaStringPtr>(field).Get();
|
| + MutableRaw<ArenaStringPtr>(message, field)->SetAllocated(
|
| + default_ptr, NULL, GetArena(message));
|
| break;
|
| }
|
| }
|
| @@ -850,7 +827,7 @@ void GeneratedMessageReflection::ClearField(
|
| }
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - if (has_bits_offset_ == -1) {
|
| + if (!schema_.HasHasbits()) {
|
| // 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) {
|
| @@ -1026,35 +1003,60 @@ struct FieldNumberSorter {
|
| return left->number() < right->number();
|
| }
|
| };
|
| +
|
| +inline bool IsIndexInHasBitSet(
|
| + const uint32* has_bit_set, uint32 has_bit_index) {
|
| + return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) &
|
| + static_cast<uint32>(1)) != 0;
|
| +}
|
| } // namespace
|
|
|
| void GeneratedMessageReflection::ListFields(
|
| const Message& message,
|
| - vector<const FieldDescriptor*>* output) const {
|
| + std::vector<const FieldDescriptor*>* output) const {
|
| output->clear();
|
|
|
| // 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++) {
|
| + if (schema_.IsDefaultInstance(message)) return;
|
| +
|
| + // Optimization: Avoid calling GetHasBits() and HasOneofField() many times
|
| + // within the field loop. We allow this violation of ReflectionSchema
|
| + // encapsulation because this function takes a noticable about of CPU
|
| + // fleetwide and properly allowing this optimization through public interfaces
|
| + // seems more trouble than it is worth.
|
| + const uint32* const has_bits =
|
| + schema_.HasHasbits() ? GetHasBits(message) : NULL;
|
| + const uint32* const has_bits_indices = schema_.has_bit_indices_;
|
| + const uint32* const oneof_case_array =
|
| + &GetConstRefAtOffset<uint32>(message, schema_.oneof_case_offset_);
|
| +
|
| + const int field_count = descriptor_->field_count();
|
| + output->reserve(field_count);
|
| + for (int i = 0; i < field_count; i++) {
|
| const FieldDescriptor* field = descriptor_->field(i);
|
| if (field->is_repeated()) {
|
| if (FieldSize(message, field) > 0) {
|
| output->push_back(field);
|
| }
|
| } else {
|
| - if (field->containing_oneof()) {
|
| - if (HasOneofField(message, field)) {
|
| + const OneofDescriptor* containing_oneof = field->containing_oneof();
|
| + if (containing_oneof) {
|
| + // Equivalent to: HasOneofField(message, field)
|
| + if (oneof_case_array[containing_oneof->index()] == field->number()) {
|
| + output->push_back(field);
|
| + }
|
| + } else if (has_bits) {
|
| + // Equivalent to: HasBit(message, field)
|
| + if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) {
|
| output->push_back(field);
|
| }
|
| - } else if (HasBit(message, field)) {
|
| + } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit.
|
| output->push_back(field);
|
| }
|
| }
|
| }
|
|
|
| - if (extensions_offset_ != -1) {
|
| + if (schema_.HasExtensionSet()) {
|
| GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_,
|
| output);
|
| }
|
| @@ -1148,9 +1150,7 @@ string GeneratedMessageReflection::GetString(
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| - return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
| + return GetField<ArenaStringPtr>(message, field).Get();
|
| }
|
| }
|
|
|
| @@ -1170,9 +1170,7 @@ const string& GeneratedMessageReflection::GetStringReference(
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| - return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
|
| + return GetField<ArenaStringPtr>(message, field).Get();
|
| }
|
| }
|
|
|
| @@ -1193,8 +1191,7 @@ void GeneratedMessageReflection::SetString(
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + const string* default_ptr = &DefaultRaw<ArenaStringPtr>(field).Get();
|
| if (field->containing_oneof() && !HasOneofField(*message, field)) {
|
| ClearOneof(message, field->containing_oneof());
|
| MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault(
|
| @@ -1579,7 +1576,8 @@ Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
|
|
|
| if (field->is_extension()) {
|
| return static_cast<Message*>(
|
| - MutableExtensionSet(message)->ReleaseMessage(field, factory));
|
| + MutableExtensionSet(message)->UnsafeArenaReleaseMessage(field,
|
| + factory));
|
| } else {
|
| ClearBit(message, field);
|
| if (field->containing_oneof()) {
|
| @@ -1727,11 +1725,10 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
|
| } else {
|
| // Trigger transform for MapField
|
| if (IsMapFieldInApi(field)) {
|
| - return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
|
| - offsets_[field->index()])
|
| + return MutableRawNonOneof<MapFieldBase>(message, field)
|
| ->MutableRepeatedField();
|
| }
|
| - return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
| + return MutableRawNonOneof<void>(message, field);
|
| }
|
| }
|
|
|
| @@ -1758,11 +1755,9 @@ const void* GeneratedMessageReflection::GetRawRepeatedField(
|
| } else {
|
| // Trigger transform for MapField
|
| if (IsMapFieldInApi(field)) {
|
| - return &(reinterpret_cast<const MapFieldBase*>(
|
| - reinterpret_cast<const uint8*>(&message) +
|
| - offsets_[field->index()])->GetRepeatedField());
|
| + return &(GetRawNonOneof<MapFieldBase>(message, field).GetRepeatedField());
|
| }
|
| - return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()];
|
| + return &GetRawNonOneof<char>(message, field);
|
| }
|
| }
|
|
|
| @@ -1844,7 +1839,7 @@ int GeneratedMessageReflection::MapSize(
|
|
|
| const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
|
| const string& name) const {
|
| - if (extensions_offset_ == -1) return NULL;
|
| + if (!schema_.HasExtensionSet()) return NULL;
|
|
|
| const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
|
| if (result != NULL && result->containing_type() == descriptor_) {
|
| @@ -1856,7 +1851,8 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
|
| const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
|
| if (type != NULL) {
|
| // Look for a matching extension in the foreign type's scope.
|
| - for (int i = 0; i < type->extension_count(); i++) {
|
| + const int type_extension_count = type->extension_count();
|
| + for (int i = 0; i < type_extension_count; i++) {
|
| const FieldDescriptor* extension = type->extension(i);
|
| if (extension->containing_type() == descriptor_ &&
|
| extension->type() == FieldDescriptor::TYPE_MESSAGE &&
|
| @@ -1874,7 +1870,7 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
|
|
|
| const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
|
| int number) const {
|
| - if (extensions_offset_ == -1) return NULL;
|
| + if (!schema_.HasExtensionSet()) return NULL;
|
| return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
|
| }
|
|
|
| @@ -1887,204 +1883,176 @@ bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
|
|
|
| // These simple template accessors obtain pointers (or references) to
|
| // the given field.
|
| +
|
| +template <class Type>
|
| +const Type& GeneratedMessageReflection::GetRawNonOneof(
|
| + const Message& message, const FieldDescriptor* field) const {
|
| + return GetConstRefAtOffset<Type>(message,
|
| + schema_.GetFieldOffsetNonOneof(field));
|
| +}
|
| +
|
| +template <class Type>
|
| +Type* GeneratedMessageReflection::MutableRawNonOneof(
|
| + Message* message, const FieldDescriptor* field) const {
|
| + return GetPointerAtOffset<Type>(message,
|
| + schema_.GetFieldOffsetNonOneof(field));
|
| +}
|
| +
|
| template <typename Type>
|
| -inline const Type& GeneratedMessageReflection::GetRaw(
|
| +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_[index];
|
| - return *reinterpret_cast<const Type*>(ptr);
|
| + return GetConstRefAtOffset<Type>(message, schema_.GetFieldOffset(field));
|
| }
|
|
|
| template <typename Type>
|
| -inline Type* GeneratedMessageReflection::MutableRaw(
|
| - Message* message, const FieldDescriptor* field) const {
|
| - 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);
|
| +Type* GeneratedMessageReflection::MutableRaw(Message* message,
|
| + const FieldDescriptor* field) const {
|
| + return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field));
|
| }
|
|
|
| -template <typename Type>
|
| -inline const Type& GeneratedMessageReflection::DefaultRaw(
|
| - const FieldDescriptor* field) const {
|
| - 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);
|
| + GOOGLE_DCHECK(schema_.HasHasbits());
|
| + return &GetConstRefAtOffset<uint32>(message, schema_.HasBitsOffset());
|
| }
|
| +
|
| 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);
|
| + GOOGLE_DCHECK(schema_.HasHasbits());
|
| + return GetPointerAtOffset<uint32>(message, schema_.HasBitsOffset());
|
| }
|
|
|
| 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()];
|
| + const Message& message, const OneofDescriptor* oneof_descriptor) const {
|
| + return GetConstRefAtOffset<uint32>(
|
| + message, schema_.GetOneofCaseOffset(oneof_descriptor));
|
| }
|
|
|
| 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()]);
|
| + Message* message, const OneofDescriptor* oneof_descriptor) const {
|
| + return GetPointerAtOffset<uint32>(
|
| + message, schema_.GetOneofCaseOffset(oneof_descriptor));
|
| }
|
|
|
| inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
|
| const Message& message) const {
|
| - GOOGLE_DCHECK_NE(extensions_offset_, -1);
|
| - const void* ptr = reinterpret_cast<const uint8*>(&message) +
|
| - extensions_offset_;
|
| - return *reinterpret_cast<const ExtensionSet*>(ptr);
|
| + return GetConstRefAtOffset<ExtensionSet>(message,
|
| + schema_.GetExtensionSetOffset());
|
| }
|
| +
|
| inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
|
| Message* message) const {
|
| - GOOGLE_DCHECK_NE(extensions_offset_, -1);
|
| - void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_;
|
| - return reinterpret_cast<ExtensionSet*>(ptr);
|
| + return GetPointerAtOffset<ExtensionSet>(message,
|
| + schema_.GetExtensionSetOffset());
|
| }
|
|
|
| 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);
|
| + return GetInternalMetadataWithArena(*message).arena();
|
| }
|
|
|
| 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);
|
| + return GetConstRefAtOffset<InternalMetadataWithArena>(
|
| + message, schema_.GetMetadataOffset());
|
| }
|
|
|
| inline InternalMetadataWithArena*
|
| GeneratedMessageReflection::MutableInternalMetadataWithArena(
|
| Message* message) const {
|
| - void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
|
| - return reinterpret_cast<InternalMetadataWithArena*>(ptr);
|
| + return GetPointerAtOffset<InternalMetadataWithArena>(
|
| + message, schema_.GetMetadataOffset());
|
| }
|
|
|
| -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);
|
| +template <typename Type>
|
| +inline const Type& GeneratedMessageReflection::DefaultRaw(
|
| + const FieldDescriptor* field) const {
|
| + return *reinterpret_cast<const Type*>(schema_.GetFieldDefault(field));
|
| }
|
|
|
| // 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;
|
| - }
|
| + if (schema_.HasHasbits()) {
|
| + return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field));
|
| + }
|
| +
|
| + // 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 !schema_.IsDefaultInstance(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: {
|
| + return GetField<ArenaStringPtr>(message, field).Get().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 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
|
| + break;
|
| }
|
| + GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
|
| + return false;
|
| }
|
| - 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) {
|
| + if (!schema_.HasHasbits()) {
|
| return;
|
| }
|
| - MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
|
| + const uint32 index = schema_.HasBitIndex(field);
|
| + MutableHasBits(message)[index / 32] |=
|
| + (static_cast<uint32>(1) << (index % 32));
|
| }
|
|
|
| inline void GeneratedMessageReflection::ClearBit(
|
| Message* message, const FieldDescriptor* field) const {
|
| - if (has_bits_offset_ == -1) {
|
| + if (!schema_.HasHasbits()) {
|
| return;
|
| }
|
| - MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
|
| + const uint32 index = schema_.HasBitIndex(field);
|
| + MutableHasBits(message)[index / 32] &=
|
| + ~(static_cast<uint32>(1) << (index % 32));
|
| }
|
|
|
| inline void GeneratedMessageReflection::SwapBit(
|
| Message* message1, Message* message2, const FieldDescriptor* field) const {
|
| - if (has_bits_offset_ == -1) {
|
| + if (!schema_.HasHasbits()) {
|
| return;
|
| }
|
| bool temp_has_bit = HasBit(*message1, field);
|
| @@ -2125,7 +2093,7 @@ inline void GeneratedMessageReflection::ClearOneofField(
|
| 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
|
| + // it. It will be much faster if an application switches a lot from
|
| // a few oneof fields. Time/space tradeoff
|
| uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
|
| if (oneof_case > 0) {
|
| @@ -2137,7 +2105,7 @@ inline void GeneratedMessageReflection::ClearOneof(
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| const string* default_ptr =
|
| - &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
|
| + &DefaultRaw<ArenaStringPtr>(field).Get();
|
| MutableField<ArenaStringPtr>(message, field)->
|
| Destroy(default_ptr, GetArena(message));
|
| break;
|
| @@ -2249,7 +2217,7 @@ void* GeneratedMessageReflection::RepeatedFieldData(
|
| return MutableExtensionSet(message)->MutableRawRepeatedField(
|
| field->number(), field->type(), field->is_packed(), field);
|
| } else {
|
| - return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
| + return MutableRawNonOneof<char>(message, field);
|
| }
|
| }
|
|
|
| @@ -2261,56 +2229,165 @@ MapFieldBase* GeneratedMessageReflection::MapData(
|
| 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 {
|
| +
|
| +// Helper function to transform migration schema into reflection schema.
|
| +ReflectionSchema MigrationToReflectionSchema(
|
| + const DefaultInstanceData* default_instance_data, const uint32* offsets,
|
| + MigrationSchema migration_schema) {
|
| + ReflectionSchema result;
|
| + result.default_instance_ = default_instance_data->default_instance;
|
| + // First 5 offsets are offsets to the special fields. The following offsets
|
| + // are the proto fields.
|
| + result.offsets_ = offsets + migration_schema.offsets_index + 4;
|
| + result.has_bit_indices_ = offsets + migration_schema.has_bit_indices_index;
|
| + result.has_bits_offset_ = offsets[migration_schema.offsets_index + 0];
|
| + result.metadata_offset_ = offsets[migration_schema.offsets_index + 1];
|
| + result.extensions_offset_ = offsets[migration_schema.offsets_index + 2];
|
| + result.default_oneof_instance_ = default_instance_data->default_oneof_instance;
|
| + result.oneof_case_offset_ = offsets[migration_schema.offsets_index + 3];
|
| + result.object_size_ = migration_schema.object_size;
|
| + return result;
|
| +}
|
| +
|
| +ReflectionSchema MigrationToReflectionSchema(
|
| + const DefaultInstanceData* default_instance_data, const uint32* offsets,
|
| + ReflectionSchema schema) {
|
| + return schema;
|
| +}
|
| +
|
| +template<typename Schema>
|
| +class AssignDescriptorsHelper {
|
| + public:
|
| + AssignDescriptorsHelper(MessageFactory* factory,
|
| + Metadata* file_level_metadata,
|
| + const EnumDescriptor** file_level_enum_descriptors,
|
| + const Schema* schemas,
|
| + const DefaultInstanceData* default_instance_data,
|
| + const uint32* offsets)
|
| + : factory_(factory),
|
| + file_level_metadata_(file_level_metadata),
|
| + file_level_enum_descriptors_(file_level_enum_descriptors),
|
| + schemas_(schemas),
|
| + default_instance_data_(default_instance_data),
|
| + offsets_(offsets) {}
|
| +
|
| + void AssignMessageDescriptor(const Descriptor* descriptor) {
|
| + for (int i = 0; i < descriptor->nested_type_count(); i++) {
|
| + AssignMessageDescriptor(descriptor->nested_type(i));
|
| + }
|
| +
|
| + file_level_metadata_->descriptor = descriptor;
|
| +
|
| + if (!descriptor->options().map_entry()) {
|
| + // Only set reflection for non map types.
|
| + file_level_metadata_->reflection = new GeneratedMessageReflection(
|
| + descriptor, MigrationToReflectionSchema(default_instance_data_++,
|
| + offsets_, *schemas_),
|
| + ::google::protobuf::DescriptorPool::generated_pool(), factory_);
|
| + for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
| + AssignEnumDescriptor(descriptor->enum_type(i));
|
| + }
|
| + schemas_++;
|
| + }
|
| + file_level_metadata_++;
|
| + }
|
| +
|
| + void AssignEnumDescriptor(const EnumDescriptor* descriptor) {
|
| + *file_level_enum_descriptors_ = descriptor;
|
| + file_level_enum_descriptors_++;
|
| + }
|
| +
|
| + private:
|
| + MessageFactory* factory_;
|
| + Metadata* file_level_metadata_;
|
| + const EnumDescriptor** file_level_enum_descriptors_;
|
| + const Schema* schemas_;
|
| + const DefaultInstanceData* default_instance_data_;
|
| + const uint32* offsets_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +void AssignDescriptors(
|
| + const string& filename, const MigrationSchema* schemas,
|
| + const DefaultInstanceData* default_instance_data, const uint32* offsets,
|
| + MessageFactory* factory,
|
| + // update the following descriptor arrays.
|
| + Metadata* file_level_metadata,
|
| + const EnumDescriptor** file_level_enum_descriptors,
|
| + const ServiceDescriptor** file_level_service_descriptors) {
|
| + const ::google::protobuf::FileDescriptor* file =
|
| + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(filename);
|
| + GOOGLE_CHECK(file != NULL);
|
| +
|
| + if (!factory) factory = MessageFactory::generated_factory();
|
| +
|
| + AssignDescriptorsHelper<MigrationSchema> helper(factory, file_level_metadata,
|
| + file_level_enum_descriptors, schemas,
|
| + default_instance_data, offsets);
|
| +
|
| + for (int i = 0; i < file->message_type_count(); i++) {
|
| + helper.AssignMessageDescriptor(file->message_type(i));
|
| + }
|
| +
|
| + for (int i = 0; i < file->enum_type_count(); i++) {
|
| + helper.AssignEnumDescriptor(file->enum_type(i));
|
| + }
|
| + if (file->options().cc_generic_services()) {
|
| + for (int i = 0; i < file->service_count(); i++) {
|
| + file_level_service_descriptors[i] = file->service(i);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void AssignDescriptors(
|
| + const string& filename, const ReflectionSchema* schemas,
|
| + MessageFactory* factory,
|
| + // update the following descriptor arrays.
|
| + Metadata* file_level_metadata,
|
| + const EnumDescriptor** file_level_enum_descriptors,
|
| + const ServiceDescriptor** file_level_service_descriptors) {
|
| + const ::google::protobuf::FileDescriptor* file =
|
| + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(filename);
|
| + GOOGLE_CHECK(file != NULL);
|
| +
|
| + if (!factory) factory = MessageFactory::generated_factory();
|
| +
|
| + AssignDescriptorsHelper<ReflectionSchema> helper(factory, file_level_metadata,
|
| + file_level_enum_descriptors, schemas,
|
| + NULL, NULL);
|
| +
|
| + for (int i = 0; i < file->message_type_count(); i++) {
|
| + helper.AssignMessageDescriptor(file->message_type(i));
|
| + }
|
| +
|
| + for (int i = 0; i < file->enum_type_count(); i++) {
|
| + helper.AssignEnumDescriptor(file->enum_type(i));
|
| + }
|
| + if (file->options().cc_generic_services()) {
|
| + for (int i = 0; i < file->service_count(); i++) {
|
| + file_level_service_descriptors[i] = file->service(i);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) {
|
| + for (int i = 0; i < size; i++) {
|
| + const GeneratedMessageReflection* reflection =
|
| + static_cast<const GeneratedMessageReflection*>(
|
| + file_level_metadata[i].reflection);
|
| + if (reflection) {
|
| + // It's not a map type
|
| + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
| + file_level_metadata[i].descriptor,
|
| + reflection->schema_.default_instance_);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void RegisterAllTypes(const Metadata* file_level_metadata, int size) {
|
| + RegisterAllTypesInternal(file_level_metadata, size);
|
| }
|
|
|
| } // namespace internal
|
|
|