// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. #include #include #include #include #include #include #include #include #include #include #include #include #include #define GOOGLE_PROTOBUF_HAS_ONEOF namespace google { namespace protobuf { namespace internal { namespace { bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } } // anonymous namespace bool ParseNamedEnum(const EnumDescriptor* descriptor, const string& name, int* value) { const EnumValueDescriptor* d = descriptor->FindValueByName(name); if (d == NULL) return false; *value = d->number(); return true; } const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); return (d == NULL ? GetEmptyString() : d->name()); } // =================================================================== // Helpers for reporting usage errors (e.g. trying to use GetInt32() on // a string field). namespace { template To* GetPointerAtOffset(Message* message, uint32 offset) { return reinterpret_cast(reinterpret_cast(message) + offset); } template const To* GetConstPointerAtOffset(const Message* message, uint32 offset) { return reinterpret_cast(reinterpret_cast(message) + offset); } template const To& GetConstRefAtOffset(const Message& message, uint32 offset) { return *GetConstPointerAtOffset(&message, offset); } void ReportReflectionUsageError( const Descriptor* descriptor, const FieldDescriptor* field, const char* method, const char* description) { GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" " Method : google::protobuf::Reflection::" << method << "\n" " Message type: " << descriptor->full_name() << "\n" " Field : " << field->full_name() << "\n" " Problem : " << description; } const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = { "INVALID_CPPTYPE", "CPPTYPE_INT32", "CPPTYPE_INT64", "CPPTYPE_UINT32", "CPPTYPE_UINT64", "CPPTYPE_DOUBLE", "CPPTYPE_FLOAT", "CPPTYPE_BOOL", "CPPTYPE_ENUM", "CPPTYPE_STRING", "CPPTYPE_MESSAGE" }; static void ReportReflectionUsageTypeError( const Descriptor* descriptor, const FieldDescriptor* field, const char* method, FieldDescriptor::CppType expected_type) { GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" " Method : google::protobuf::Reflection::" << method << "\n" " Message type: " << descriptor->full_name() << "\n" " Field : " << field->full_name() << "\n" " Problem : Field is not the right type for this message:\n" " Expected : " << cpptype_names_[expected_type] << "\n" " Field type: " << cpptype_names_[field->cpp_type()]; } static void ReportReflectionUsageEnumTypeError( const Descriptor* descriptor, const FieldDescriptor* field, const char* method, const EnumValueDescriptor* value) { GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" " Method : google::protobuf::Reflection::" << method << "\n" " Message type: " << descriptor->full_name() << "\n" " Field : " << field->full_name() << "\n" " Problem : Enum value did not match field type:\n" " Expected : " << field->enum_type()->full_name() << "\n" " Actual : " << value->full_name(); } #define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \ if (!(CONDITION)) \ ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION) #define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \ USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION) #define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \ USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION) #define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \ if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \ ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \ FieldDescriptor::CPPTYPE_##CPPTYPE) #define USAGE_CHECK_ENUM_VALUE(METHOD) \ if (value->type() != field->enum_type()) \ ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value) #define USAGE_CHECK_MESSAGE_TYPE(METHOD) \ USAGE_CHECK_EQ(field->containing_type(), descriptor_, \ METHOD, "Field does not match message type."); #define USAGE_CHECK_SINGULAR(METHOD) \ USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ "Field is repeated; the method requires a singular field.") #define USAGE_CHECK_REPEATED(METHOD) \ USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ "Field is singular; the method requires a repeated field.") #define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \ USAGE_CHECK_MESSAGE_TYPE(METHOD); \ USAGE_CHECK_##LABEL(METHOD); \ USAGE_CHECK_TYPE(METHOD, CPPTYPE) } // namespace // =================================================================== 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), last_non_weak_field_index_(-1) { last_non_weak_field_index_ = descriptor_->field_count() - 1; } GeneratedMessageReflection::~GeneratedMessageReflection() {} const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( const Message& message) const { if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && !GetProto3PreserveUnknownsDefault()) { // We have to ensure that any mutations made to the return value of // MutableUnknownFields() are not reflected here when Proto3 defaults to // discard unknowns. return *UnknownFieldSet::default_instance(); } else { return GetInternalMetadataWithArena(message).unknown_fields(); } } UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields( Message* message) const { return MutableInternalMetadataWithArena(message)->mutable_unknown_fields(); } size_t GeneratedMessageReflection::SpaceUsedLong(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. size_t total_size = schema_.GetObjectSize(); total_size += GetUnknownFields(message).SpaceUsedExcludingSelfLong(); if (schema_.HasExtensionSet()) { total_size += GetExtensionSet(message).SpaceUsedExcludingSelfLong(); } for (int i = 0; i <= last_non_weak_field_index_; i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { switch (field->cpp_type()) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case FieldDescriptor::CPPTYPE_##UPPERCASE : \ total_size += GetRaw >(message, field) \ .SpaceUsedExcludingSelfLong(); \ break HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE( FLOAT, float); HANDLE_TYPE( BOOL, bool); HANDLE_TYPE( ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: total_size += GetRaw >(message, field) .SpaceUsedExcludingSelfLong(); break; } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { total_size += GetRaw(message, field) .SpaceUsedExcludingSelfLong(); } else { // We don't know which subclass of RepeatedPtrFieldBase the type is, // so we use RepeatedPtrFieldBase directly. total_size += GetRaw(message, field) .SpaceUsedExcludingSelfLong >(); } break; } } else { if (field->containing_oneof() && !HasOneofField(message, field)) { continue; } switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32 : case FieldDescriptor::CPPTYPE_INT64 : case FieldDescriptor::CPPTYPE_UINT32: case FieldDescriptor::CPPTYPE_UINT64: case FieldDescriptor::CPPTYPE_DOUBLE: case FieldDescriptor::CPPTYPE_FLOAT : case FieldDescriptor::CPPTYPE_BOOL : case FieldDescriptor::CPPTYPE_ENUM : // Field is inline, so we've already counted it. break; case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { if (IsInlined(field)) { const string* ptr = &GetField(message, field).GetNoArena(); total_size += StringSpaceUsedExcludingSelfLong(*ptr); break; } // 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(field).Get(); const string* ptr = &GetField(message, field).Get(); if (ptr != default_ptr) { // string fields are represented by just a pointer, so also // include sizeof(string) as well. total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelfLong(*ptr); } break; } } break; } case FieldDescriptor::CPPTYPE_MESSAGE: 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 { const Message* sub_message = GetRaw(message, field); if (sub_message != NULL) { total_size += sub_message->SpaceUsedLong(); } } break; } } } return total_size; } void GeneratedMessageReflection::SwapField( Message* message1, Message* message2, const FieldDescriptor* field) const { if (field->is_repeated()) { switch (field->cpp_type()) { #define SWAP_ARRAYS(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ MutableRaw >(message1, field)->Swap( \ MutableRaw >(message2, field)); \ break; SWAP_ARRAYS(INT32 , int32 ); SWAP_ARRAYS(INT64 , int64 ); SWAP_ARRAYS(UINT32, uint32); SWAP_ARRAYS(UINT64, uint64); SWAP_ARRAYS(FLOAT , float ); SWAP_ARRAYS(DOUBLE, double); SWAP_ARRAYS(BOOL , bool ); SWAP_ARRAYS(ENUM , int ); #undef SWAP_ARRAYS case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: MutableRaw(message1, field)-> Swap >( MutableRaw(message2, field)); break; } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { MutableRaw(message1, field)-> MutableRepeatedField()-> Swap >( MutableRaw(message2, field)-> MutableRepeatedField()); } else { MutableRaw(message1, field)-> Swap >( MutableRaw(message2, field)); } break; default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); } } else { switch (field->cpp_type()) { #define SWAP_VALUES(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ std::swap(*MutableRaw(message1, field), \ *MutableRaw(message2, field)); \ break; SWAP_VALUES(INT32 , int32 ); SWAP_VALUES(INT64 , int64 ); SWAP_VALUES(UINT32, uint32); SWAP_VALUES(UINT64, uint64); SWAP_VALUES(FLOAT , float ); SWAP_VALUES(DOUBLE, double); SWAP_VALUES(BOOL , bool ); SWAP_VALUES(ENUM , int ); #undef SWAP_VALUES case FieldDescriptor::CPPTYPE_MESSAGE: if (GetArena(message1) == GetArena(message2)) { std::swap(*MutableRaw(message1, field), *MutableRaw(message2, field)); } else { Message** sub_msg1 = MutableRaw(message1, field); Message** sub_msg2 = MutableRaw(message2, field); if (*sub_msg1 == NULL && *sub_msg2 == NULL) break; if (*sub_msg1 && *sub_msg2) { (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2); break; } if (*sub_msg1 == NULL) { *sub_msg1 = (*sub_msg2)->New(message1->GetArena()); (*sub_msg1)->CopyFrom(**sub_msg2); ClearField(message2, field); } else { *sub_msg2 = (*sub_msg1)->New(message2->GetArena()); (*sub_msg2)->CopyFrom(**sub_msg1); ClearField(message1, field); } } break; case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { Arena* arena1 = GetArena(message1); Arena* arena2 = GetArena(message2); if (IsInlined(field)) { InlinedStringField* string1 = MutableRaw(message1, field); InlinedStringField* string2 = MutableRaw(message2, field); string1->Swap(string2); break; } ArenaStringPtr* string1 = MutableRaw(message1, field); ArenaStringPtr* string2 = MutableRaw(message2, field); const string* default_ptr = &DefaultRaw(field).Get(); if (arena1 == arena2) { string1->Swap(string2, default_ptr, arena1); } else { const string temp = string1->Get(); string1->Set(default_ptr, string2->Get(), arena1); string2->Set(default_ptr, temp, arena2); } } break; } break; default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); } } } void GeneratedMessageReflection::SwapOneofField( Message* message1, Message* message2, const OneofDescriptor* oneof_descriptor) const { uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor); uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor); int32 temp_int32; int64 temp_int64; uint32 temp_uint32; uint64 temp_uint64; float temp_float; double temp_double; bool temp_bool; int temp_int; Message* temp_message = NULL; string temp_string; // Stores message1's oneof field to a temp variable. const FieldDescriptor* field1 = NULL; if (oneof_case1 > 0) { field1 = descriptor_->FindFieldByNumber(oneof_case1); //oneof_descriptor->field(oneof_case1); switch (field1->cpp_type()) { #define GET_TEMP_VALUE(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ temp_##TYPE = GetField(*message1, field1); \ break; GET_TEMP_VALUE(INT32 , int32 ); GET_TEMP_VALUE(INT64 , int64 ); GET_TEMP_VALUE(UINT32, uint32); GET_TEMP_VALUE(UINT64, uint64); GET_TEMP_VALUE(FLOAT , float ); GET_TEMP_VALUE(DOUBLE, double); GET_TEMP_VALUE(BOOL , bool ); GET_TEMP_VALUE(ENUM , int ); #undef GET_TEMP_VALUE case FieldDescriptor::CPPTYPE_MESSAGE: temp_message = ReleaseMessage(message1, field1); break; case FieldDescriptor::CPPTYPE_STRING: temp_string = GetString(*message1, field1); break; default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); } } // Sets message1's oneof field from the message2's oneof field. if (oneof_case2 > 0) { const FieldDescriptor* field2 = descriptor_->FindFieldByNumber(oneof_case2); switch (field2->cpp_type()) { #define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ SetField(message1, field2, GetField(*message2, field2)); \ break; SET_ONEOF_VALUE1(INT32 , int32 ); SET_ONEOF_VALUE1(INT64 , int64 ); SET_ONEOF_VALUE1(UINT32, uint32); SET_ONEOF_VALUE1(UINT64, uint64); SET_ONEOF_VALUE1(FLOAT , float ); SET_ONEOF_VALUE1(DOUBLE, double); SET_ONEOF_VALUE1(BOOL , bool ); SET_ONEOF_VALUE1(ENUM , int ); #undef SET_ONEOF_VALUE1 case FieldDescriptor::CPPTYPE_MESSAGE: SetAllocatedMessage(message1, ReleaseMessage(message2, field2), field2); break; case FieldDescriptor::CPPTYPE_STRING: SetString(message1, field2, GetString(*message2, field2)); break; default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type(); } } else { ClearOneof(message1, oneof_descriptor); } // Sets message2's oneof field from the temp variable. if (oneof_case1 > 0) { switch (field1->cpp_type()) { #define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ SetField(message2, field1, temp_##TYPE); \ break; SET_ONEOF_VALUE2(INT32 , int32 ); SET_ONEOF_VALUE2(INT64 , int64 ); SET_ONEOF_VALUE2(UINT32, uint32); SET_ONEOF_VALUE2(UINT64, uint64); SET_ONEOF_VALUE2(FLOAT , float ); SET_ONEOF_VALUE2(DOUBLE, double); SET_ONEOF_VALUE2(BOOL , bool ); SET_ONEOF_VALUE2(ENUM , int ); #undef SET_ONEOF_VALUE2 case FieldDescriptor::CPPTYPE_MESSAGE: SetAllocatedMessage(message2, temp_message, field1); break; case FieldDescriptor::CPPTYPE_STRING: SetString(message2, field1, temp_string); break; default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); } } else { ClearOneof(message2, oneof_descriptor); } } void GeneratedMessageReflection::Swap( Message* message1, Message* message2) const { if (message1 == message2) return; // TODO(kenton): Other Reflection methods should probably check this too. GOOGLE_CHECK_EQ(message1->GetReflection(), this) << "First argument to Swap() (of type \"" << message1->GetDescriptor()->full_name() << "\") is not compatible with this reflection object (which is for type \"" << descriptor_->full_name() << "\"). Note that the exact same class is required; not just the same " "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) << "Second argument to Swap() (of type \"" << message2->GetDescriptor()->full_name() << "\") is not compatible with this reflection object (which is for type \"" << descriptor_->full_name() << "\"). Note that the exact same class is required; not just the same " "descriptor."; // 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(*message2); message2->CopyFrom(*message1); Swap(message1, temp); if (GetArena(message1) == NULL) { delete temp; } return; } if (schema_.HasHasbits()) { uint32* has_bits1 = MutableHasBits(message1); uint32* has_bits2 = MutableHasBits(message2); int fields_with_has_bits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated() || field->containing_oneof()) { continue; } fields_with_has_bits++; } int has_bits_size = (fields_with_has_bits + 31) / 32; for (int i = 0; i < has_bits_size; i++) { std::swap(has_bits1[i], has_bits2[i]); } } for (int i = 0; i <= last_non_weak_field_index_; i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->containing_oneof()) continue; SwapField(message1, message2, field); } 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 (schema_.HasExtensionSet()) { MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); } MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); } void GeneratedMessageReflection::SwapFields( Message* message1, Message* message2, const std::vector& fields) const { if (message1 == message2) return; // TODO(kenton): Other Reflection methods should probably check this too. GOOGLE_CHECK_EQ(message1->GetReflection(), this) << "First argument to SwapFields() (of type \"" << message1->GetDescriptor()->full_name() << "\") is not compatible with this reflection object (which is for type \"" << descriptor_->full_name() << "\"). Note that the exact same class is required; not just the same " "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) << "Second argument to SwapFields() (of type \"" << message2->GetDescriptor()->full_name() << "\") is not compatible with this reflection object (which is for type \"" << descriptor_->full_name() << "\"). Note that the exact same class is required; not just the same " "descriptor."; std::set swapped_oneof; const int fields_size = static_cast(fields.size()); for (int i = 0; i < fields_size; i++) { const FieldDescriptor* field = fields[i]; if (field->is_extension()) { MutableExtensionSet(message1)->SwapExtension( MutableExtensionSet(message2), field->number()); } else { if (field->containing_oneof()) { int oneof_index = field->containing_oneof()->index(); // Only swap the oneof field once. if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) { continue; } swapped_oneof.insert(oneof_index); SwapOneofField(message1, message2, field->containing_oneof()); } else { // Swap has bit for non-repeated fields. We have already checked for // oneof already. if (!field->is_repeated()) { SwapBit(message1, message2, field); } // Swap field. SwapField(message1, message2, field); } } } } // ------------------------------------------------------------------- bool GeneratedMessageReflection::HasField(const Message& message, const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(HasField); USAGE_CHECK_SINGULAR(HasField); if (field->is_extension()) { return GetExtensionSet(message).Has(field->number()); } else { if (field->containing_oneof()) { return HasOneofField(message, field); } else { return HasBit(message, field); } } } int GeneratedMessageReflection::FieldSize(const Message& message, const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(FieldSize); USAGE_CHECK_REPEATED(FieldSize); if (field->is_extension()) { return GetExtensionSet(message).ExtensionSize(field->number()); } else { switch (field->cpp_type()) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case FieldDescriptor::CPPTYPE_##UPPERCASE : \ return GetRaw >(message, field).size() HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE( FLOAT, float); HANDLE_TYPE( BOOL, bool); HANDLE_TYPE( ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { const internal::MapFieldBase& map = GetRaw(message, field); if (map.IsRepeatedFieldValid()) { return map.GetRepeatedField().size(); } else { // No need to materialize the repeated field if it is out of sync: // its size will be the same as the map's size. return map.size(); } } else { return GetRaw(message, field).size(); } } GOOGLE_LOG(FATAL) << "Can't get here."; return 0; } } void GeneratedMessageReflection::ClearField( Message* message, const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(ClearField); if (field->is_extension()) { MutableExtensionSet(message)->ClearExtension(field->number()); } else if (!field->is_repeated()) { if (field->containing_oneof()) { ClearOneofField(message, field); return; } if (HasBit(*message, field)) { ClearBit(message, field); // We need to set the field back to its default value. switch (field->cpp_type()) { #define CLEAR_TYPE(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ *MutableRaw(message, field) = \ field->default_value_##TYPE(); \ break; CLEAR_TYPE(INT32 , int32 ); CLEAR_TYPE(INT64 , int64 ); CLEAR_TYPE(UINT32, uint32); CLEAR_TYPE(UINT64, uint64); CLEAR_TYPE(FLOAT , float ); CLEAR_TYPE(DOUBLE, double); CLEAR_TYPE(BOOL , bool ); #undef CLEAR_TYPE case FieldDescriptor::CPPTYPE_ENUM: *MutableRaw(message, field) = field->default_value_enum()->number(); break; case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { if (IsInlined(field)) { const string* default_ptr = &DefaultRaw(field).GetNoArena(); MutableRaw(message, field)->SetNoArena( default_ptr, *default_ptr); break; } const string* default_ptr = &DefaultRaw(field).Get(); MutableRaw(message, field)->SetAllocated( default_ptr, NULL, GetArena(message)); break; } } break; } case FieldDescriptor::CPPTYPE_MESSAGE: 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) { delete *MutableRaw(message, field); } *MutableRaw(message, field) = NULL; } else { (*MutableRaw(message, field))->Clear(); } break; } } } else { switch (field->cpp_type()) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case FieldDescriptor::CPPTYPE_##UPPERCASE : \ MutableRaw >(message, field)->Clear(); \ break HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE( FLOAT, float); HANDLE_TYPE( BOOL, bool); HANDLE_TYPE( ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: MutableRaw >(message, field)->Clear(); break; } break; } case FieldDescriptor::CPPTYPE_MESSAGE: { if (IsMapFieldInApi(field)) { MutableRaw(message, field) ->MutableRepeatedField() ->Clear >(); } else { // We don't know which subclass of RepeatedPtrFieldBase the type is, // so we use RepeatedPtrFieldBase directly. MutableRaw(message, field) ->Clear >(); } break; } } } } void GeneratedMessageReflection::RemoveLast( Message* message, const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(RemoveLast); USAGE_CHECK_REPEATED(RemoveLast); if (field->is_extension()) { MutableExtensionSet(message)->RemoveLast(field->number()); } else { switch (field->cpp_type()) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case FieldDescriptor::CPPTYPE_##UPPERCASE : \ MutableRaw >(message, field)->RemoveLast(); \ break HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE( FLOAT, float); HANDLE_TYPE( BOOL, bool); HANDLE_TYPE( ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: MutableRaw >(message, field)->RemoveLast(); break; } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { MutableRaw(message, field) ->MutableRepeatedField() ->RemoveLast >(); } else { MutableRaw(message, field) ->RemoveLast >(); } break; } } } Message* GeneratedMessageReflection::ReleaseLast( Message* message, const FieldDescriptor* field) const { USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE); if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->ReleaseLast(field->number())); } else { if (IsMapFieldInApi(field)) { return MutableRaw(message, field) ->MutableRepeatedField() ->ReleaseLast >(); } else { return MutableRaw(message, field) ->ReleaseLast >(); } } } void GeneratedMessageReflection::SwapElements( Message* message, const FieldDescriptor* field, int index1, int index2) const { USAGE_CHECK_MESSAGE_TYPE(Swap); USAGE_CHECK_REPEATED(Swap); if (field->is_extension()) { MutableExtensionSet(message)->SwapElements(field->number(), index1, index2); } else { switch (field->cpp_type()) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case FieldDescriptor::CPPTYPE_##UPPERCASE : \ MutableRaw >(message, field) \ ->SwapElements(index1, index2); \ break HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE( FLOAT, float); HANDLE_TYPE( BOOL, bool); HANDLE_TYPE( ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { MutableRaw(message, field) ->MutableRepeatedField() ->SwapElements(index1, index2); } else { MutableRaw(message, field) ->SwapElements(index1, index2); } break; } } } namespace { // Comparison functor for sorting FieldDescriptors by field number. struct FieldNumberSorter { bool operator()(const FieldDescriptor* left, const FieldDescriptor* right) const { return left->number() < right->number(); } }; inline bool IsIndexInHasBitSet( const uint32* has_bit_set, uint32 has_bit_index) { GOOGLE_DCHECK_NE(has_bit_index, ~0u); return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) & static_cast(1)) != 0; } } // namespace void GeneratedMessageReflection::ListFields( const Message& message, std::vector* 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 = GetConstPointerAtOffset(&message, schema_.oneof_case_offset_); output->reserve(descriptor_->field_count()); for (int i = 0; i <= last_non_weak_field_index_; 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])) { output->push_back(field); } } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit. output->push_back(field); } } } if (schema_.HasExtensionSet()) { GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_, output); } // ListFields() must sort output by field number. std::sort(output->begin(), output->end(), FieldNumberSorter()); } // ------------------------------------------------------------------- #undef DEFINE_PRIMITIVE_ACCESSORS #define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \ const Message& message, const FieldDescriptor* field) const { \ USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ if (field->is_extension()) { \ return GetExtensionSet(message).Get##TYPENAME( \ field->number(), field->default_value_##PASSTYPE()); \ } else { \ return GetField(message, field); \ } \ } \ \ void GeneratedMessageReflection::Set##TYPENAME( \ Message* message, const FieldDescriptor* field, \ PASSTYPE value) const { \ USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ if (field->is_extension()) { \ return MutableExtensionSet(message)->Set##TYPENAME( \ field->number(), field->type(), value, field); \ } else { \ SetField(message, field, value); \ } \ } \ \ PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \ const Message& message, \ const FieldDescriptor* field, int index) const { \ USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ if (field->is_extension()) { \ return GetExtensionSet(message).GetRepeated##TYPENAME( \ field->number(), index); \ } else { \ return GetRepeatedField(message, field, index); \ } \ } \ \ void GeneratedMessageReflection::SetRepeated##TYPENAME( \ Message* message, const FieldDescriptor* field, \ int index, PASSTYPE value) const { \ USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ if (field->is_extension()) { \ MutableExtensionSet(message)->SetRepeated##TYPENAME( \ field->number(), index, value); \ } else { \ SetRepeatedField(message, field, index, value); \ } \ } \ \ void GeneratedMessageReflection::Add##TYPENAME( \ Message* message, const FieldDescriptor* field, \ PASSTYPE value) const { \ USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ if (field->is_extension()) { \ MutableExtensionSet(message)->Add##TYPENAME( \ field->number(), field->type(), field->options().packed(), value, \ field); \ } else { \ AddField(message, field, value); \ } \ } DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 ) DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 ) DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32) DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64) DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT ) DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE) DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL ) #undef DEFINE_PRIMITIVE_ACCESSORS // ------------------------------------------------------------------- string GeneratedMessageReflection::GetString( const Message& message, const FieldDescriptor* field) const { USAGE_CHECK_ALL(GetString, SINGULAR, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { if (IsInlined(field)) { return GetField(message, field).GetNoArena(); } return GetField(message, field).Get(); } } } } const string& GeneratedMessageReflection::GetStringReference( const Message& message, const FieldDescriptor* field, string* scratch) const { USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { if (IsInlined(field)) { return GetField(message, field).GetNoArena(); } return GetField(message, field).Get(); } } } } void GeneratedMessageReflection::SetString( Message* message, const FieldDescriptor* field, const string& value) const { USAGE_CHECK_ALL(SetString, SINGULAR, STRING); if (field->is_extension()) { return MutableExtensionSet(message)->SetString(field->number(), field->type(), value, field); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { if (IsInlined(field)) { MutableField(message, field)->SetNoArena( NULL, value); break; } const string* default_ptr = &DefaultRaw(field).Get(); if (field->containing_oneof() && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); MutableField(message, field)->UnsafeSetDefault( default_ptr); } MutableField(message, field)->Set(default_ptr, value, GetArena(message)); break; } } } } string GeneratedMessageReflection::GetRepeatedString( const Message& message, const FieldDescriptor* field, int index) const { USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: return GetRepeatedPtrField(message, field, index); } } } const string& GeneratedMessageReflection::GetRepeatedStringReference( const Message& message, const FieldDescriptor* field, int index, string* scratch) const { USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: return GetRepeatedPtrField(message, field, index); } } } void GeneratedMessageReflection::SetRepeatedString( Message* message, const FieldDescriptor* field, int index, const string& value) const { USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING); if (field->is_extension()) { MutableExtensionSet(message)->SetRepeatedString( field->number(), index, value); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: *MutableRepeatedField(message, field, index) = value; break; } } } void GeneratedMessageReflection::AddString( Message* message, const FieldDescriptor* field, const string& value) const { USAGE_CHECK_ALL(AddString, REPEATED, STRING); if (field->is_extension()) { MutableExtensionSet(message)->AddString(field->number(), field->type(), value, field); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: *AddField(message, field) = value; break; } } } // ------------------------------------------------------------------- inline bool CreateUnknownEnumValues(const FileDescriptor* file) { return file->syntax() == FileDescriptor::SYNTAX_PROTO3; } const EnumValueDescriptor* GeneratedMessageReflection::GetEnum( const Message& message, const FieldDescriptor* field) const { // 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); int32 value; if (field->is_extension()) { value = GetExtensionSet(message).GetEnum( field->number(), field->default_value_enum()->number()); } else { value = GetField(message, field); } return value; } void GeneratedMessageReflection::SetEnum( Message* message, const FieldDescriptor* field, const EnumValueDescriptor* value) const { // 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, field); } else { SetField(message, field, value); } } const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum( const Message& message, const FieldDescriptor* field, int index) const { // 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()) { value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index); } else { value = GetRepeatedField(message, field, index); } return value; } void GeneratedMessageReflection::SetRepeatedEnum( Message* message, const FieldDescriptor* field, int index, const EnumValueDescriptor* value) const { // 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); } else { SetRepeatedField(message, field, index, value); } } void GeneratedMessageReflection::AddEnum( Message* message, const FieldDescriptor* field, const EnumValueDescriptor* value) const { // 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, field); } else { AddField(message, field, value); } } // ------------------------------------------------------------------- const Message& GeneratedMessageReflection::GetMessage( const Message& message, const FieldDescriptor* field, MessageFactory* factory) const { USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); if (factory == NULL) factory = message_factory_; if (field->is_extension()) { return static_cast( GetExtensionSet(message).GetMessage( field->number(), field->message_type(), factory)); } else { const Message* result = GetRaw(message, field); if (result == NULL) { result = DefaultRaw(field); } return *result; } } Message* GeneratedMessageReflection::MutableMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); if (factory == NULL) factory = message_factory_; if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->MutableMessage(field, factory)); } else { Message* result; Message** result_holder = MutableRaw(message, field); if (field->containing_oneof()) { if (!HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); result_holder = MutableField(message, field); const Message* default_message = DefaultRaw(field); *result_holder = default_message->New(message->GetArena()); } } else { SetBit(message, field); } if (*result_holder == NULL) { const Message* default_message = DefaultRaw(field); *result_holder = default_message->New(message->GetArena()); } result = *result_holder; return result; } } void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage( Message* message, Message* sub_message, const FieldDescriptor* field) const { USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE); if (field->is_extension()) { MutableExtensionSet(message)->UnsafeArenaSetAllocatedMessage( field->number(), field->type(), field, sub_message); } else { if (field->containing_oneof()) { if (sub_message == NULL) { ClearOneof(message, field->containing_oneof()); return; } ClearOneof(message, field->containing_oneof()); *MutableRaw(message, field) = sub_message; SetOneofCase(message, field); return; } if (sub_message == NULL) { ClearBit(message, field); } else { SetBit(message, field); } Message** sub_message_holder = MutableRaw(message, field); if (GetArena(message) == NULL) { delete *sub_message_holder; } *sub_message_holder = sub_message; } } void GeneratedMessageReflection::SetAllocatedMessage( Message* message, Message* sub_message, const FieldDescriptor* field) const { // If message and sub-message are in different memory ownership domains // (different arenas, or one is on heap and one is not), then we may need to // do a copy. if (sub_message != NULL && sub_message->GetArena() != message->GetArena()) { if (sub_message->GetArena() == NULL && message->GetArena() != NULL) { // Case 1: parent is on an arena and child is heap-allocated. We can add // the child to the arena's Own() list to free on arena destruction, then // set our pointer. message->GetArena()->Own(sub_message); UnsafeArenaSetAllocatedMessage(message, sub_message, field); } else { // Case 2: all other cases. We need to make a copy. MutableMessage() will // either get the existing message object, or instantiate a new one as // appropriate w.r.t. our arena. Message* sub_message_copy = MutableMessage(message, field); sub_message_copy->CopyFrom(*sub_message); } } else { // Same memory ownership domains. UnsafeArenaSetAllocatedMessage(message, sub_message, field); } } Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE); if (factory == NULL) factory = message_factory_; if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->UnsafeArenaReleaseMessage(field, factory)); } else { if (!(field->is_repeated() || field->containing_oneof())) { ClearBit(message, field); } if (field->containing_oneof()) { if (HasOneofField(*message, field)) { *MutableOneofCase(message, field->containing_oneof()) = 0; } else { return NULL; } } Message** result = MutableRaw(message, field); Message* ret = *result; *result = NULL; return ret; } } 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); if (field->is_extension()) { return static_cast( GetExtensionSet(message).GetRepeatedMessage(field->number(), index)); } else { if (IsMapFieldInApi(field)) { return GetRaw(message, field) .GetRepeatedField() .Get >(index); } else { return GetRaw(message, field) .Get >(index); } } } Message* GeneratedMessageReflection::MutableRepeatedMessage( Message* message, const FieldDescriptor* field, int index) const { USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->MutableRepeatedMessage( field->number(), index)); } else { if (IsMapFieldInApi(field)) { return MutableRaw(message, field) ->MutableRepeatedField() ->Mutable >(index); } else { return MutableRaw(message, field) ->Mutable >(index); } } } Message* GeneratedMessageReflection::AddMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); if (factory == NULL) factory = message_factory_; if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->AddMessage(field, factory)); } else { Message* result = NULL; // We can't use AddField() because RepeatedPtrFieldBase doesn't // know how to allocate one. RepeatedPtrFieldBase* repeated = NULL; if (IsMapFieldInApi(field)) { repeated = MutableRaw(message, field)->MutableRepeatedField(); } else { repeated = MutableRaw(message, field); } result = repeated->AddFromCleared >(); if (result == NULL) { // We must allocate a new object. const Message* prototype; if (repeated->size() == 0) { prototype = factory->GetPrototype(field->message_type()); } else { prototype = &repeated->Get >(0); } 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 >(result); } return result; } } void GeneratedMessageReflection::AddAllocatedMessage( Message* message, const FieldDescriptor* field, Message* new_entry) const { USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE); if (field->is_extension()) { MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry); } else { RepeatedPtrFieldBase* repeated = NULL; if (IsMapFieldInApi(field)) { repeated = MutableRaw(message, field)->MutableRepeatedField(); } else { repeated = MutableRaw(message, field); } repeated->AddAllocated >(new_entry); } } void* GeneratedMessageReflection::MutableRawRepeatedField( Message* message, const FieldDescriptor* field, FieldDescriptor::CppType cpptype, int ctype, const Descriptor* desc) const { USAGE_CHECK_REPEATED("MutableRawRepeatedField"); if (field->cpp_type() != cpptype) ReportReflectionUsageTypeError(descriptor_, field, "MutableRawRepeatedField", cpptype); if (ctype >= 0) GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; if (desc != NULL) GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) { return MutableExtensionSet(message)->MutableRawRepeatedField( field->number(), field->type(), field->is_packed(), field); } else { // Trigger transform for MapField if (IsMapFieldInApi(field)) { return MutableRawNonOneof(message, field) ->MutableRepeatedField(); } return MutableRawNonOneof(message, field); } } const void* GeneratedMessageReflection::GetRawRepeatedField( const Message& message, const FieldDescriptor* field, FieldDescriptor::CppType cpptype, int ctype, const Descriptor* desc) const { USAGE_CHECK_REPEATED("GetRawRepeatedField"); if (field->cpp_type() != cpptype) ReportReflectionUsageTypeError(descriptor_, field, "GetRawRepeatedField", cpptype); if (ctype >= 0) GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; if (desc != NULL) GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) { // Should use extension_set::GetRawRepeatedField. However, the required // parameter "default repeated value" is not very easy to get here. // Map is not supported in extensions, it is acceptable to use // extension_set::MutableRawRepeatedField which does not change the message. return MutableExtensionSet(const_cast(&message)) ->MutableRawRepeatedField( field->number(), field->type(), field->is_packed(), field); } else { // Trigger transform for MapField if (IsMapFieldInApi(field)) { return &(GetRawNonOneof(message, field).GetRepeatedField()); } return &GetRawNonOneof(message, field); } } const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( const Message& message, const OneofDescriptor* oneof_descriptor) const { uint32 field_number = GetOneofCase(message, oneof_descriptor); if (field_number == 0) { return NULL; } return descriptor_->FindFieldByNumber(field_number); } bool GeneratedMessageReflection::ContainsMapKey( const Message& message, const FieldDescriptor* field, const MapKey& key) const { USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue", "Field is not a map field."); return GetRaw(message, field).ContainsMapKey(key); } bool GeneratedMessageReflection::InsertOrLookupMapValue( Message* message, const FieldDescriptor* field, const MapKey& key, MapValueRef* val) const { USAGE_CHECK(IsMapFieldInApi(field), "InsertOrLookupMapValue", "Field is not a map field."); val->SetType(field->message_type()->FindFieldByName("value")->cpp_type()); return MutableRaw(message, field)->InsertOrLookupMapValue( key, val); } bool GeneratedMessageReflection::DeleteMapValue( Message* message, const FieldDescriptor* field, const MapKey& key) const { USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue", "Field is not a map field."); return MutableRaw(message, field)->DeleteMapValue(key); } MapIterator GeneratedMessageReflection::MapBegin( Message* message, const FieldDescriptor* field) const { USAGE_CHECK(IsMapFieldInApi(field), "MapBegin", "Field is not a map field."); MapIterator iter(message, field); GetRaw(*message, field).MapBegin(&iter); return iter; } MapIterator GeneratedMessageReflection::MapEnd( Message* message, const FieldDescriptor* field) const { USAGE_CHECK(IsMapFieldInApi(field), "MapEnd", "Field is not a map field."); MapIterator iter(message, field); GetRaw(*message, field).MapEnd(&iter); return iter; } int GeneratedMessageReflection::MapSize( const Message& message, const FieldDescriptor* field) const { USAGE_CHECK(IsMapFieldInApi(field), "MapSize", "Field is not a map field."); return GetRaw(message, field).size(); } // ----------------------------------------------------------------------------- const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( const string& name) const { if (!schema_.HasExtensionSet()) return NULL; const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name); if (result != NULL && result->containing_type() == descriptor_) { return result; } if (descriptor_->options().message_set_wire_format()) { // MessageSet extensions may be identified by type name. 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++) { const FieldDescriptor* extension = type->extension(i); if (extension->containing_type() == descriptor_ && extension->type() == FieldDescriptor::TYPE_MESSAGE && extension->is_optional() && extension->message_type() == type) { // Found it. return extension; } } } } return NULL; } const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( int number) const { if (!schema_.HasExtensionSet()) return NULL; return descriptor_pool_->FindExtensionByNumber(descriptor_, number); } bool GeneratedMessageReflection::SupportsUnknownEnumValues() const { return CreateUnknownEnumValues(descriptor_->file()); } // =================================================================== // Some private helpers. // These simple template accessors obtain pointers (or references) to // the given field. template const Type& GeneratedMessageReflection::GetRawNonOneof( const Message& message, const FieldDescriptor* field) const { return GetConstRefAtOffset(message, schema_.GetFieldOffsetNonOneof(field)); } template Type* GeneratedMessageReflection::MutableRawNonOneof( Message* message, const FieldDescriptor* field) const { return GetPointerAtOffset(message, schema_.GetFieldOffsetNonOneof(field)); } template const Type& GeneratedMessageReflection::GetRaw( const Message& message, const FieldDescriptor* field) const { if (field->containing_oneof() && !HasOneofField(message, field)) { return DefaultRaw(field); } return GetConstRefAtOffset(message, schema_.GetFieldOffset(field)); } bool GeneratedMessageReflection::IsInlined(const FieldDescriptor* field) const { return schema_.IsFieldInlined(field); } template Type* GeneratedMessageReflection::MutableRaw(Message* message, const FieldDescriptor* field) const { return GetPointerAtOffset(message, schema_.GetFieldOffset(field)); } inline const uint32* GeneratedMessageReflection::GetHasBits( const Message& message) const { GOOGLE_DCHECK(schema_.HasHasbits()); return &GetConstRefAtOffset(message, schema_.HasBitsOffset()); } inline uint32* GeneratedMessageReflection::MutableHasBits( Message* message) const { GOOGLE_DCHECK(schema_.HasHasbits()); return GetPointerAtOffset(message, schema_.HasBitsOffset()); } inline uint32 GeneratedMessageReflection::GetOneofCase( const Message& message, const OneofDescriptor* oneof_descriptor) const { return GetConstRefAtOffset( message, schema_.GetOneofCaseOffset(oneof_descriptor)); } inline uint32* GeneratedMessageReflection::MutableOneofCase( Message* message, const OneofDescriptor* oneof_descriptor) const { return GetPointerAtOffset( message, schema_.GetOneofCaseOffset(oneof_descriptor)); } inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet( const Message& message) const { return GetConstRefAtOffset(message, schema_.GetExtensionSetOffset()); } inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet( Message* message) const { return GetPointerAtOffset(message, schema_.GetExtensionSetOffset()); } inline Arena* GeneratedMessageReflection::GetArena(Message* message) const { return GetInternalMetadataWithArena(*message).arena(); } inline const InternalMetadataWithArena& GeneratedMessageReflection::GetInternalMetadataWithArena( const Message& message) const { return GetConstRefAtOffset( message, schema_.GetMetadataOffset()); } inline InternalMetadataWithArena* GeneratedMessageReflection::MutableInternalMetadataWithArena( Message* message) const { return GetPointerAtOffset( message, schema_.GetMetadataOffset()); } template inline const Type& GeneratedMessageReflection::DefaultRaw( const FieldDescriptor* field) const { return *reinterpret_cast(schema_.GetFieldDefault(field)); } // Simple accessors for manipulating has_bits_. inline bool GeneratedMessageReflection::HasBit( const Message& message, const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); 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(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: { if (IsInlined(field)) { return !GetField(message, field) .GetNoArena().empty(); } return GetField(message, field).Get().size() > 0; } } return false; case FieldDescriptor::CPPTYPE_BOOL: return GetRaw(message, field) != false; case FieldDescriptor::CPPTYPE_INT32: return GetRaw(message, field) != 0; case FieldDescriptor::CPPTYPE_INT64: return GetRaw(message, field) != 0; case FieldDescriptor::CPPTYPE_UINT32: return GetRaw(message, field) != 0; case FieldDescriptor::CPPTYPE_UINT64: return GetRaw(message, field) != 0; case FieldDescriptor::CPPTYPE_FLOAT: return GetRaw(message, field) != 0.0; case FieldDescriptor::CPPTYPE_DOUBLE: return GetRaw(message, field) != 0.0; case FieldDescriptor::CPPTYPE_ENUM: return GetRaw(message, field) != 0; case FieldDescriptor::CPPTYPE_MESSAGE: // handled above; avoid warning break; } GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit()."; return false; } } inline void GeneratedMessageReflection::SetBit( Message* message, const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; } const uint32 index = schema_.HasBitIndex(field); MutableHasBits(message)[index / 32] |= (static_cast(1) << (index % 32)); } inline void GeneratedMessageReflection::ClearBit( Message* message, const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; } const uint32 index = schema_.HasBitIndex(field); MutableHasBits(message)[index / 32] &= ~(static_cast(1) << (index % 32)); } inline void GeneratedMessageReflection::SwapBit( Message* message1, Message* message2, const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; } bool temp_has_bit = HasBit(*message1, field); if (HasBit(*message2, field)) { SetBit(message1, field); } else { ClearBit(message1, field); } if (temp_has_bit) { SetBit(message2, field); } else { ClearBit(message2, field); } } inline bool GeneratedMessageReflection::HasOneof( const Message& message, const OneofDescriptor* oneof_descriptor) const { return (GetOneofCase(message, oneof_descriptor) > 0); } inline bool GeneratedMessageReflection::HasOneofField( const Message& message, const FieldDescriptor* field) const { return (GetOneofCase(message, field->containing_oneof()) == field->number()); } inline void GeneratedMessageReflection::SetOneofCase( Message* message, const FieldDescriptor* field) const { *MutableOneofCase(message, field->containing_oneof()) = field->number(); } inline void GeneratedMessageReflection::ClearOneofField( Message* message, const FieldDescriptor* field) const { if (HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); } } inline void GeneratedMessageReflection::ClearOneof( Message* message, const OneofDescriptor* oneof_descriptor) const { // TODO(jieluo): Consider to cache the unused object instead of deleting // it. It will be much faster if an application switches a lot from // a few oneof fields. Time/space tradeoff uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); if (oneof_case > 0) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); if (GetArena(message) == NULL) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { const string* default_ptr = &DefaultRaw(field).Get(); MutableField(message, field)-> Destroy(default_ptr, GetArena(message)); break; } } break; } case FieldDescriptor::CPPTYPE_MESSAGE: delete *MutableRaw(message, field); break; default: break; } } *MutableOneofCase(message, oneof_descriptor) = 0; } } // Template implementations of basic accessors. Inline because each // template instance is only called from one location. These are // used for all types except messages. template inline const Type& GeneratedMessageReflection::GetField( const Message& message, const FieldDescriptor* field) const { return GetRaw(message, field); } template inline void GeneratedMessageReflection::SetField( Message* message, const FieldDescriptor* field, const Type& value) const { if (field->containing_oneof() && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); } *MutableRaw(message, field) = value; field->containing_oneof() ? SetOneofCase(message, field) : SetBit(message, field); } template inline Type* GeneratedMessageReflection::MutableField( Message* message, const FieldDescriptor* field) const { field->containing_oneof() ? SetOneofCase(message, field) : SetBit(message, field); return MutableRaw(message, field); } template inline const Type& GeneratedMessageReflection::GetRepeatedField( const Message& message, const FieldDescriptor* field, int index) const { return GetRaw >(message, field).Get(index); } template inline const Type& GeneratedMessageReflection::GetRepeatedPtrField( const Message& message, const FieldDescriptor* field, int index) const { return GetRaw >(message, field).Get(index); } template inline void GeneratedMessageReflection::SetRepeatedField( Message* message, const FieldDescriptor* field, int index, Type value) const { MutableRaw >(message, field)->Set(index, value); } template inline Type* GeneratedMessageReflection::MutableRepeatedField( Message* message, const FieldDescriptor* field, int index) const { RepeatedPtrField* repeated = MutableRaw >(message, field); return repeated->Mutable(index); } template inline void GeneratedMessageReflection::AddField( Message* message, const FieldDescriptor* field, const Type& value) const { MutableRaw >(message, field)->Add(value); } template inline Type* GeneratedMessageReflection::AddField( Message* message, const FieldDescriptor* field) const { RepeatedPtrField* repeated = MutableRaw >(message, field); 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 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 MutableRawNonOneof(message, field); } } MapFieldBase* GeneratedMessageReflection::MapData( Message* message, const FieldDescriptor* field) const { USAGE_CHECK(IsMapFieldInApi(field), "GetMapData", "Field is not a map field."); return MutableRaw(message, field); } namespace { // Helper function to transform migration schema into reflection schema. ReflectionSchema MigrationToReflectionSchema( const Message* const* default_instance, const uint32* offsets, MigrationSchema migration_schema) { ReflectionSchema result; result.default_instance_ = *default_instance; // First 6 offsets are offsets to the special fields. The following offsets // are the proto fields. result.offsets_ = offsets + migration_schema.offsets_index + 5; 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.oneof_case_offset_ = offsets[migration_schema.offsets_index + 3]; result.object_size_ = migration_schema.object_size; result.weak_field_map_offset_ = offsets[migration_schema.offsets_index + 4]; return result; } template class AssignDescriptorsHelper { public: AssignDescriptorsHelper(MessageFactory* factory, Metadata* file_level_metadata, const EnumDescriptor** file_level_enum_descriptors, const Schema* schemas, const Message* const* 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; 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_++; default_instance_data_++; file_level_metadata_++; } void AssignEnumDescriptor(const EnumDescriptor* descriptor) { *file_level_enum_descriptors_ = descriptor; file_level_enum_descriptors_++; } const Metadata* GetCurrentMetadataPtr() const { return file_level_metadata_; } private: MessageFactory* factory_; Metadata* file_level_metadata_; const EnumDescriptor** file_level_enum_descriptors_; const Schema* schemas_; const Message* const * default_instance_data_; const uint32* offsets_; }; // We have the routines that assign descriptors and build reflection // automatically delete the allocated reflection. MetadataOwner owns // all the allocated reflection instances. struct MetadataOwner { ~MetadataOwner() { for (auto range : metadata_arrays_) { for (const Metadata* m = range.first; m < range.second; m++) { delete m->reflection; } } } void AddArray(const Metadata* begin, const Metadata* end) { MutexLock lock(&mu_); metadata_arrays_.push_back(std::make_pair(begin, end)); } static MetadataOwner* Instance() { static MetadataOwner* res = OnShutdownDelete(new MetadataOwner); return res; } private: MetadataOwner() = default; // private because singleton Mutex mu_; std::vector > metadata_arrays_; }; } // namespace void AssignDescriptors( const string& filename, const MigrationSchema* schemas, const Message* const* default_instances_, const uint32* offsets, // 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); MessageFactory* factory = MessageFactory::generated_factory(); AssignDescriptorsHelper helper(factory, file_level_metadata, file_level_enum_descriptors, schemas, default_instances_, 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); } } MetadataOwner::Instance()->AddArray( file_level_metadata, helper.GetCurrentMetadataPtr()); } void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) { for (int i = 0; i < size; i++) { const GeneratedMessageReflection* reflection = static_cast( 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); } void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, ::google::protobuf::io::CodedOutputStream* output) { const void* ptr = base + offset; const InternalMetadataWithArena* metadata = static_cast(ptr); if (metadata->have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( metadata->unknown_fields(), output); } } } // namespace internal } // namespace protobuf } // namespace google