diff options
author | Feng Xiao <xfxyjwf@gmail.com> | 2014-11-10 17:34:54 -0800 |
---|---|---|
committer | Feng Xiao <xfxyjwf@gmail.com> | 2014-11-10 17:34:54 -0800 |
commit | 6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e (patch) | |
tree | d17c61ff9f3ae28224fbddac6d26bfc59e2cf755 /src/google/protobuf/generated_message_reflection.cc | |
parent | baca1a8a1aa180c42de6278d3b8286c4496c6a10 (diff) |
Down-integrate from internal code base.
Diffstat (limited to 'src/google/protobuf/generated_message_reflection.cc')
-rw-r--r-- | src/google/protobuf/generated_message_reflection.cc | 458 |
1 files changed, 390 insertions, 68 deletions
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 536de7d9..ea97aebc 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -74,6 +74,19 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { return (d == NULL ? GetEmptyString() : d->name()); } +namespace { +inline bool SupportsArenas(const Descriptor* descriptor) { + // In open-source release we enable arena support by default but as we also + // down-integrate descriptor.pb.(h|cc) from our internal code base which + // hasn't enabled arena support yet, here we need to be able to handle both + // cases for descriptor protos. + if (!Arena::is_arena_constructable<FileDescriptorProto>::type::value) { + return descriptor->name() != "google/protobuf/descriptor.proto"; + } + return true; +} +} // anonymous namespace + // =================================================================== // Helpers for reporting usage errors (e.g. trying to use GetInt32() on // a string field). @@ -177,13 +190,15 @@ GeneratedMessageReflection::GeneratedMessageReflection( int extensions_offset, const DescriptorPool* descriptor_pool, MessageFactory* factory, - int object_size) + int object_size, + int arena_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), object_size_ (object_size), descriptor_pool_ ((descriptor_pool == NULL) ? DescriptorPool::generated_pool() : @@ -202,7 +217,8 @@ GeneratedMessageReflection::GeneratedMessageReflection( int oneof_case_offset, const DescriptorPool* descriptor_pool, MessageFactory* factory, - int object_size) + int object_size, + int arena_offset) : descriptor_ (descriptor), default_instance_ (default_instance), default_oneof_instance_ (default_oneof_instance), @@ -211,6 +227,7 @@ GeneratedMessageReflection::GeneratedMessageReflection( oneof_case_offset_(oneof_case_offset), unknown_fields_offset_(unknown_fields_offset), extensions_offset_(extensions_offset), + arena_offset_ (arena_offset), object_size_ (object_size), descriptor_pool_ ((descriptor_pool == NULL) ? DescriptorPool::generated_pool() : @@ -220,14 +237,39 @@ GeneratedMessageReflection::GeneratedMessageReflection( GeneratedMessageReflection::~GeneratedMessageReflection() {} +namespace { +UnknownFieldSet* empty_unknown_field_set_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_); + +void InitEmptyUnknownFieldSet() { + empty_unknown_field_set_ = new UnknownFieldSet; +} + +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); } @@ -303,12 +345,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 @@ -363,8 +406,9 @@ void GeneratedMessageReflection::SwapField( case FieldDescriptor::CPPTYPE_STRING: case FieldDescriptor::CPPTYPE_MESSAGE: - MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap( - MutableRaw<RepeatedPtrFieldBase>(message2, field)); + MutableRaw<RepeatedPtrFieldBase>(message1, field)-> + Swap<GenericTypeHandler<google::protobuf::Message> >( + MutableRaw<RepeatedPtrFieldBase>(message2, field)); break; default: @@ -396,8 +440,8 @@ void GeneratedMessageReflection::SwapField( switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - std::swap(*MutableRaw<string*>(message1, field), - *MutableRaw<string*>(message2, field)); + MutableRaw<ArenaStringPtr>(message1, field)->Swap( + MutableRaw<ArenaStringPtr>(message2, field)); break; } break; @@ -549,12 +593,29 @@ 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++) { @@ -715,17 +776,13 @@ 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; } @@ -994,8 +1051,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."; @@ -1013,8 +1073,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."; @@ -1034,16 +1097,15 @@ 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); if (field->containing_oneof() && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); - *MutableField<string*>(message, field) = new string; - } - string** ptr = MutableField<string*>(message, field); - if (*ptr == DefaultRaw<const string*>(field)) { - *ptr = new string(value); - } else { - (*ptr)->assign(value); + MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault( + default_ptr); } + MutableField<ArenaStringPtr>(message, field)->Set(default_ptr, + value, GetArena(message)); break; } } @@ -1125,42 +1187,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 GeneratedMessageReflection::GetEnumValue( + const Message& message, const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM); - int value; + 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()) { @@ -1168,41 +1268,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); } } @@ -1246,7 +1394,7 @@ Message* GeneratedMessageReflection::MutableMessage( ClearOneof(message, field->containing_oneof()); result_holder = MutableField<Message*>(message, field); const Message* default_message = DefaultRaw<const Message*>(field); - *result_holder = default_message->New(); + *result_holder = default_message->New(message->GetArena()); } } else { SetBit(message, field); @@ -1254,14 +1402,14 @@ Message* GeneratedMessageReflection::MutableMessage( 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; } } -void GeneratedMessageReflection::SetAllocatedMessage( +void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage( Message* message, Message* sub_message, const FieldDescriptor* field) const { @@ -1288,12 +1436,42 @@ void GeneratedMessageReflection::SetAllocatedMessage( SetBit(message, field); } Message** sub_message_holder = MutableRaw<Message*>(message, field); - delete *sub_message_holder; + if (GetArena(message) == NULL) { + delete *sub_message_holder; + } *sub_message_holder = sub_message; } } -Message* GeneratedMessageReflection::ReleaseMessage( +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 { @@ -1320,6 +1498,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); @@ -1371,8 +1562,11 @@ 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; } @@ -1445,6 +1639,10 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( return descriptor_pool_->FindExtensionByNumber(descriptor_, number); } +bool GeneratedMessageReflection::SupportsUnknownEnumValues() const { + return CreateUnknownEnumValues(descriptor_->file()); +} + // =================================================================== // Some private helpers. @@ -1487,11 +1685,17 @@ inline const Type& GeneratedMessageReflection::DefaultRaw( 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); } @@ -1525,25 +1729,113 @@ 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); +} + // 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 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); @@ -1591,9 +1883,13 @@ inline void GeneratedMessageReflection::ClearOneof( case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: - delete *MutableRaw<string*>(message, field); + case FieldOptions::STRING: { + const string* default_ptr = + &DefaultRaw<ArenaStringPtr>(field).Get(NULL); + MutableField<ArenaStringPtr>(message, field)-> + Destroy(default_ptr, GetArena(message)); break; + } } break; } @@ -1678,6 +1974,32 @@ 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()]; + } +} + } // namespace internal } // namespace protobuf } // namespace google |