diff options
author | Feng Xiao <xfxyjwf@gmail.com> | 2018-08-08 17:00:41 -0700 |
---|---|---|
committer | Feng Xiao <xfxyjwf@gmail.com> | 2018-08-08 17:00:41 -0700 |
commit | 6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3 (patch) | |
tree | e575738adf52d24b883cca5e8928a5ded31caba1 /src/google/protobuf/message.cc | |
parent | e7746f487cb9cca685ffb1b3d7dccc5554b618a4 (diff) | |
download | protobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.tar.gz protobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.tar.bz2 protobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.zip |
Down-integrate from google3.
Diffstat (limited to 'src/google/protobuf/message.cc')
-rw-r--r-- | src/google/protobuf/message.cc | 581 |
1 files changed, 517 insertions, 64 deletions
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index a536615a..eac70d88 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -34,15 +34,13 @@ #include <iostream> #include <stack> -#include <google/protobuf/stubs/hash.h> +#include <unordered_map> #include <google/protobuf/message.h> #include <google/protobuf/stubs/casts.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/stubs/once.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/reflection_internal.h> #include <google/protobuf/io/coded_stream.h> @@ -50,19 +48,26 @@ #include <google/protobuf/descriptor.h> #include <google/protobuf/generated_message_util.h> #include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> #include <google/protobuf/reflection_ops.h> #include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/singleton.h> #include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/hash.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { -using internal::WireFormat; +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +using internal::ParseClosure; +#endif using internal::ReflectionOps; +using internal::WireFormat; +using internal::WireFormatLite; void Message::MergeFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); @@ -118,9 +123,11 @@ void Message::DiscardUnknownFields() { return ReflectionOps::DiscardUnknownFields(this); } +#if !GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { return WireFormat::ParseAndMergePartial(input, this); } +#endif bool Message::ParseFromFileDescriptor(int file_descriptor) { io::FileInputStream input(file_descriptor); @@ -142,6 +149,449 @@ bool Message::ParsePartialFromIstream(std::istream* input) { return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); } +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +namespace internal { + +class ReflectionAccessor { + public: + static void* GetOffset(void* msg, const proto2::FieldDescriptor* f, + const proto2::Reflection* r) { + auto gr = + dynamic_cast<const proto2::internal::GeneratedMessageReflection*>(r); + GOOGLE_CHECK(gr != nullptr); + return static_cast<char*>(msg) + gr->schema_.GetFieldOffset(f); + } + + static proto2::internal::ExtensionSet* GetExtensionSet( + void* msg, const proto2::Reflection* r) { + auto gr = + dynamic_cast<const proto2::internal::GeneratedMessageReflection*>(r); + GOOGLE_CHECK(gr != nullptr); + return reinterpret_cast<proto2::internal::ExtensionSet*>( + static_cast<char*>(msg) + gr->schema_.GetExtensionSetOffset()); + } + static proto2::internal::InternalMetadataWithArena* GetMetadata( + void* msg, const proto2::Reflection* r) { + auto gr = + dynamic_cast<const proto2::internal::GeneratedMessageReflection*>(r); + GOOGLE_CHECK(gr != nullptr); + return reinterpret_cast<proto2::internal::InternalMetadataWithArena*>( + static_cast<char*>(msg) + gr->schema_.GetMetadataOffset()); + } +}; + +} // namespace internal + +void SetField(uint64 val, const FieldDescriptor* field, Message* msg, + const Reflection* reflection) { +#define STORE_TYPE(CPPTYPE_METHOD) \ + do \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE_METHOD(msg, field, value); \ + } else { \ + reflection->Set##CPPTYPE_METHOD(msg, field, value); \ + } \ + while (0) + + switch (field->type()) { +#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value = val; \ + STORE_TYPE(CPPTYPE_METHOD); \ + break; \ + } + + // Varints + HANDLE_TYPE(INT32, int32, Int32) + HANDLE_TYPE(INT64, int64, Int64) + HANDLE_TYPE(UINT32, uint32, UInt32) + HANDLE_TYPE(UINT64, uint64, UInt64) + case FieldDescriptor::TYPE_SINT32: { + int32 value = WireFormatLite::ZigZagDecode32(val); + STORE_TYPE(Int32); + break; + } + case FieldDescriptor::TYPE_SINT64: { + int64 value = WireFormatLite::ZigZagDecode64(val); + STORE_TYPE(Int64); + break; + } + HANDLE_TYPE(BOOL, bool, Bool) + + // Fixed + HANDLE_TYPE(FIXED32, uint32, UInt32) + HANDLE_TYPE(FIXED64, uint64, UInt64) + HANDLE_TYPE(SFIXED32, int32, Int32) + HANDLE_TYPE(SFIXED64, int64, Int64) + + case FieldDescriptor::TYPE_FLOAT: { + float value; + uint32 bit_rep = val; + std::memcpy(&value, &bit_rep, sizeof(value)); + STORE_TYPE(Float); + break; + } + case FieldDescriptor::TYPE_DOUBLE: { + double value; + uint64 bit_rep = val; + std::memcpy(&value, &bit_rep, sizeof(value)); + STORE_TYPE(Double); + break; + } + case FieldDescriptor::TYPE_ENUM: { + int value = val; + if (field->is_repeated()) { + reflection->AddEnumValue(msg, field, value); + } else { + reflection->SetEnumValue(msg, field, value); + } + break; + } + default: + GOOGLE_LOG(FATAL) << "Error in descriptors, primitve field with field type " + << field->type(); + } +#undef STORE_TYPE +#undef HANDLE_TYPE +} + +bool ReflectiveValidator(const void* arg, int val) { + auto d = static_cast<const EnumDescriptor*>(arg); + return d->FindValueByNumber(val) != nullptr; +} + +ParseClosure GetPackedField(const FieldDescriptor* field, Message* msg, + const Reflection* reflection, + internal::ParseContext* ctx) { + switch (field->type()) { +#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, METHOD_NAME) \ + case FieldDescriptor::TYPE_##TYPE: \ + return {internal::Packed##METHOD_NAME##Parser, \ + reflection->MutableRepeatedField<CPPTYPE>(msg, field)} + HANDLE_PACKED_TYPE(INT32, int32, Int32); + HANDLE_PACKED_TYPE(INT64, int64, Int64); + HANDLE_PACKED_TYPE(SINT32, int32, SInt32); + HANDLE_PACKED_TYPE(SINT64, int64, SInt64); + HANDLE_PACKED_TYPE(UINT32, uint32, UInt32); + HANDLE_PACKED_TYPE(UINT64, uint64, UInt64); + HANDLE_PACKED_TYPE(BOOL, bool, Bool); + case FieldDescriptor::TYPE_ENUM: { + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + auto object = + internal::ReflectionAccessor::GetOffset(msg, field, reflection); + return {internal::PackedEnumParser, object}; + } else { + ctx->extra_parse_data().SetEnumValidatorArg( + ReflectiveValidator, field->enum_type(), + reflection->MutableUnknownFields(msg), field->number()); + auto object = + internal::ReflectionAccessor::GetOffset(msg, field, reflection); + return {internal::PackedValidEnumParserArg, object}; + } + } + HANDLE_PACKED_TYPE(FIXED32, uint32, Fixed32); + HANDLE_PACKED_TYPE(FIXED64, uint64, Fixed64); + HANDLE_PACKED_TYPE(SFIXED32, int32, SFixed32); + HANDLE_PACKED_TYPE(SFIXED64, int64, SFixed64); + HANDLE_PACKED_TYPE(FLOAT, float, Float); + HANDLE_PACKED_TYPE(DOUBLE, double, Double); +#undef HANDLE_PACKED_TYPE + + default: + GOOGLE_LOG(FATAL) << "Type is not packable " << field->type(); + } +} + +ParseClosure GetLenDelim(int field_number, const FieldDescriptor* field, + Message* msg, UnknownFieldSet* unknown, + const Reflection* reflection, + internal::ParseContext* ctx) { + if (field == nullptr || WireFormat::WireTypeForFieldType(field->type()) != + WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (field && field->is_packable()) { + return GetPackedField(field, msg, reflection, ctx); + } + return {internal::StringParser, unknown->AddLengthDelimited(field_number)}; + } + enum { kNone = 0, kVerify, kStrict } utf8_level = kNone; + internal::ParseFunc string_parsers[] = {internal::StringParser, + internal::StringParserUTF8Verify, + internal::StringParserUTF8}; + internal::ParseFunc cord_parsers[] = {internal::CordParser, + internal::CordParserUTF8Verify, + internal::CordParserUTF8}; + internal::ParseFunc string_piece_parsers[] = { + internal::StringPieceParser, internal::StringPieceParserUTF8Verify, + internal::StringPieceParserUTF8}; + switch (field->type()) { + case FieldDescriptor::TYPE_STRING: + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 + ) { + ctx->extra_parse_data().SetFieldName(field->full_name().c_str()); + utf8_level = kStrict; + } else if ( + true) { + ctx->extra_parse_data().SetFieldName(field->full_name().c_str()); + utf8_level = kVerify; + } + GOOGLE_FALLTHROUGH_INTENDED; + case FieldDescriptor::TYPE_BYTES: { + if (field->is_repeated()) { + int index = reflection->FieldSize(*msg, field); + // Add new empty value. + reflection->AddString(msg, field, ""); + if (field->options().ctype() == FieldOptions::STRING || + field->is_extension()) { + auto object = reflection->MutableRepeatedPtrField<string>(msg, field) + ->Mutable(index); + return {string_parsers[utf8_level], object}; + } else if (field->options().ctype() == FieldOptions::CORD) { + auto object = reflection->MutableRepeatedField<Cord>(msg, field) + ->Mutable(index); + return {cord_parsers[utf8_level], object}; + } else if (field->options().ctype() == FieldOptions::STRING_PIECE) { + auto object = + reflection + ->MutableRepeatedPtrField<internal::StringPieceField>(msg, + field) + ->Mutable(index); + return {string_piece_parsers[utf8_level], object}; + } + } else { + // Clear value and make sure it's set. + reflection->SetString(msg, field, ""); + if (field->options().ctype() == FieldOptions::STRING || + field->is_extension()) { + // HACK around inability to get mutable_string in reflection + string* object = &const_cast<string&>( + reflection->GetStringReference(*msg, field, nullptr)); + return {string_parsers[utf8_level], object}; + } else { + void* object = + internal::ReflectionAccessor::GetOffset(msg, field, reflection); + if (field->containing_oneof()) { + object = *static_cast<Cord**>(object); + } + if (field->options().ctype() == FieldOptions::CORD) { + return {cord_parsers[utf8_level], object}; + } else if (field->options().ctype() == FieldOptions::STRING_PIECE) { + return {string_piece_parsers[utf8_level], object}; + } + } + } + GOOGLE_LOG(FATAL) << "No other type than string supported"; + } + case FieldDescriptor::TYPE_MESSAGE: { + Message* object; + if (field->is_repeated()) { + object = reflection->AddMessage(msg, field, nullptr); + } else { + object = reflection->MutableMessage(msg, field, nullptr); + } + return {object->_ParseFunc(), object}; + } + default: + GOOGLE_LOG(FATAL) << "Wrong type for length delim " << field->type(); + } +} + +const char* ReflectiveParseMessageSetItem(const char* begin, const char* end, + void* object, + internal::ParseContext* ctx) { + ParseClosure child; + auto msg = static_cast<Message*>(object); + auto reflection = msg->GetReflection(); + uint32 size; + auto ptr = begin; + while (ptr < end) { + uint32 tag = *ptr++; + if (tag == WireFormatLite::kMessageSetTypeIdTag) { + uint32 type_id; + ptr = Varint::Parse32(ptr, &type_id); + if (!ptr) goto error; + + auto field = reflection->FindKnownExtensionByNumber(type_id); + + if (ctx->extra_parse_data().payload.empty()) { + tag = *ptr++; + if (tag == WireFormatLite::kMessageSetMessageTag) { + ptr = Varint::Parse32Inline(ptr, &size); + if (!ptr) goto error; + child = GetLenDelim(type_id * 8 + 2, field, msg, + reflection->MutableUnknownFields(msg), reflection, + ctx); + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (!ctx->ParseExactRange(child, ptr, newend)) goto error; + ptr = newend; + } else { + goto error; + } + } else { + GOOGLE_LOG(FATAL) << "Wrong order"; + } + } else if (tag == WireFormatLite::kMessageSetItemEndTag) { + if (!ctx->ValidEndGroup(tag)) goto error; + break; + } else if (tag == WireFormatLite::kMessageSetMessageTag) { + uint32 size; + ptr = Varint::Parse32Inline(ptr, &size); + if (!ptr) goto error; + child = {internal::StringParser, &ctx->extra_parse_data().payload}; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (!ctx->ParseExactRange(child, ptr, newend)) goto error; + ptr = newend; + } else { + GOOGLE_LOG(FATAL) << "Unknown message set item tag"; + } + } + return ptr; +error: + return nullptr; +len_delim_till_end: + return ctx->StoreAndTailCall(ptr, end, {ReflectiveParseMessageSetItem, msg}, + child, size); +} + +ParseClosure GetGroup(int field_number, const FieldDescriptor* field, + Message* msg, UnknownFieldSet* unknown, + const Reflection* reflection) { + if (field == nullptr && field_number == 1 && + msg->GetDescriptor()->options().message_set_wire_format()) { + return {ReflectiveParseMessageSetItem, msg}; + } + if (field == nullptr || WireFormat::WireTypeForFieldType(field->type()) != + WireFormatLite::WIRETYPE_START_GROUP) { + return {internal::UnknownGroupParse, unknown->AddGroup(field_number)}; + } + + Message* object; + if (field->is_repeated()) { + object = reflection->AddMessage(msg, field, nullptr); + } else { + object = reflection->MutableMessage(msg, field, nullptr); + } + return {object->_ParseFunc(), object}; +} + +const char* Message::_InternalParse(const char* begin, const char* end, + void* object, internal::ParseContext* ctx) { + auto msg = static_cast<Message*>(object); + const Descriptor* descriptor = msg->GetDescriptor(); + const Reflection* reflection = msg->GetReflection(); + auto unknown = reflection->MutableUnknownFields(msg); + GOOGLE_DCHECK(descriptor); + GOOGLE_DCHECK(reflection); + + GOOGLE_DCHECK(begin <= end); + uint32 size; + internal::ParseFunc parser_till_end; + uint32 tag; + int depth; + auto ptr = begin; + while (ptr < end) { + ptr = Varint::Parse32Inline(ptr, &tag); + if (ptr == nullptr) return nullptr; + if ((tag >> 3) == 0) return nullptr; + const FieldDescriptor* field = nullptr; + + int field_number = WireFormatLite::GetTagFieldNumber(tag); + field = descriptor->FindFieldByNumber(field_number); + + // If that failed, check if the field is an extension. + if (field == nullptr && descriptor->IsExtensionNumber(field_number)) { + field = reflection->FindKnownExtensionByNumber(field_number); + } + + // if (field) GOOGLE_LOG(ERROR) << "Encountered field " << field->name(); + + switch (tag & 7) { + case 0: { + uint64 val; + ptr = Varint::Parse64(ptr, &val); + if (!ptr) goto error; + if (field == nullptr || + WireFormat::WireTypeForFieldType(field->type()) != 0) { + unknown->AddVarint(field_number, val); + break; + } + SetField(val, field, msg, reflection); + break; + } + case 1: { + uint64 val = UNALIGNED_LOAD64(ptr); + ptr = ptr + 8; + if (field == nullptr || + WireFormat::WireTypeForFieldType(field->type()) != 1) { + unknown->AddFixed64(field_number, val); + break; + } + SetField(val, field, msg, reflection); + break; + } + case 2: { + ptr = Varint::Parse32Inline(ptr, &size); + if (!ptr) goto error; + ParseClosure child = + GetLenDelim(field_number, field, msg, unknown, reflection, ctx); + parser_till_end = child.func; + object = child.object; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (!ctx->ParseExactRange(child, ptr, newend)) goto error; + ptr = newend; + break; + } + case 3: { + if (!ctx->PrepareGroup(tag, &depth)) goto error; + + ParseClosure child = + GetGroup(field_number, field, msg, unknown, reflection); + parser_till_end = child.func; + object = child.object; + + if (ptr < end) ptr = child(ptr, end, ctx); + if (!ptr) goto error; + if (ctx->GroupContinues(depth)) goto group_continues; + break; + } + case 4: { + if (!ctx->ValidEndGroup(tag)) goto error; + return ptr; + } + case 5: { + uint32 val = UNALIGNED_LOAD32(ptr); + ptr = ptr + 4; + if (field == nullptr || + WireFormat::WireTypeForFieldType(field->type()) != 5) { + unknown->AddFixed64(field_number, val); + break; + } + SetField(val, field, msg, reflection); + break; + } + default: + goto error; + } + } + return ptr; +error: + return nullptr; +len_delim_till_end: + // Length delimited field crosses end + return ctx->StoreAndTailCall(ptr, end, {Message::_InternalParse, msg}, + {parser_till_end, object}, size); +group_continues: + GOOGLE_DCHECK(ptr >= end); + // Group crossed end and must be continued. Either this a parse failure + // or we need to resume on the next chunk and thus save the state. + ctx->StoreGroup({Message::_InternalParse, msg}, {parser_till_end, object}, + depth); + return ptr; +} +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + void Message::SerializeWithCachedSizes( io::CodedOutputStream* output) const { @@ -258,14 +708,32 @@ MapIterator Reflection::MapEnd( MessageFactory::~MessageFactory() {} +namespace internal { + +// TODO(gerbens) make this factorized better. This should not have to hop +// to reflection. Currently uses GeneratedMessageReflection and thus is +// defined in generated_message_reflection.cc +void RegisterFileLevelMetadata(void* assign_descriptors_table); + +} // namespace internal + namespace { +void RegisterFileLevelMetadata(void* assign_descriptors_table, + const string& filename) { + internal::RegisterFileLevelMetadata(assign_descriptors_table); +} + class GeneratedMessageFactory : public MessageFactory { public: static GeneratedMessageFactory* singleton(); - typedef void RegistrationFunc(const string&); - void RegisterFile(const char* file, RegistrationFunc* registration_func); + struct RegistrationData { + const Metadata* file_level_metadata; + int size; + }; + + void RegisterFile(const char* file, void* registration_data); void RegisterType(const Descriptor* descriptor, const Message* prototype); // implements MessageFactory --------------------------------------- @@ -273,22 +741,24 @@ class GeneratedMessageFactory : public MessageFactory { private: // Only written at static init time, so does not require locking. - hash_map<const char*, RegistrationFunc*, - hash<const char*>, streq> file_map_; + std::unordered_map<const char*, void*, hash<const char*>, + streq> + file_map_; - Mutex mutex_; + internal::WrappedMutex mutex_; // Initialized lazily, so requires locking. - hash_map<const Descriptor*, const Message*> type_map_; + std::unordered_map<const Descriptor*, const Message*> type_map_; }; GeneratedMessageFactory* GeneratedMessageFactory::singleton() { - static auto instance = internal::OnShutdownDelete(new GeneratedMessageFactory); + static auto instance = + internal::OnShutdownDelete(new GeneratedMessageFactory); return instance; } -void GeneratedMessageFactory::RegisterFile( - const char* file, RegistrationFunc* registration_func) { - if (!InsertIfNotPresent(&file_map_, file, registration_func)) { +void GeneratedMessageFactory::RegisterFile(const char* file, + void* registration_data) { + if (!InsertIfNotPresent(&file_map_, file, registration_data)) { GOOGLE_LOG(FATAL) << "File is already registered: " << file; } } @@ -321,9 +791,9 @@ const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL; // Apparently the file hasn't been registered yet. Let's do that now. - RegistrationFunc* registration_func = + void* registration_data = FindPtrOrNull(file_map_, type->file()->name().c_str()); - if (registration_func == NULL) { + if (registration_data == NULL) { GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't " "registered: " << type->file()->name(); return NULL; @@ -335,7 +805,7 @@ const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { const Message* result = FindPtrOrNull(type_map_, type); if (result == NULL) { // Nope. OK, register everything. - registration_func(type->file()->name()); + RegisterFileLevelMetadata(registration_data, type->file()->name()); // Should be here now. result = FindPtrOrNull(type_map_, type); } @@ -355,9 +825,9 @@ MessageFactory* MessageFactory::generated_factory() { } void MessageFactory::InternalRegisterGeneratedFile( - const char* filename, void (*register_messages)(const string&)) { + const char* filename, void* assign_descriptors_table) { GeneratedMessageFactory::singleton()->RegisterFile(filename, - register_messages); + assign_descriptors_table); } void MessageFactory::InternalRegisterGeneratedMessage( @@ -379,18 +849,21 @@ void* Reflection::RepeatedFieldData( return NULL; } -namespace internal { -RepeatedFieldAccessor::~RepeatedFieldAccessor() { +namespace { +template <typename T> +T* GetSingleton() { + static T singleton; + return &singleton; } -} // namespace internal +} // namespace const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( const FieldDescriptor* field) const { GOOGLE_CHECK(field->is_repeated()); switch (field->cpp_type()) { #define HANDLE_PRIMITIVE_TYPE(TYPE, type) \ - case FieldDescriptor::CPPTYPE_ ## TYPE: \ - return internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<type> >::get(); + case FieldDescriptor::CPPTYPE_##TYPE: \ + return GetSingleton<internal::RepeatedFieldPrimitiveAccessor<type> >(); HANDLE_PRIMITIVE_TYPE(INT32, int32) HANDLE_PRIMITIVE_TYPE(UINT32, uint32) HANDLE_PRIMITIVE_TYPE(INT64, int64) @@ -404,14 +877,14 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( switch (field->options().ctype()) { default: case FieldOptions::STRING: - return internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::get(); + return GetSingleton<internal::RepeatedPtrFieldStringAccessor>(); } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (field->is_map()) { - return internal::Singleton<internal::MapFieldAccessor>::get(); + return GetSingleton<internal::MapFieldAccessor>(); } else { - return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get(); + return GetSingleton<internal::RepeatedPtrFieldMessageAccessor>(); } } GOOGLE_LOG(FATAL) << "Should not reach here."; @@ -419,55 +892,35 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( } namespace internal { -namespace { -void ShutdownRepeatedFieldAccessor() { - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown(); - internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown(); - internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown(); - internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown(); - internal::Singleton<internal::MapFieldAccessor>::ShutDown(); -} - -struct ShutdownRepeatedFieldRegister { - ShutdownRepeatedFieldRegister() { - OnShutdown(&ShutdownRepeatedFieldAccessor); - } -} shutdown_; - -} // namespace -} // namespace internal - -namespace internal { -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE #endif -Message* GenericTypeHandler<Message>::NewFromPrototype( - const Message* prototype, google::protobuf::Arena* arena) { + Message* + GenericTypeHandler<Message>::NewFromPrototype(const Message* prototype, + Arena* arena) { return prototype->New(arena); } -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE #endif -google::protobuf::Arena* GenericTypeHandler<Message>::GetArena( - Message* value) { + Arena* + GenericTypeHandler<Message>::GetArena(Message* value) { return value->GetArena(); } -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE #endif -void* GenericTypeHandler<Message>::GetMaybeArenaPointer( - Message* value) { + void* + GenericTypeHandler<Message>::GetMaybeArenaPointer(Message* value) { return value->GetMaybeArenaPointer(); } } // namespace internal |