| Index: third_party/protobuf/src/google/protobuf/dynamic_message.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message.cc b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
|
| index 09bec54363aa2eba3004ea0ea6b6e11f67b3d780..bb4004769d4d5e9b3a333cbb187fe8f71acc8e06 100644
|
| --- a/third_party/protobuf/src/google/protobuf/dynamic_message.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
|
| @@ -1,6 +1,6 @@
|
| // Protocol Buffers - Google's data interchange format
|
| // Copyright 2008 Google Inc. All rights reserved.
|
| -// http://code.google.com/p/protobuf/
|
| +// 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
|
| @@ -64,18 +64,27 @@
|
|
|
| #include <algorithm>
|
| #include <google/protobuf/stubs/hash.h>
|
| +#include <memory>
|
| +#ifndef _SHARED_PTR_H
|
| +#include <google/protobuf/stubs/shared_ptr.h>
|
| +#endif
|
|
|
| #include <google/protobuf/stubs/common.h>
|
| +#include <google/protobuf/stubs/scoped_ptr.h>
|
|
|
| #include <google/protobuf/dynamic_message.h>
|
| #include <google/protobuf/descriptor.h>
|
| #include <google/protobuf/descriptor.pb.h>
|
| #include <google/protobuf/generated_message_util.h>
|
| #include <google/protobuf/generated_message_reflection.h>
|
| +#include <google/protobuf/arenastring.h>
|
| +#include <google/protobuf/map_field_inl.h>
|
| #include <google/protobuf/reflection_ops.h>
|
| #include <google/protobuf/repeated_field.h>
|
| +#include <google/protobuf/map_type_handler.h>
|
| #include <google/protobuf/extension_set.h>
|
| #include <google/protobuf/wire_format.h>
|
| +#include <google/protobuf/map_field.h>
|
|
|
| namespace google {
|
| namespace protobuf {
|
| @@ -83,13 +92,21 @@ namespace protobuf {
|
| using internal::WireFormat;
|
| using internal::ExtensionSet;
|
| using internal::GeneratedMessageReflection;
|
| +using internal::MapField;
|
| +using internal::DynamicMapField;
|
|
|
|
|
| +using internal::ArenaStringPtr;
|
| +
|
| // ===================================================================
|
| // Some helper tables and functions...
|
|
|
| namespace {
|
|
|
| +bool IsMapFieldInApi(const FieldDescriptor* field) {
|
| + return field->is_map();
|
| +}
|
| +
|
| // Compute the byte size of the in-memory representation of the field.
|
| int FieldSpaceUsed(const FieldDescriptor* field) {
|
| typedef FieldDescriptor FD; // avoid line wrapping
|
| @@ -103,7 +120,12 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
|
| case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField<float >);
|
| case FD::CPPTYPE_BOOL : return sizeof(RepeatedField<bool >);
|
| case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
|
| - case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
|
| + case FD::CPPTYPE_MESSAGE:
|
| + if (IsMapFieldInApi(field)) {
|
| + return sizeof(DynamicMapField);
|
| + } else {
|
| + return sizeof(RepeatedPtrField<Message>);
|
| + }
|
|
|
| case FD::CPPTYPE_STRING:
|
| switch (field->options().ctype()) {
|
| @@ -131,7 +153,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING:
|
| - return sizeof(string*);
|
| + return sizeof(ArenaStringPtr);
|
| }
|
| break;
|
| }
|
| @@ -141,11 +163,42 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
|
| return 0;
|
| }
|
|
|
| +// Compute the byte size of in-memory representation of the oneof fields
|
| +// in default oneof instance.
|
| +int OneofFieldSpaceUsed(const FieldDescriptor* field) {
|
| + typedef FieldDescriptor FD; // avoid line wrapping
|
| + switch (field->cpp_type()) {
|
| + case FD::CPPTYPE_INT32 : return sizeof(int32 );
|
| + case FD::CPPTYPE_INT64 : return sizeof(int64 );
|
| + case FD::CPPTYPE_UINT32 : return sizeof(uint32 );
|
| + case FD::CPPTYPE_UINT64 : return sizeof(uint64 );
|
| + case FD::CPPTYPE_DOUBLE : return sizeof(double );
|
| + case FD::CPPTYPE_FLOAT : return sizeof(float );
|
| + case FD::CPPTYPE_BOOL : return sizeof(bool );
|
| + case FD::CPPTYPE_ENUM : return sizeof(int );
|
| +
|
| + case FD::CPPTYPE_MESSAGE:
|
| + return sizeof(Message*);
|
| +
|
| + case FD::CPPTYPE_STRING:
|
| + switch (field->options().ctype()) {
|
| + default:
|
| + case FieldOptions::STRING:
|
| + return sizeof(ArenaStringPtr);
|
| + }
|
| + break;
|
| + }
|
| +
|
| + GOOGLE_LOG(DFATAL) << "Can't get here.";
|
| + return 0;
|
| +}
|
| +
|
| inline int DivideRoundingUp(int i, int j) {
|
| return (i + (j - 1)) / j;
|
| }
|
|
|
| static const int kSafeAlignment = sizeof(uint64);
|
| +static const int kMaxOneofUnionSize = sizeof(uint64);
|
|
|
| inline int AlignTo(int offset, int alignment) {
|
| return DivideRoundingUp(offset, alignment) * alignment;
|
| @@ -168,8 +221,10 @@ class DynamicMessage : public Message {
|
| struct TypeInfo {
|
| int size;
|
| int has_bits_offset;
|
| + int oneof_case_offset;
|
| int unknown_fields_offset;
|
| int extensions_offset;
|
| + int is_default_instance_offset;
|
|
|
| // Not owned by the TypeInfo.
|
| DynamicMessageFactory* factory; // The factory that created this object.
|
| @@ -178,18 +233,20 @@ class DynamicMessage : public Message {
|
|
|
| // Warning: The order in which the following pointers are defined is
|
| // important (the prototype must be deleted *before* the offsets).
|
| - scoped_array<int> offsets;
|
| - scoped_ptr<const GeneratedMessageReflection> reflection;
|
| + google::protobuf::scoped_array<int> offsets;
|
| + google::protobuf::scoped_ptr<const GeneratedMessageReflection> reflection;
|
| // Don't use a scoped_ptr to hold the prototype: the destructor for
|
| // DynamicMessage needs to know whether it is the prototype, and does so by
|
| // looking back at this field. This would assume details about the
|
| // implementation of scoped_ptr.
|
| const DynamicMessage* prototype;
|
| + void* default_oneof_instance;
|
|
|
| - TypeInfo() : prototype(NULL) {}
|
| + TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {}
|
|
|
| ~TypeInfo() {
|
| delete prototype;
|
| + operator delete(default_oneof_instance);
|
| }
|
| };
|
|
|
| @@ -202,14 +259,19 @@ class DynamicMessage : public Message {
|
| // implements Message ----------------------------------------------
|
|
|
| Message* New() const;
|
| + Message* New(::google::protobuf::Arena* arena) const;
|
| + ::google::protobuf::Arena* GetArena() const { return NULL; };
|
|
|
| int GetCachedSize() const;
|
| void SetCachedSize(int size) const;
|
|
|
| Metadata GetMetadata() const;
|
|
|
| +
|
| private:
|
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
|
| + DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
|
| + void SharedCtor();
|
|
|
| inline bool is_prototype() const {
|
| return type_info_->prototype == this ||
|
| @@ -226,7 +288,6 @@ class DynamicMessage : public Message {
|
| }
|
|
|
| const TypeInfo* type_info_;
|
| -
|
| // TODO(kenton): Make this an atomic<int> when C++ supports it.
|
| mutable int cached_byte_size_;
|
| };
|
| @@ -234,6 +295,17 @@ class DynamicMessage : public Message {
|
| DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
| : type_info_(type_info),
|
| cached_byte_size_(0) {
|
| + SharedCtor();
|
| +}
|
| +
|
| +DynamicMessage::DynamicMessage(const TypeInfo* type_info,
|
| + ::google::protobuf::Arena* arena)
|
| + : type_info_(type_info),
|
| + cached_byte_size_(0) {
|
| + SharedCtor();
|
| +}
|
| +
|
| +void DynamicMessage::SharedCtor() {
|
| // We need to call constructors for various fields manually and set
|
| // default values where appropriate. We use placement new to call
|
| // constructors. If you haven't heard of placement new, I suggest Googling
|
| @@ -245,6 +317,17 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
|
|
| const Descriptor* descriptor = type_info_->type;
|
|
|
| + // Initialize oneof cases.
|
| + for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) {
|
| + new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i))
|
| + uint32(0);
|
| + }
|
| +
|
| + if (type_info_->is_default_instance_offset != -1) {
|
| + *reinterpret_cast<bool*>(
|
| + OffsetToPointer(type_info_->is_default_instance_offset)) = false;
|
| + }
|
| +
|
| new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
|
|
|
| if (type_info_->extensions_offset != -1) {
|
| @@ -254,6 +337,9 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
| for (int i = 0; i < descriptor->field_count(); i++) {
|
| const FieldDescriptor* field = descriptor->field(i);
|
| void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
| + if (field->containing_oneof()) {
|
| + continue;
|
| + }
|
| switch (field->cpp_type()) {
|
| #define HANDLE_TYPE(CPPTYPE, TYPE) \
|
| case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| @@ -286,15 +372,17 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING:
|
| if (!field->is_repeated()) {
|
| + const string* default_value;
|
| if (is_prototype()) {
|
| - new(field_ptr) const string*(&field->default_value_string());
|
| + default_value = &field->default_value_string();
|
| } else {
|
| - string* default_value =
|
| - *reinterpret_cast<string* const*>(
|
| + default_value =
|
| + &(reinterpret_cast<const ArenaStringPtr*>(
|
| type_info_->prototype->OffsetToPointer(
|
| - type_info_->offsets[i]));
|
| - new(field_ptr) string*(default_value);
|
| + type_info_->offsets[i]))->Get(NULL));
|
| }
|
| + ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr();
|
| + asp->UnsafeSetDefault(default_value);
|
| } else {
|
| new(field_ptr) RepeatedPtrField<string>();
|
| }
|
| @@ -306,7 +394,12 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
| if (!field->is_repeated()) {
|
| new(field_ptr) Message*(NULL);
|
| } else {
|
| - new(field_ptr) RepeatedPtrField<Message>();
|
| + if (IsMapFieldInApi(field)) {
|
| + new (field_ptr) DynamicMapField(
|
| + type_info_->factory->GetPrototypeNoLock(field->message_type()));
|
| + } else {
|
| + new (field_ptr) RepeatedPtrField<Message>();
|
| + }
|
| }
|
| break;
|
| }
|
| @@ -327,12 +420,41 @@ DynamicMessage::~DynamicMessage() {
|
|
|
| // We need to manually run the destructors for repeated fields and strings,
|
| // just as we ran their constructors in the the DynamicMessage constructor.
|
| + // We also need to manually delete oneof fields if it is set and is string
|
| + // or message.
|
| // Additionally, if any singular embedded messages have been allocated, we
|
| // need to delete them, UNLESS we are the prototype message of this type,
|
| // in which case any embedded messages are other prototypes and shouldn't
|
| // be touched.
|
| for (int i = 0; i < descriptor->field_count(); i++) {
|
| const FieldDescriptor* field = descriptor->field(i);
|
| + if (field->containing_oneof()) {
|
| + void* field_ptr = OffsetToPointer(
|
| + type_info_->oneof_case_offset
|
| + + sizeof(uint32) * field->containing_oneof()->index());
|
| + if (*(reinterpret_cast<const uint32*>(field_ptr)) ==
|
| + field->number()) {
|
| + field_ptr = OffsetToPointer(type_info_->offsets[
|
| + descriptor->field_count() + field->containing_oneof()->index()]);
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
| + switch (field->options().ctype()) {
|
| + default:
|
| + case FieldOptions::STRING: {
|
| + const ::std::string* default_value =
|
| + &(reinterpret_cast<const ArenaStringPtr*>(
|
| + type_info_->prototype->OffsetToPointer(
|
| + type_info_->offsets[i]))->Get(NULL));
|
| + reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
|
| + default_value, NULL);
|
| + break;
|
| + }
|
| + }
|
| + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + delete *reinterpret_cast<Message**>(field_ptr);
|
| + }
|
| + }
|
| + continue;
|
| + }
|
| void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
|
|
| if (field->is_repeated()) {
|
| @@ -364,8 +486,12 @@ DynamicMessage::~DynamicMessage() {
|
| break;
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
| - ->~RepeatedPtrField<Message>();
|
| + if (IsMapFieldInApi(field)) {
|
| + reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
|
| + } else {
|
| + reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
| + ->~RepeatedPtrField<Message>();
|
| + }
|
| break;
|
| }
|
|
|
| @@ -373,10 +499,12 @@ DynamicMessage::~DynamicMessage() {
|
| switch (field->options().ctype()) {
|
| default: // TODO(kenton): Support other string reps.
|
| case FieldOptions::STRING: {
|
| - string* ptr = *reinterpret_cast<string**>(field_ptr);
|
| - if (ptr != &field->default_value_string()) {
|
| - delete ptr;
|
| - }
|
| + const ::std::string* default_value =
|
| + &(reinterpret_cast<const ArenaStringPtr*>(
|
| + type_info_->prototype->OffsetToPointer(
|
| + type_info_->offsets[i]))->Get(NULL));
|
| + reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
|
| + default_value, NULL);
|
| break;
|
| }
|
| }
|
| @@ -402,6 +530,10 @@ void DynamicMessage::CrossLinkPrototypes() {
|
| for (int i = 0; i < descriptor->field_count(); i++) {
|
| const FieldDescriptor* field = descriptor->field(i);
|
| void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
| + if (field->containing_oneof()) {
|
| + field_ptr = reinterpret_cast<uint8*>(
|
| + type_info_->default_oneof_instance) + type_info_->offsets[i];
|
| + }
|
|
|
| if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
| !field->is_repeated()) {
|
| @@ -413,6 +545,14 @@ void DynamicMessage::CrossLinkPrototypes() {
|
| factory->GetPrototypeNoLock(field->message_type());
|
| }
|
| }
|
| +
|
| + // Set as the default instance -- this affects field-presence semantics for
|
| + // proto3.
|
| + if (type_info_->is_default_instance_offset != -1) {
|
| + void* is_default_instance_ptr =
|
| + OffsetToPointer(type_info_->is_default_instance_offset);
|
| + *reinterpret_cast<bool*>(is_default_instance_ptr) = true;
|
| + }
|
| }
|
|
|
| Message* DynamicMessage::New() const {
|
| @@ -421,6 +561,16 @@ Message* DynamicMessage::New() const {
|
| return new(new_base) DynamicMessage(type_info_);
|
| }
|
|
|
| +Message* DynamicMessage::New(::google::protobuf::Arena* arena) const {
|
| + if (arena != NULL) {
|
| + Message* message = New();
|
| + arena->Own(message);
|
| + return message;
|
| + } else {
|
| + return New();
|
| + }
|
| +}
|
| +
|
| int DynamicMessage::GetCachedSize() const {
|
| return cached_byte_size_;
|
| }
|
| @@ -429,7 +579,9 @@ void DynamicMessage::SetCachedSize(int size) const {
|
| // This is theoretically not thread-compatible, but in practice it works
|
| // because if multiple threads write this simultaneously, they will be
|
| // writing the exact same value.
|
| + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
| cached_byte_size_ = size;
|
| + GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
| }
|
|
|
| Metadata DynamicMessage::GetMetadata() const {
|
| @@ -459,6 +611,9 @@ DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
|
| DynamicMessageFactory::~DynamicMessageFactory() {
|
| for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
|
| iter != prototypes_->map_.end(); ++iter) {
|
| + DeleteDefaultOneofInstance(iter->second->type,
|
| + iter->second->offsets.get(),
|
| + iter->second->default_oneof_instance);
|
| delete iter->second;
|
| }
|
| }
|
| @@ -497,7 +652,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
|
| // or not that field is set.
|
|
|
| // Compute size and offsets.
|
| - int* offsets = new int[type->field_count()];
|
| + int* offsets = new int[type->field_count() + type->oneof_decl_count()];
|
| type_info->offsets.reset(offsets);
|
|
|
| // Decide all field offsets by packing in order.
|
| @@ -507,11 +662,31 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
|
| size = AlignOffset(size);
|
|
|
| // Next the has_bits, which is an array of uint32s.
|
| - type_info->has_bits_offset = size;
|
| - int has_bits_array_size =
|
| - DivideRoundingUp(type->field_count(), bitsizeof(uint32));
|
| - size += has_bits_array_size * sizeof(uint32);
|
| - size = AlignOffset(size);
|
| + if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
| + type_info->has_bits_offset = -1;
|
| + } else {
|
| + type_info->has_bits_offset = size;
|
| + int has_bits_array_size =
|
| + DivideRoundingUp(type->field_count(), bitsizeof(uint32));
|
| + size += has_bits_array_size * sizeof(uint32);
|
| + size = AlignOffset(size);
|
| + }
|
| +
|
| + // The is_default_instance member, if any.
|
| + if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
| + type_info->is_default_instance_offset = size;
|
| + size += sizeof(bool);
|
| + size = AlignOffset(size);
|
| + } else {
|
| + type_info->is_default_instance_offset = -1;
|
| + }
|
| +
|
| + // The oneof_case, if any. It is an array of uint32s.
|
| + if (type->oneof_decl_count() > 0) {
|
| + type_info->oneof_case_offset = size;
|
| + size += type->oneof_decl_count() * sizeof(uint32);
|
| + size = AlignOffset(size);
|
| + }
|
|
|
| // The ExtensionSet, if any.
|
| if (type->extension_range_count() > 0) {
|
| @@ -526,10 +701,20 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
|
| // All the fields.
|
| for (int i = 0; i < type->field_count(); i++) {
|
| // Make sure field is aligned to avoid bus errors.
|
| - int field_size = FieldSpaceUsed(type->field(i));
|
| - size = AlignTo(size, min(kSafeAlignment, field_size));
|
| - offsets[i] = size;
|
| - size += field_size;
|
| + // Oneof fields do not use any space.
|
| + if (!type->field(i)->containing_oneof()) {
|
| + int field_size = FieldSpaceUsed(type->field(i));
|
| + size = AlignTo(size, min(kSafeAlignment, field_size));
|
| + offsets[i] = size;
|
| + size += field_size;
|
| + }
|
| + }
|
| +
|
| + // The oneofs.
|
| + for (int i = 0; i < type->oneof_decl_count(); i++) {
|
| + size = AlignTo(size, kSafeAlignment);
|
| + offsets[type->field_count() + i] = size;
|
| + size += kMaxOneofUnionSize;
|
| }
|
|
|
| // Add the UnknownFieldSet to the end.
|
| @@ -545,27 +730,133 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
|
| // Allocate the prototype.
|
| void* base = operator new(size);
|
| memset(base, 0, size);
|
| + // The prototype in type_info has to be set before creating the prototype
|
| + // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
|
| + // creating prototype for Foo, prototype of the map entry will also be
|
| + // created, which needs the address of the prototype of Foo (the value in
|
| + // map). To break the cyclic dependency, we have to assgin the address of
|
| + // prototype into type_info first.
|
| + type_info->prototype = static_cast<DynamicMessage*>(base);
|
| DynamicMessage* prototype = new(base) DynamicMessage(type_info);
|
| - type_info->prototype = prototype;
|
|
|
| // Construct the reflection object.
|
| - type_info->reflection.reset(
|
| - new GeneratedMessageReflection(
|
| - type_info->type,
|
| - type_info->prototype,
|
| - type_info->offsets.get(),
|
| - type_info->has_bits_offset,
|
| - type_info->unknown_fields_offset,
|
| - type_info->extensions_offset,
|
| - type_info->pool,
|
| - this,
|
| - type_info->size));
|
| -
|
| + if (type->oneof_decl_count() > 0) {
|
| + // Compute the size of default oneof instance and offsets of default
|
| + // oneof fields.
|
| + int oneof_size = 0;
|
| + for (int i = 0; i < type->oneof_decl_count(); i++) {
|
| + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
|
| + const FieldDescriptor* field = type->oneof_decl(i)->field(j);
|
| + int field_size = OneofFieldSpaceUsed(field);
|
| + oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size));
|
| + offsets[field->index()] = oneof_size;
|
| + oneof_size += field_size;
|
| + }
|
| + }
|
| + // Construct default oneof instance.
|
| + type_info->default_oneof_instance = ::operator new(oneof_size);
|
| + ConstructDefaultOneofInstance(type_info->type,
|
| + type_info->offsets.get(),
|
| + type_info->default_oneof_instance);
|
| + type_info->reflection.reset(
|
| + new GeneratedMessageReflection(
|
| + type_info->type,
|
| + type_info->prototype,
|
| + type_info->offsets.get(),
|
| + type_info->has_bits_offset,
|
| + type_info->unknown_fields_offset,
|
| + type_info->extensions_offset,
|
| + type_info->default_oneof_instance,
|
| + type_info->oneof_case_offset,
|
| + type_info->pool,
|
| + this,
|
| + type_info->size,
|
| + -1 /* arena_offset */,
|
| + type_info->is_default_instance_offset));
|
| + } else {
|
| + type_info->reflection.reset(
|
| + new GeneratedMessageReflection(
|
| + type_info->type,
|
| + type_info->prototype,
|
| + type_info->offsets.get(),
|
| + type_info->has_bits_offset,
|
| + type_info->unknown_fields_offset,
|
| + type_info->extensions_offset,
|
| + type_info->pool,
|
| + this,
|
| + type_info->size,
|
| + -1 /* arena_offset */,
|
| + type_info->is_default_instance_offset));
|
| + }
|
| // Cross link prototypes.
|
| prototype->CrossLinkPrototypes();
|
|
|
| return prototype;
|
| }
|
|
|
| +void DynamicMessageFactory::ConstructDefaultOneofInstance(
|
| + const Descriptor* type,
|
| + const int offsets[],
|
| + void* default_oneof_instance) {
|
| + for (int i = 0; i < type->oneof_decl_count(); i++) {
|
| + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
|
| + const FieldDescriptor* field = type->oneof_decl(i)->field(j);
|
| + void* field_ptr = reinterpret_cast<uint8*>(
|
| + default_oneof_instance) + offsets[field->index()];
|
| + switch (field->cpp_type()) {
|
| +#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
| + case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
| + new(field_ptr) TYPE(field->default_value_##TYPE()); \
|
| + 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 );
|
| +#undef HANDLE_TYPE
|
| +
|
| + case FieldDescriptor::CPPTYPE_ENUM:
|
| + new(field_ptr) int(field->default_value_enum()->number());
|
| + break;
|
| + case FieldDescriptor::CPPTYPE_STRING:
|
| + switch (field->options().ctype()) {
|
| + default:
|
| + case FieldOptions::STRING:
|
| + ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
|
| + asp->UnsafeSetDefault(&field->default_value_string());
|
| + break;
|
| + }
|
| + break;
|
| +
|
| + case FieldDescriptor::CPPTYPE_MESSAGE: {
|
| + new(field_ptr) Message*(NULL);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void DynamicMessageFactory::DeleteDefaultOneofInstance(
|
| + const Descriptor* type,
|
| + const int offsets[],
|
| + void* default_oneof_instance) {
|
| + for (int i = 0; i < type->oneof_decl_count(); i++) {
|
| + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
|
| + const FieldDescriptor* field = type->oneof_decl(i)->field(j);
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
| + switch (field->options().ctype()) {
|
| + default:
|
| + case FieldOptions::STRING:
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace protobuf
|
| } // namespace google
|
|
|