aboutsummaryrefslogtreecommitdiffstats
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.cc262
1 files changed, 28 insertions, 234 deletions
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 4cca986..c711a2d 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -1,6 +1,6 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
+// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -123,9 +123,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
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_MESSAGE: return sizeof(Message*);
case FD::CPPTYPE_STRING:
switch (field->options().ctype()) {
@@ -141,42 +139,11 @@ 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(string*);
- }
- 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;
@@ -199,7 +166,6 @@ class DynamicMessage : public Message {
struct TypeInfo {
int size;
int has_bits_offset;
- int oneof_case_offset;
int unknown_fields_offset;
int extensions_offset;
@@ -212,19 +178,7 @@ class DynamicMessage : public Message {
// important (the prototype must be deleted *before* the offsets).
scoped_array<int> offsets;
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), default_oneof_instance(NULL) {}
-
- ~TypeInfo() {
- delete prototype;
- operator delete(default_oneof_instance);
- }
+ scoped_ptr<const DynamicMessage> prototype;
};
DynamicMessage(const TypeInfo* type_info);
@@ -242,7 +196,6 @@ class DynamicMessage : public Message {
Metadata GetMetadata() const;
-
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -280,12 +233,6 @@ 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);
- }
-
new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
if (type_info_->extensions_offset != -1) {
@@ -295,9 +242,6 @@ 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: \
@@ -371,35 +315,12 @@ 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:
- delete *reinterpret_cast<string**>(field_ptr);
- 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()) {
@@ -447,12 +368,11 @@ DynamicMessage::~DynamicMessage() {
break;
}
}
- } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (!is_prototype()) {
- Message* message = *reinterpret_cast<Message**>(field_ptr);
- if (message != NULL) {
- delete message;
- }
+ } else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
+ !is_prototype()) {
+ Message* message = *reinterpret_cast<Message**>(field_ptr);
+ if (message != NULL) {
+ delete message;
}
}
}
@@ -469,10 +389,6 @@ 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()) {
@@ -487,7 +403,7 @@ void DynamicMessage::CrossLinkPrototypes() {
}
Message* DynamicMessage::New() const {
- void* new_base = operator new(type_info_->size);
+ void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size));
memset(new_base, 0, type_info_->size);
return new(new_base) DynamicMessage(type_info_);
}
@@ -500,9 +416,7 @@ 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 {
@@ -532,9 +446,6 @@ 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;
}
}
@@ -554,7 +465,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
if (*target != NULL) {
// Already exists.
- return (*target)->prototype;
+ return (*target)->prototype.get();
}
DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
@@ -573,7 +484,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
// or not that field is set.
// Compute size and offsets.
- int* offsets = new int[type->field_count() + type->oneof_decl_count()];
+ int* offsets = new int[type->field_count()];
type_info->offsets.reset(offsets);
// Decide all field offsets by packing in order.
@@ -589,13 +500,6 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
size += has_bits_array_size * sizeof(uint32);
size = AlignOffset(size);
- // 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) {
type_info->extensions_offset = size;
@@ -609,20 +513,10 @@ 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.
- // 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;
+ int field_size = FieldSpaceUsed(type->field(i));
+ size = AlignTo(size, min(kSafeAlignment, field_size));
+ offsets[i] = size;
+ size += field_size;
}
// Add the UnknownFieldSet to the end.
@@ -639,126 +533,26 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
void* base = operator new(size);
memset(base, 0, size);
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
- type_info->prototype = prototype;
+ type_info->prototype.reset(prototype);
// Construct the reflection object.
- 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));
- } 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));
- }
+ type_info->reflection.reset(
+ new GeneratedMessageReflection(
+ type_info->type,
+ type_info->prototype.get(),
+ 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));
+
// 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:
- if (field->has_default_value()) {
- new(field_ptr) const string*(&field->default_value_string());
- } else {
- new(field_ptr) string*(
- const_cast<string*>(&internal::GetEmptyString()));
- }
- 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