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 08742232237ef2e8994b58c6ea48936b40aad1a5..2313181cc995220fe39ce23236e365b467e05276 100644 |
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc |
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc |
@@ -44,7 +44,6 @@ |
#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 |
@@ -85,22 +84,6 @@ 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) { |
@@ -190,24 +173,61 @@ static void ReportReflectionUsageEnumTypeError( |
// =================================================================== |
GeneratedMessageReflection::GeneratedMessageReflection( |
- 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_) { |
+ 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) { |
} |
GeneratedMessageReflection::~GeneratedMessageReflection() {} |
@@ -235,33 +255,39 @@ 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(); |
- } else { |
+ } |
+ 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 { |
- return MutableInternalMetadataWithArena(message)->mutable_unknown_fields(); |
+ 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); |
} |
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 = schema_.GetObjectSize(); |
+ int total_size = object_size_; |
total_size += GetUnknownFields(message).SpaceUsedExcludingSelf(); |
- if (schema_.HasExtensionSet()) { |
+ if (extensions_offset_ != -1) { |
total_size += GetExtensionSet(message).SpaceUsedExcludingSelf(); |
} |
- const int field_count = descriptor_->field_count(); |
- for (int i = 0; i < field_count; i++) { |
+ for (int i = 0; i < descriptor_->field_count(); i++) { |
const FieldDescriptor* field = descriptor_->field(i); |
if (field->is_repeated()) { |
@@ -330,9 +356,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(); |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
const string* ptr = |
- &GetField<ArenaStringPtr>(message, field).Get(); |
+ &GetField<ArenaStringPtr>(message, field).Get(default_ptr); |
if (ptr != default_ptr) { |
// string fields are represented by just a pointer, so also |
@@ -346,7 +372,7 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { |
} |
case FieldDescriptor::CPPTYPE_MESSAGE: |
- if (schema_.IsDefaultInstance(message)) { |
+ if (&message == default_instance_) { |
// For singular fields, the prototype just stores a pointer to the |
// external type's prototype, so there is no extra memory usage. |
} else { |
@@ -468,9 +494,9 @@ void GeneratedMessageReflection::SwapField( |
string1->Swap(string2); |
} else { |
const string* default_ptr = |
- &DefaultRaw<ArenaStringPtr>(field).Get(); |
- const string temp = string1->Get(); |
- string1->Set(default_ptr, string2->Get(), arena1); |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
+ const string temp = string1->Get(default_ptr); |
+ string1->Set(default_ptr, string2->Get(default_ptr), arena1); |
string2->Set(default_ptr, temp, arena2); |
} |
} |
@@ -631,16 +657,16 @@ void GeneratedMessageReflection::Swap( |
// Slow copy path. |
// Use our arena as temp space, if available. |
Message* temp = message1->New(GetArena(message1)); |
- temp->MergeFrom(*message2); |
- message2->CopyFrom(*message1); |
- Swap(message1, temp); |
+ temp->MergeFrom(*message1); |
+ message1->CopyFrom(*message2); |
+ message2->CopyFrom(*temp); |
if (GetArena(message1) == NULL) { |
delete temp; |
} |
return; |
} |
- if (schema_.HasHasbits()) { |
+ if (has_bits_offset_ != -1) { |
uint32* has_bits1 = MutableHasBits(message1); |
uint32* has_bits2 = MutableHasBits(message2); |
int has_bits_size = (descriptor_->field_count() + 31) / 32; |
@@ -650,20 +676,18 @@ void GeneratedMessageReflection::Swap( |
} |
} |
- const int field_count = descriptor_->field_count(); |
- for (int i = 0; i < field_count; i++) { |
+ for (int i = 0; i < descriptor_->field_count(); i++) { |
const FieldDescriptor* field = descriptor_->field(i); |
if (!field->containing_oneof()) { |
SwapField(message1, message2, field); |
} |
} |
- const int oneof_decl_count = descriptor_->oneof_decl_count(); |
- for (int i = 0; i < oneof_decl_count; i++) { |
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
SwapOneofField(message1, message2, descriptor_->oneof_decl(i)); |
} |
- if (schema_.HasExtensionSet()) { |
+ if (extensions_offset_ != -1) { |
MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); |
} |
@@ -673,7 +697,7 @@ void GeneratedMessageReflection::Swap( |
void GeneratedMessageReflection::SwapFields( |
Message* message1, |
Message* message2, |
- const std::vector<const FieldDescriptor*>& fields) const { |
+ const vector<const FieldDescriptor*>& fields) const { |
if (message1 == message2) return; |
// TODO(kenton): Other Reflection methods should probably check this too. |
@@ -694,8 +718,7 @@ void GeneratedMessageReflection::SwapFields( |
std::set<int> swapped_oneof; |
- const int fields_size = static_cast<int>(fields.size()); |
- for (int i = 0; i < fields_size; i++) { |
+ for (int i = 0; i < fields.size(); i++) { |
const FieldDescriptor* field = fields[i]; |
if (field->is_extension()) { |
MutableExtensionSet(message1)->SwapExtension( |
@@ -817,9 +840,9 @@ void GeneratedMessageReflection::ClearField( |
default: // TODO(kenton): Support other string reps. |
case FieldOptions::STRING: { |
const string* default_ptr = |
- &DefaultRaw<ArenaStringPtr>(field).Get(); |
- MutableRaw<ArenaStringPtr>(message, field)->SetAllocated( |
- default_ptr, NULL, GetArena(message)); |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
+ MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr, |
+ GetArena(message)); |
break; |
} |
} |
@@ -827,7 +850,7 @@ void GeneratedMessageReflection::ClearField( |
} |
case FieldDescriptor::CPPTYPE_MESSAGE: |
- if (!schema_.HasHasbits()) { |
+ 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) { |
@@ -1003,60 +1026,35 @@ 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, |
- std::vector<const FieldDescriptor*>* output) const { |
+ vector<const FieldDescriptor*>* output) const { |
output->clear(); |
// Optimization: The default instance never has any fields set. |
- 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++) { |
+ 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()) { |
if (FieldSize(message, field) > 0) { |
output->push_back(field); |
} |
} else { |
- 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])) { |
+ if (field->containing_oneof()) { |
+ if (HasOneofField(message, field)) { |
output->push_back(field); |
} |
- } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit. |
+ } else if (HasBit(message, field)) { |
output->push_back(field); |
} |
} |
} |
- if (schema_.HasExtensionSet()) { |
+ if (extensions_offset_ != -1) { |
GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_, |
output); |
} |
@@ -1150,7 +1148,9 @@ string GeneratedMessageReflection::GetString( |
switch (field->options().ctype()) { |
default: // TODO(kenton): Support other string reps. |
case FieldOptions::STRING: { |
- return GetField<ArenaStringPtr>(message, field).Get(); |
+ const string* default_ptr = |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr); |
} |
} |
@@ -1170,7 +1170,9 @@ const string& GeneratedMessageReflection::GetStringReference( |
switch (field->options().ctype()) { |
default: // TODO(kenton): Support other string reps. |
case FieldOptions::STRING: { |
- return GetField<ArenaStringPtr>(message, field).Get(); |
+ const string* default_ptr = |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr); |
} |
} |
@@ -1191,7 +1193,8 @@ 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(); |
+ 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( |
@@ -1576,8 +1579,7 @@ Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage( |
if (field->is_extension()) { |
return static_cast<Message*>( |
- MutableExtensionSet(message)->UnsafeArenaReleaseMessage(field, |
- factory)); |
+ MutableExtensionSet(message)->ReleaseMessage(field, factory)); |
} else { |
ClearBit(message, field); |
if (field->containing_oneof()) { |
@@ -1725,10 +1727,11 @@ void* GeneratedMessageReflection::MutableRawRepeatedField( |
} else { |
// Trigger transform for MapField |
if (IsMapFieldInApi(field)) { |
- return MutableRawNonOneof<MapFieldBase>(message, field) |
+ return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) + |
+ offsets_[field->index()]) |
->MutableRepeatedField(); |
} |
- return MutableRawNonOneof<void>(message, field); |
+ return reinterpret_cast<uint8*>(message) + offsets_[field->index()]; |
} |
} |
@@ -1755,9 +1758,11 @@ const void* GeneratedMessageReflection::GetRawRepeatedField( |
} else { |
// Trigger transform for MapField |
if (IsMapFieldInApi(field)) { |
- return &(GetRawNonOneof<MapFieldBase>(message, field).GetRepeatedField()); |
+ return &(reinterpret_cast<const MapFieldBase*>( |
+ reinterpret_cast<const uint8*>(&message) + |
+ offsets_[field->index()])->GetRepeatedField()); |
} |
- return &GetRawNonOneof<char>(message, field); |
+ return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()]; |
} |
} |
@@ -1839,7 +1844,7 @@ int GeneratedMessageReflection::MapSize( |
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( |
const string& name) const { |
- if (!schema_.HasExtensionSet()) return NULL; |
+ if (extensions_offset_ == -1) return NULL; |
const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name); |
if (result != NULL && result->containing_type() == descriptor_) { |
@@ -1851,8 +1856,7 @@ 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. |
- const int type_extension_count = type->extension_count(); |
- for (int i = 0; i < type_extension_count; i++) { |
+ 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 && |
@@ -1870,7 +1874,7 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( |
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( |
int number) const { |
- if (!schema_.HasExtensionSet()) return NULL; |
+ if (extensions_offset_ == -1) return NULL; |
return descriptor_pool_->FindExtensionByNumber(descriptor_, number); |
} |
@@ -1883,176 +1887,204 @@ 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> |
-const Type& GeneratedMessageReflection::GetRaw( |
+inline const Type& GeneratedMessageReflection::GetRaw( |
const Message& message, const FieldDescriptor* field) const { |
if (field->containing_oneof() && !HasOneofField(message, field)) { |
return DefaultRaw<Type>(field); |
} |
- return GetConstRefAtOffset<Type>(message, schema_.GetFieldOffset(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); |
} |
template <typename Type> |
-Type* GeneratedMessageReflection::MutableRaw(Message* message, |
- const FieldDescriptor* field) const { |
- return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field)); |
+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); |
} |
+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 { |
- GOOGLE_DCHECK(schema_.HasHasbits()); |
- return &GetConstRefAtOffset<uint32>(message, schema_.HasBitsOffset()); |
+ 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 { |
- GOOGLE_DCHECK(schema_.HasHasbits()); |
- return GetPointerAtOffset<uint32>(message, schema_.HasBitsOffset()); |
+ 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 { |
- return GetConstRefAtOffset<uint32>( |
- message, schema_.GetOneofCaseOffset(oneof_descriptor)); |
+ 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 { |
- return GetPointerAtOffset<uint32>( |
- message, schema_.GetOneofCaseOffset(oneof_descriptor)); |
+ 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 { |
- return GetConstRefAtOffset<ExtensionSet>(message, |
- schema_.GetExtensionSetOffset()); |
+ GOOGLE_DCHECK_NE(extensions_offset_, -1); |
+ const void* ptr = reinterpret_cast<const uint8*>(&message) + |
+ extensions_offset_; |
+ return *reinterpret_cast<const ExtensionSet*>(ptr); |
} |
- |
inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet( |
Message* message) const { |
- return GetPointerAtOffset<ExtensionSet>(message, |
- schema_.GetExtensionSetOffset()); |
+ GOOGLE_DCHECK_NE(extensions_offset_, -1); |
+ void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_; |
+ return reinterpret_cast<ExtensionSet*>(ptr); |
} |
inline Arena* GeneratedMessageReflection::GetArena(Message* message) const { |
- return GetInternalMetadataWithArena(*message).arena(); |
+ 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 { |
- return GetConstRefAtOffset<InternalMetadataWithArena>( |
- message, schema_.GetMetadataOffset()); |
+ const void* ptr = reinterpret_cast<const uint8*>(&message) + arena_offset_; |
+ return *reinterpret_cast<const InternalMetadataWithArena*>(ptr); |
} |
inline InternalMetadataWithArena* |
GeneratedMessageReflection::MutableInternalMetadataWithArena( |
Message* message) const { |
- return GetPointerAtOffset<InternalMetadataWithArena>( |
- message, schema_.GetMetadataOffset()); |
+ void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_; |
+ return reinterpret_cast<InternalMetadataWithArena*>(ptr); |
} |
-template <typename Type> |
-inline const Type& GeneratedMessageReflection::DefaultRaw( |
- const FieldDescriptor* field) const { |
- return *reinterpret_cast<const Type*>(schema_.GetFieldDefault(field)); |
+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 (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; |
+ 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 |
- 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 |
+ GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit()."; |
+ 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 (!schema_.HasHasbits()) { |
+ if (has_bits_offset_ == -1) { |
return; |
} |
- const uint32 index = schema_.HasBitIndex(field); |
- MutableHasBits(message)[index / 32] |= |
- (static_cast<uint32>(1) << (index % 32)); |
+ MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32)); |
} |
inline void GeneratedMessageReflection::ClearBit( |
Message* message, const FieldDescriptor* field) const { |
- if (!schema_.HasHasbits()) { |
+ if (has_bits_offset_ == -1) { |
return; |
} |
- const uint32 index = schema_.HasBitIndex(field); |
- MutableHasBits(message)[index / 32] &= |
- ~(static_cast<uint32>(1) << (index % 32)); |
+ MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32)); |
} |
inline void GeneratedMessageReflection::SwapBit( |
Message* message1, Message* message2, const FieldDescriptor* field) const { |
- if (!schema_.HasHasbits()) { |
+ if (has_bits_offset_ == -1) { |
return; |
} |
bool temp_has_bit = HasBit(*message1, field); |
@@ -2093,7 +2125,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 application switches a lot from |
+ // 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) { |
@@ -2105,7 +2137,7 @@ inline void GeneratedMessageReflection::ClearOneof( |
default: // TODO(kenton): Support other string reps. |
case FieldOptions::STRING: { |
const string* default_ptr = |
- &DefaultRaw<ArenaStringPtr>(field).Get(); |
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL); |
MutableField<ArenaStringPtr>(message, field)-> |
Destroy(default_ptr, GetArena(message)); |
break; |
@@ -2217,7 +2249,7 @@ void* GeneratedMessageReflection::RepeatedFieldData( |
return MutableExtensionSet(message)->MutableRawRepeatedField( |
field->number(), field->type(), field->is_packed(), field); |
} else { |
- return MutableRawNonOneof<char>(message, field); |
+ return reinterpret_cast<uint8*>(message) + offsets_[field->index()]; |
} |
} |
@@ -2229,165 +2261,56 @@ MapFieldBase* GeneratedMessageReflection::MapData( |
return MutableRaw<MapFieldBase>(message, field); |
} |
-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); |
+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 |