aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/dynamic_message.cc
diff options
context:
space:
mode:
authorGravatar Feng Xiao <xfxyjwf@gmail.com>2015-08-22 18:25:48 -0700
committerGravatar Feng Xiao <xfxyjwf@gmail.com>2015-08-22 18:25:48 -0700
commiteee38b0c018b3279f77d03dff796f440f40d3516 (patch)
tree7ff0978e30238d493fc7899b75abeb6d66939f07 /src/google/protobuf/dynamic_message.cc
parentc3bc155aceda36ecb01cde2367a3b427f2d7ce40 (diff)
Down-integrate from google3.
Diffstat (limited to 'src/google/protobuf/dynamic_message.cc')
-rw-r--r--src/google/protobuf/dynamic_message.cc27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 318ce6f9..2324d952 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -65,6 +65,7 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
@@ -79,6 +80,7 @@
#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 {
@@ -87,7 +89,7 @@ using internal::WireFormat;
using internal::ExtensionSet;
using internal::GeneratedMessageReflection;
using internal::MapField;
-using internal::MapFieldBase;
+using internal::DynamicMapField;
using internal::ArenaStringPtr;
@@ -116,7 +118,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
case FD::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- return sizeof(MapFieldBase);
+ return sizeof(DynamicMapField);
} else {
return sizeof(RepeatedPtrField<Message>);
}
@@ -389,7 +391,8 @@ void DynamicMessage::SharedCtor() {
new(field_ptr) Message*(NULL);
} else {
if (IsMapFieldInApi(field)) {
- new (field_ptr) MapFieldBase();
+ new (field_ptr) DynamicMapField(
+ type_info_->factory->GetPrototypeNoLock(field->message_type()));
} else {
new (field_ptr) RepeatedPtrField<Message>();
}
@@ -437,8 +440,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -480,7 +483,7 @@ DynamicMessage::~DynamicMessage() {
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- reinterpret_cast<MapFieldBase*>(field_ptr)->~MapFieldBase();
+ reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
} else {
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
->~RepeatedPtrField<Message>();
@@ -496,8 +499,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -723,8 +726,14 @@ 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.
if (type->oneof_decl_count() > 0) {