aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/dynamic_message.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/dynamic_message.cc')
-rw-r--r--src/google/protobuf/dynamic_message.cc79
1 files changed, 57 insertions, 22 deletions
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 4cca9869..db1dd4d3 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -72,6 +72,7 @@
#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/reflection_ops.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
@@ -85,6 +86,8 @@ using internal::ExtensionSet;
using internal::GeneratedMessageReflection;
+using internal::ArenaStringPtr;
+
// ===================================================================
// Some helper tables and functions...
@@ -131,7 +134,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;
}
@@ -162,7 +165,7 @@ int OneofFieldSpaceUsed(const FieldDescriptor* field) {
switch (field->options().ctype()) {
default:
case FieldOptions::STRING:
- return sizeof(string*);
+ return sizeof(ArenaStringPtr);
}
break;
}
@@ -236,6 +239,8 @@ 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;
@@ -245,6 +250,8 @@ class DynamicMessage : public Message {
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 ||
@@ -261,7 +268,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_;
};
@@ -269,6 +275,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
@@ -330,15 +347,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>();
}
@@ -390,9 +409,15 @@ DynamicMessage::~DynamicMessage() {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
switch (field->options().ctype()) {
default:
- case FieldOptions::STRING:
- delete *reinterpret_cast<string**>(field_ptr);
+ 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);
@@ -440,10 +465,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;
}
}
@@ -492,6 +519,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_;
}
@@ -672,7 +709,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->oneof_case_offset,
type_info->pool,
this,
- type_info->size));
+ type_info->size,
+ -1 /* arena_offset */));
} else {
type_info->reflection.reset(
new GeneratedMessageReflection(
@@ -684,7 +722,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->extensions_offset,
type_info->pool,
this,
- type_info->size));
+ type_info->size,
+ -1 /* arena_offset */));
}
// Cross link prototypes.
prototype->CrossLinkPrototypes();
@@ -723,12 +762,8 @@ void DynamicMessageFactory::ConstructDefaultOneofInstance(
switch (field->options().ctype()) {
default:
case FieldOptions::STRING:
- if (field->has_default_value()) {
- new(field_ptr) const string*(&field->default_value_string());
- } else {
- new(field_ptr) string*(
- const_cast<string*>(&internal::GetEmptyString()));
- }
+ ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
+ asp->UnsafeSetDefault(&field->default_value_string());
break;
}
break;