aboutsummaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/generated_message_reflection.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/generated_message_reflection.cc')
-rw-r--r--src/google/protobuf/generated_message_reflection.cc634
1 files changed, 543 insertions, 91 deletions
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 0f065ff..7cfaa98 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -33,25 +33,26 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
+#include <set>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/stubs/common.h>
+#define GOOGLE_PROTOBUF_HAS_ONEOF
+
namespace google {
namespace protobuf {
namespace internal {
-namespace { const string kEmptyString; }
-
int StringSpaceUsedExcludingSelf(const string& str) {
const void* start = &str;
const void* end = &str + 1;
- if (start <= str.data() && str.data() <= end) {
+ if (start <= str.data() && str.data() < end) {
// The string's data is stored inside the string object itself.
return 0;
} else {
@@ -69,9 +70,8 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor,
}
const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
- static string kEmptyString;
const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
- return (d == NULL ? kEmptyString : d->name());
+ return (d == NULL ? GetEmptyString() : d->name());
}
// ===================================================================
@@ -191,6 +191,33 @@ GeneratedMessageReflection::GeneratedMessageReflection(
message_factory_ (factory) {
}
+GeneratedMessageReflection::GeneratedMessageReflection(
+ const Descriptor* descriptor,
+ const Message* default_instance,
+ const int offsets[],
+ int has_bits_offset,
+ int unknown_fields_offset,
+ int extensions_offset,
+ const void* default_oneof_instance,
+ int oneof_case_offset,
+ const DescriptorPool* descriptor_pool,
+ MessageFactory* factory,
+ int object_size)
+ : descriptor_ (descriptor),
+ default_instance_ (default_instance),
+ default_oneof_instance_ (default_oneof_instance),
+ offsets_ (offsets),
+ has_bits_offset_ (has_bits_offset),
+ oneof_case_offset_(oneof_case_offset),
+ unknown_fields_offset_(unknown_fields_offset),
+ extensions_offset_(extensions_offset),
+ object_size_ (object_size),
+ descriptor_pool_ ((descriptor_pool == NULL) ?
+ DescriptorPool::generated_pool() :
+ descriptor_pool),
+ message_factory_ (factory) {
+}
+
GeneratedMessageReflection::~GeneratedMessageReflection() {}
const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
@@ -257,6 +284,9 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
break;
}
} else {
+ if (field->containing_oneof() && !HasOneofField(message, field)) {
+ continue;
+ }
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32 :
case FieldDescriptor::CPPTYPE_INT64 :
@@ -309,6 +339,195 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
return total_size;
}
+void GeneratedMessageReflection::SwapField(
+ Message* message1,
+ Message* message2,
+ const FieldDescriptor* field) const {
+ if (field->is_repeated()) {
+ switch (field->cpp_type()) {
+#define SWAP_ARRAYS(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
+ MutableRaw<RepeatedField<TYPE> >(message2, field)); \
+ break;
+
+ SWAP_ARRAYS(INT32 , int32 );
+ SWAP_ARRAYS(INT64 , int64 );
+ SWAP_ARRAYS(UINT32, uint32);
+ SWAP_ARRAYS(UINT64, uint64);
+ SWAP_ARRAYS(FLOAT , float );
+ SWAP_ARRAYS(DOUBLE, double);
+ SWAP_ARRAYS(BOOL , bool );
+ SWAP_ARRAYS(ENUM , int );
+#undef SWAP_ARRAYS
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
+ MutableRaw<RepeatedPtrFieldBase>(message2, field));
+ break;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+ }
+ } else {
+ switch (field->cpp_type()) {
+#define SWAP_VALUES(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ std::swap(*MutableRaw<TYPE>(message1, field), \
+ *MutableRaw<TYPE>(message2, field)); \
+ break;
+
+ SWAP_VALUES(INT32 , int32 );
+ SWAP_VALUES(INT64 , int64 );
+ SWAP_VALUES(UINT32, uint32);
+ SWAP_VALUES(UINT64, uint64);
+ SWAP_VALUES(FLOAT , float );
+ SWAP_VALUES(DOUBLE, double);
+ SWAP_VALUES(BOOL , bool );
+ SWAP_VALUES(ENUM , int );
+#undef SWAP_VALUES
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ std::swap(*MutableRaw<Message*>(message1, field),
+ *MutableRaw<Message*>(message2, field));
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ std::swap(*MutableRaw<string*>(message1, field),
+ *MutableRaw<string*>(message2, field));
+ break;
+ }
+ break;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+ }
+ }
+}
+
+void GeneratedMessageReflection::SwapOneofField(
+ Message* message1,
+ Message* message2,
+ const OneofDescriptor* oneof_descriptor) const {
+ uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
+ uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
+
+ int32 temp_int32;
+ int64 temp_int64;
+ uint32 temp_uint32;
+ uint64 temp_uint64;
+ float temp_float;
+ double temp_double;
+ bool temp_bool;
+ int temp_int;
+ Message* temp_message;
+ string temp_string;
+
+ // Stores message1's oneof field to a temp variable.
+ const FieldDescriptor* field1;
+ if (oneof_case1 > 0) {
+ field1 = descriptor_->FindFieldByNumber(oneof_case1);
+ //oneof_descriptor->field(oneof_case1);
+ switch (field1->cpp_type()) {
+#define GET_TEMP_VALUE(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ temp_##TYPE = GetField<TYPE>(*message1, field1); \
+ break;
+
+ GET_TEMP_VALUE(INT32 , int32 );
+ GET_TEMP_VALUE(INT64 , int64 );
+ GET_TEMP_VALUE(UINT32, uint32);
+ GET_TEMP_VALUE(UINT64, uint64);
+ GET_TEMP_VALUE(FLOAT , float );
+ GET_TEMP_VALUE(DOUBLE, double);
+ GET_TEMP_VALUE(BOOL , bool );
+ GET_TEMP_VALUE(ENUM , int );
+#undef GET_TEMP_VALUE
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ temp_message = ReleaseMessage(message1, field1);
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ temp_string = GetString(*message1, field1);
+ break;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
+ }
+ }
+
+ // Sets message1's oneof field from the message2's oneof field.
+ if (oneof_case2 > 0) {
+ const FieldDescriptor* field2 =
+ descriptor_->FindFieldByNumber(oneof_case2);
+ switch (field2->cpp_type()) {
+#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ SetField<TYPE>(message1, field2, GetField<TYPE>(*message2, field2)); \
+ break;
+
+ SET_ONEOF_VALUE1(INT32 , int32 );
+ SET_ONEOF_VALUE1(INT64 , int64 );
+ SET_ONEOF_VALUE1(UINT32, uint32);
+ SET_ONEOF_VALUE1(UINT64, uint64);
+ SET_ONEOF_VALUE1(FLOAT , float );
+ SET_ONEOF_VALUE1(DOUBLE, double);
+ SET_ONEOF_VALUE1(BOOL , bool );
+ SET_ONEOF_VALUE1(ENUM , int );
+#undef SET_ONEOF_VALUE1
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ SetAllocatedMessage(message1,
+ ReleaseMessage(message2, field2),
+ field2);
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ SetString(message1, field2, GetString(*message2, field2));
+ break;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type();
+ }
+ } else {
+ ClearOneof(message1, oneof_descriptor);
+ }
+
+ // Sets message2's oneof field from the temp variable.
+ if (oneof_case1 > 0) {
+ switch (field1->cpp_type()) {
+#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ SetField<TYPE>(message2, field1, temp_##TYPE); \
+ break;
+
+ SET_ONEOF_VALUE2(INT32 , int32 );
+ SET_ONEOF_VALUE2(INT64 , int64 );
+ SET_ONEOF_VALUE2(UINT32, uint32);
+ SET_ONEOF_VALUE2(UINT64, uint64);
+ SET_ONEOF_VALUE2(FLOAT , float );
+ SET_ONEOF_VALUE2(DOUBLE, double);
+ SET_ONEOF_VALUE2(BOOL , bool );
+ SET_ONEOF_VALUE2(ENUM , int );
+#undef SET_ONEOF_VALUE2
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ SetAllocatedMessage(message2, temp_message, field1);
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ SetString(message2, field1, temp_string);
+ break;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
+ }
+ } else {
+ ClearOneof(message2, oneof_descriptor);
+ }
+}
+
void GeneratedMessageReflection::Swap(
Message* message1,
Message* message2) const {
@@ -324,7 +543,7 @@ void GeneratedMessageReflection::Swap(
"descriptor.";
GOOGLE_CHECK_EQ(message2->GetReflection(), this)
<< "Second argument to Swap() (of type \""
- << message1->GetDescriptor()->full_name()
+ << message2->GetDescriptor()->full_name()
<< "\") is not compatible with this reflection object (which is for type \""
<< descriptor_->full_name()
<< "\"). Note that the exact same class is required; not just the same "
@@ -340,73 +559,69 @@ void GeneratedMessageReflection::Swap(
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- if (field->is_repeated()) {
- switch (field->cpp_type()) {
-#define SWAP_ARRAYS(CPPTYPE, TYPE) \
- case FieldDescriptor::CPPTYPE_##CPPTYPE: \
- MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
- MutableRaw<RepeatedField<TYPE> >(message2, field)); \
- break;
+ if (!field->containing_oneof()) {
+ SwapField(message1, message2, field);
+ }
+ }
- SWAP_ARRAYS(INT32 , int32 );
- SWAP_ARRAYS(INT64 , int64 );
- SWAP_ARRAYS(UINT32, uint32);
- SWAP_ARRAYS(UINT64, uint64);
- SWAP_ARRAYS(FLOAT , float );
- SWAP_ARRAYS(DOUBLE, double);
- SWAP_ARRAYS(BOOL , bool );
- SWAP_ARRAYS(ENUM , int );
-#undef SWAP_ARRAYS
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ SwapOneofField(message1, message2, descriptor_->oneof_decl(i));
+ }
- case FieldDescriptor::CPPTYPE_STRING:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
- MutableRaw<RepeatedPtrFieldBase>(message2, field));
- break;
+ if (extensions_offset_ != -1) {
+ MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
+ }
- default:
- GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
- }
- } else {
- switch (field->cpp_type()) {
-#define SWAP_VALUES(CPPTYPE, TYPE) \
- case FieldDescriptor::CPPTYPE_##CPPTYPE: \
- std::swap(*MutableRaw<TYPE>(message1, field), \
- *MutableRaw<TYPE>(message2, field)); \
- break;
+ MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
+}
- SWAP_VALUES(INT32 , int32 );
- SWAP_VALUES(INT64 , int64 );
- SWAP_VALUES(UINT32, uint32);
- SWAP_VALUES(UINT64, uint64);
- SWAP_VALUES(FLOAT , float );
- SWAP_VALUES(DOUBLE, double);
- SWAP_VALUES(BOOL , bool );
- SWAP_VALUES(ENUM , int );
- SWAP_VALUES(MESSAGE, Message*);
-#undef SWAP_VALUES
+void GeneratedMessageReflection::SwapFields(
+ Message* message1,
+ Message* message2,
+ const vector<const FieldDescriptor*>& fields) const {
+ if (message1 == message2) return;
- case FieldDescriptor::CPPTYPE_STRING:
- switch (field->options().ctype()) {
- default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- std::swap(*MutableRaw<string*>(message1, field),
- *MutableRaw<string*>(message2, field));
- break;
- }
- break;
+ // TODO(kenton): Other Reflection methods should probably check this too.
+ GOOGLE_CHECK_EQ(message1->GetReflection(), this)
+ << "First argument to SwapFields() (of type \""
+ << message1->GetDescriptor()->full_name()
+ << "\") is not compatible with this reflection object (which is for type \""
+ << descriptor_->full_name()
+ << "\"). Note that the exact same class is required; not just the same "
+ "descriptor.";
+ GOOGLE_CHECK_EQ(message2->GetReflection(), this)
+ << "Second argument to SwapFields() (of type \""
+ << message2->GetDescriptor()->full_name()
+ << "\") is not compatible with this reflection object (which is for type \""
+ << descriptor_->full_name()
+ << "\"). Note that the exact same class is required; not just the same "
+ "descriptor.";
- default:
- GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+ std::set<int> swapped_oneof;
+
+ for (int i = 0; i < fields.size(); i++) {
+ const FieldDescriptor* field = fields[i];
+ if (field->is_extension()) {
+ MutableExtensionSet(message1)->SwapExtension(
+ MutableExtensionSet(message2),
+ field->number());
+ } else {
+ if (field->containing_oneof()) {
+ int oneof_index = field->containing_oneof()->index();
+ // Only swap the oneof field once.
+ if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) {
+ continue;
+ }
+ swapped_oneof.insert(oneof_index);
+ SwapOneofField(message1, message2, field->containing_oneof());
+ } else {
+ // Swap has bit.
+ SwapBit(message1, message2, field);
+ // Swap field.
+ SwapField(message1, message2, field);
}
}
}
-
- if (extensions_offset_ != -1) {
- MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
- }
-
- MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
}
// -------------------------------------------------------------------
@@ -419,7 +634,11 @@ bool GeneratedMessageReflection::HasField(const Message& message,
if (field->is_extension()) {
return GetExtensionSet(message).Has(field->number());
} else {
- return HasBit(message, field);
+ if (field->containing_oneof()) {
+ return HasOneofField(message, field);
+ } else {
+ return HasBit(message, field);
+ }
}
}
@@ -463,6 +682,11 @@ void GeneratedMessageReflection::ClearField(
if (field->is_extension()) {
MutableExtensionSet(message)->ClearExtension(field->number());
} else if (!field->is_repeated()) {
+ if (field->containing_oneof()) {
+ ClearOneofField(message, field);
+ return;
+ }
+
if (HasBit(*message, field)) {
ClearBit(message, field);
@@ -591,6 +815,20 @@ void GeneratedMessageReflection::RemoveLast(
}
}
+Message* GeneratedMessageReflection::ReleaseLast(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ return static_cast<Message*>(
+ MutableExtensionSet(message)->ReleaseLast(field->number()));
+ } else {
+ return MutableRaw<RepeatedPtrFieldBase>(message, field)
+ ->ReleaseLast<GenericTypeHandler<Message> >();
+ }
+}
+
void GeneratedMessageReflection::SwapElements(
Message* message,
const FieldDescriptor* field,
@@ -653,7 +891,11 @@ void GeneratedMessageReflection::ListFields(
output->push_back(field);
}
} else {
- if (HasBit(message, field)) {
+ if (field->containing_oneof()) {
+ if (HasOneofField(message, field)) {
+ output->push_back(field);
+ }
+ } else if (HasBit(message, field)) {
output->push_back(field);
}
}
@@ -757,7 +999,7 @@ string GeneratedMessageReflection::GetString(
}
GOOGLE_LOG(FATAL) << "Can't get here.";
- return kEmptyString; // Make compiler happy.
+ return GetEmptyString(); // Make compiler happy.
}
}
@@ -776,7 +1018,7 @@ const string& GeneratedMessageReflection::GetStringReference(
}
GOOGLE_LOG(FATAL) << "Can't get here.";
- return kEmptyString; // Make compiler happy.
+ return GetEmptyString(); // Make compiler happy.
}
}
@@ -792,6 +1034,10 @@ void GeneratedMessageReflection::SetString(
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
+ if (field->containing_oneof() && !HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ *MutableField<string*>(message, field) = new string;
+ }
string** ptr = MutableField<string*>(message, field);
if (*ptr == DefaultRaw<const string*>(field)) {
*ptr = new string(value);
@@ -818,7 +1064,7 @@ string GeneratedMessageReflection::GetRepeatedString(
}
GOOGLE_LOG(FATAL) << "Can't get here.";
- return kEmptyString; // Make compiler happy.
+ return GetEmptyString(); // Make compiler happy.
}
}
@@ -836,7 +1082,7 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
}
GOOGLE_LOG(FATAL) << "Can't get here.";
- return kEmptyString; // Make compiler happy.
+ return GetEmptyString(); // Make compiler happy.
}
}
@@ -892,7 +1138,9 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL);
+ GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+ << field->full_name() << " of type "
+ << field->enum_type()->full_name() << ".";
return result;
}
@@ -922,7 +1170,9 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL);
+ GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+ << field->full_name() << " of type "
+ << field->enum_type()->full_name() << ".";
return result;
}
@@ -963,13 +1213,15 @@ const Message& GeneratedMessageReflection::GetMessage(
MessageFactory* factory) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
+
if (field->is_extension()) {
return static_cast<const Message&>(
GetExtensionSet(message).GetMessage(
- field->number(), field->message_type(),
- factory == NULL ? message_factory_ : factory));
+ field->number(), field->message_type(), factory));
} else {
- const Message* result = GetRaw<const Message*>(message, field);
+ const Message* result;
+ result = GetRaw<const Message*>(message, field);
if (result == NULL) {
result = DefaultRaw<const Message*>(field);
}
@@ -980,19 +1232,91 @@ const Message& GeneratedMessageReflection::GetMessage(
Message* GeneratedMessageReflection::MutableMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory) const {
- USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->MutableMessage(field,
- factory == NULL ? message_factory_ : factory));
+ MutableExtensionSet(message)->MutableMessage(field, factory));
} else {
- Message** result = MutableField<Message*>(message, field);
- if (*result == NULL) {
+ Message* result;
+ Message** result_holder = MutableRaw<Message*>(message, field);
+
+ if (field->containing_oneof()) {
+ if (!HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ result_holder = MutableField<Message*>(message, field);
+ const Message* default_message = DefaultRaw<const Message*>(field);
+ *result_holder = default_message->New();
+ }
+ } else {
+ SetBit(message, field);
+ }
+
+ if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
- *result = default_message->New();
+ *result_holder = default_message->New();
}
- return *result;
+ result = *result_holder;
+ return result;
+ }
+}
+
+void GeneratedMessageReflection::SetAllocatedMessage(
+ Message* message,
+ Message* sub_message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->SetAllocatedMessage(
+ field->number(), field->type(), field, sub_message);
+ } else {
+ if (field->containing_oneof()) {
+ if (sub_message == NULL) {
+ ClearOneof(message, field->containing_oneof());
+ return;
+ }
+ ClearOneof(message, field->containing_oneof());
+ *MutableRaw<Message*>(message, field) = sub_message;
+ SetOneofCase(message, field);
+ return;
+ }
+
+ if (sub_message == NULL) {
+ ClearBit(message, field);
+ } else {
+ SetBit(message, field);
+ }
+ Message** sub_message_holder = MutableRaw<Message*>(message, field);
+ delete *sub_message_holder;
+ *sub_message_holder = sub_message;
+ }
+}
+
+Message* GeneratedMessageReflection::ReleaseMessage(
+ Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory) const {
+ USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
+
+ if (factory == NULL) factory = message_factory_;
+
+ if (field->is_extension()) {
+ return static_cast<Message*>(
+ MutableExtensionSet(message)->ReleaseMessage(field, factory));
+ } else {
+ ClearBit(message, field);
+ if (field->containing_oneof()) {
+ if (HasOneofField(*message, field)) {
+ *MutableOneofCase(message, field->containing_oneof()) = 0;
+ } else {
+ return NULL;
+ }
+ }
+ Message** result = MutableRaw<Message*>(message, field);
+ Message* ret = *result;
+ *result = NULL;
+ return ret;
}
}
@@ -1037,7 +1361,7 @@ Message* GeneratedMessageReflection::AddMessage(
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
// know how to allocate one.
RepeatedPtrFieldBase* repeated =
- MutableRaw<RepeatedPtrFieldBase>(message, field);
+ MutableRaw<RepeatedPtrFieldBase>(message, field);
Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
if (result == NULL) {
// We must allocate a new object.
@@ -1054,7 +1378,36 @@ Message* GeneratedMessageReflection::AddMessage(
}
}
-// -------------------------------------------------------------------
+void* GeneratedMessageReflection::MutableRawRepeatedField(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype,
+ int ctype, const Descriptor* desc) const {
+ USAGE_CHECK_REPEATED("MutableRawRepeatedField");
+ if (field->cpp_type() != cpptype)
+ ReportReflectionUsageTypeError(descriptor_,
+ field, "MutableRawRepeatedField", cpptype);
+ if (ctype >= 0)
+ GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+ if (desc != NULL)
+ GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+ if (field->is_extension())
+ return MutableExtensionSet(message)->MutableRawRepeatedField(
+ field->number(), field->type(), field->is_packed(), field);
+ else
+ return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+}
+
+const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
+ const Message& message,
+ const OneofDescriptor* oneof_descriptor) const {
+ uint32 field_number = GetOneofCase(message, oneof_descriptor);
+ if (field_number == 0) {
+ return NULL;
+ }
+ return descriptor_->FindFieldByNumber(field_number);
+}
+
+// -----------------------------------------------------------------------------
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
const string& name) const {
@@ -1100,23 +1453,35 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRaw(
const Message& message, const FieldDescriptor* field) const {
+ if (field->containing_oneof() && !HasOneofField(message, field)) {
+ return DefaultRaw<Type>(field);
+ }
+ int index = field->containing_oneof() ?
+ descriptor_->field_count() + field->containing_oneof()->index() :
+ field->index();
const void* ptr = reinterpret_cast<const uint8*>(&message) +
- offsets_[field->index()];
+ offsets_[index];
return *reinterpret_cast<const Type*>(ptr);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRaw(
Message* message, const FieldDescriptor* field) const {
- void* ptr = reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+ int index = field->containing_oneof() ?
+ descriptor_->field_count() + field->containing_oneof()->index() :
+ field->index();
+ void* ptr = reinterpret_cast<uint8*>(message) + offsets_[index];
return reinterpret_cast<Type*>(ptr);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::DefaultRaw(
const FieldDescriptor* field) const {
- const void* ptr = reinterpret_cast<const uint8*>(default_instance_) +
- offsets_[field->index()];
+ const void* ptr = field->containing_oneof() ?
+ reinterpret_cast<const uint8*>(default_oneof_instance_) +
+ offsets_[field->index()] :
+ reinterpret_cast<const uint8*>(default_instance_) +
+ offsets_[field->index()];
return *reinterpret_cast<const Type*>(ptr);
}
@@ -1131,6 +1496,21 @@ inline uint32* GeneratedMessageReflection::MutableHasBits(
return reinterpret_cast<uint32*>(ptr);
}
+inline uint32 GeneratedMessageReflection::GetOneofCase(
+ const Message& message,
+ const OneofDescriptor* oneof_descriptor) const {
+ const void* ptr = reinterpret_cast<const uint8*>(&message)
+ + oneof_case_offset_;
+ return reinterpret_cast<const uint32*>(ptr)[oneof_descriptor->index()];
+}
+
+inline uint32* GeneratedMessageReflection::MutableOneofCase(
+ Message* message,
+ const OneofDescriptor* oneof_descriptor) const {
+ void* ptr = reinterpret_cast<uint8*>(message) + oneof_case_offset_;
+ return &(reinterpret_cast<uint32*>(ptr)[oneof_descriptor->index()]);
+}
+
inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
const Message& message) const {
GOOGLE_DCHECK_NE(extensions_offset_, -1);
@@ -1162,6 +1542,73 @@ inline void GeneratedMessageReflection::ClearBit(
MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
}
+inline void GeneratedMessageReflection::SwapBit(
+ Message* message1, Message* message2, const FieldDescriptor* field) const {
+ bool temp_has_bit = HasBit(*message1, field);
+ if (HasBit(*message2, field)) {
+ SetBit(message1, field);
+ } else {
+ ClearBit(message1, field);
+ }
+ if (temp_has_bit) {
+ SetBit(message2, field);
+ } else {
+ ClearBit(message2, field);
+ }
+}
+
+inline bool GeneratedMessageReflection::HasOneof(
+ const Message& message, const OneofDescriptor* oneof_descriptor) const {
+ return (GetOneofCase(message, oneof_descriptor) > 0);
+}
+
+inline bool GeneratedMessageReflection::HasOneofField(
+ const Message& message, const FieldDescriptor* field) const {
+ return (GetOneofCase(message, field->containing_oneof()) == field->number());
+}
+
+inline void GeneratedMessageReflection::SetOneofCase(
+ Message* message, const FieldDescriptor* field) const {
+ *MutableOneofCase(message, field->containing_oneof()) = field->number();
+}
+
+inline void GeneratedMessageReflection::ClearOneofField(
+ Message* message, const FieldDescriptor* field) const {
+ if (HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ }
+}
+
+inline void GeneratedMessageReflection::ClearOneof(
+ Message* message, const OneofDescriptor* oneof_descriptor) const {
+ // TODO(jieluo): Consider to cache the unused object instead of deleting
+ // it. It will be much faster if an aplication switches a lot from
+ // a few oneof fields. Time/space tradeoff
+ uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
+ if (oneof_case > 0) {
+ const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING: {
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ delete *MutableRaw<string*>(message, field);
+ break;
+ }
+ break;
+ }
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ delete *MutableRaw<Message*>(message, field);
+ break;
+ default:
+ break;
+ }
+
+ *MutableOneofCase(message, oneof_descriptor) = 0;
+ }
+}
+
// Template implementations of basic accessors. Inline because each
// template instance is only called from one location. These are
// used for all types except messages.
@@ -1174,14 +1621,19 @@ inline const Type& GeneratedMessageReflection::GetField(
template <typename Type>
inline void GeneratedMessageReflection::SetField(
Message* message, const FieldDescriptor* field, const Type& value) const {
+ if (field->containing_oneof() && !HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ }
*MutableRaw<Type>(message, field) = value;
- SetBit(message, field);
+ field->containing_oneof() ?
+ SetOneofCase(message, field) : SetBit(message, field);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableField(
Message* message, const FieldDescriptor* field) const {
- SetBit(message, field);
+ field->containing_oneof() ?
+ SetOneofCase(message, field) : SetBit(message, field);
return MutableRaw<Type>(message, field);
}