Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(937)

Unified Diff: third_party/protobuf/src/google/protobuf/generated_message_reflection.cc

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
index 56d6b2990d1e219f61f1343c83d33dcbd4e451d7..eee024ee073910754be1897244a7448c7a97dc09 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.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
@@ -33,18 +33,31 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
+#include <set>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/repeated_field.h>
+
+
+#define GOOGLE_PROTOBUF_HAS_ONEOF
namespace google {
namespace protobuf {
namespace internal {
+namespace {
+bool IsMapFieldInApi(const FieldDescriptor* field) {
+ return field->is_map();
+}
+} // anonymous namespace
+
bool ParseNamedEnum(const EnumDescriptor* descriptor,
const string& name,
int* value) {
@@ -59,6 +72,12 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
return (d == NULL ? GetEmptyString() : d->name());
}
+namespace {
+inline bool SupportsArenas(const Descriptor* descriptor) {
+ return descriptor->file()->options().cc_enable_arenas();
+}
+} // anonymous namespace
+
// ===================================================================
// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
// a string field).
@@ -162,13 +181,48 @@ GeneratedMessageReflection::GeneratedMessageReflection(
int extensions_offset,
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
- int object_size)
+ int object_size,
+ int arena_offset,
+ int is_default_instance_offset)
+ : descriptor_ (descriptor),
+ default_instance_ (default_instance),
+ offsets_ (offsets),
+ has_bits_offset_ (has_bits_offset),
+ unknown_fields_offset_(unknown_fields_offset),
+ extensions_offset_(extensions_offset),
+ arena_offset_ (arena_offset),
+ is_default_instance_offset_(is_default_instance_offset),
+ object_size_ (object_size),
+ descriptor_pool_ ((descriptor_pool == NULL) ?
+ DescriptorPool::generated_pool() :
+ descriptor_pool),
+ 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,
+ int arena_offset,
+ int is_default_instance_offset)
: 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),
+ arena_offset_ (arena_offset),
+ is_default_instance_offset_(is_default_instance_offset),
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
@@ -178,14 +232,45 @@ GeneratedMessageReflection::GeneratedMessageReflection(
GeneratedMessageReflection::~GeneratedMessageReflection() {}
+namespace {
+UnknownFieldSet* empty_unknown_field_set_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
+
+void DeleteEmptyUnknownFieldSet() {
+ delete empty_unknown_field_set_;
+ empty_unknown_field_set_ = NULL;
+}
+
+void InitEmptyUnknownFieldSet() {
+ empty_unknown_field_set_ = new UnknownFieldSet;
+ internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
+}
+
+const UnknownFieldSet& GetEmptyUnknownFieldSet() {
+ ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet);
+ return *empty_unknown_field_set_;
+}
+} // namespace
+
const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
const Message& message) const {
+ if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return GetEmptyUnknownFieldSet();
+ }
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ return GetInternalMetadataWithArena(message).unknown_fields();
+ }
const void* ptr = reinterpret_cast<const uint8*>(&message) +
unknown_fields_offset_;
return *reinterpret_cast<const UnknownFieldSet*>(ptr);
}
+
UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
Message* message) const {
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ return MutableInternalMetadataWithArena(message)->
+ mutable_unknown_fields();
+ }
void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
return reinterpret_cast<UnknownFieldSet*>(ptr);
}
@@ -234,14 +319,23 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- // We don't know which subclass of RepeatedPtrFieldBase the type is,
- // so we use RepeatedPtrFieldBase directly.
- total_size +=
- GetRaw<RepeatedPtrFieldBase>(message, field)
- .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+ if (IsMapFieldInApi(field)) {
+ total_size +=
+ GetRaw<MapFieldBase>(message, field).SpaceUsedExcludingSelf();
+ } else {
+ // We don't know which subclass of RepeatedPtrFieldBase the type is,
+ // so we use RepeatedPtrFieldBase directly.
+ total_size +=
+ GetRaw<RepeatedPtrFieldBase>(message, field)
+ .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+ }
+
break;
}
} else {
+ if (field->containing_oneof() && !HasOneofField(message, field)) {
+ continue;
+ }
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32 :
case FieldDescriptor::CPPTYPE_INT64 :
@@ -258,12 +352,13 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
- const string* ptr = GetField<const string*>(message, field);
-
// Initially, the string points to the default value stored in
// the prototype. Only count the string if it has been changed
// from the default value.
- const string* default_ptr = DefaultRaw<const string*>(field);
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ const string* ptr =
+ &GetField<ArenaStringPtr>(message, field).Get(default_ptr);
if (ptr != default_ptr) {
// string fields are represented by just a pointer, so also
@@ -294,6 +389,204 @@ 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:
+ if (IsMapFieldInApi(field)) {
+ MutableRaw<MapFieldBase>(message1, field)->
+ MutableRepeatedField()->
+ Swap<GenericTypeHandler<google::protobuf::Message> >(
+ MutableRaw<MapFieldBase>(message2, field)->
+ MutableRepeatedField());
+ } else {
+ MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+ Swap<GenericTypeHandler<google::protobuf::Message> >(
+ 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:
+ MutableRaw<ArenaStringPtr>(message1, field)->Swap(
+ MutableRaw<ArenaStringPtr>(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 = NULL;
+ string temp_string;
+
+ // Stores message1's oneof field to a temp variable.
+ const FieldDescriptor* field1 = NULL;
+ 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 {
@@ -315,86 +608,96 @@ void GeneratedMessageReflection::Swap(
<< "\"). Note that the exact same class is required; not just the same "
"descriptor.";
- uint32* has_bits1 = MutableHasBits(message1);
- uint32* has_bits2 = MutableHasBits(message2);
- int has_bits_size = (descriptor_->field_count() + 31) / 32;
+ // Check that both messages are in the same arena (or both on the heap). We
+ // need to copy all data if not, due to ownership semantics.
+ if (GetArena(message1) != GetArena(message2)) {
+ // Slow copy path.
+ // Use our arena as temp space, if available.
+ Message* temp = message1->New(GetArena(message1));
+ temp->MergeFrom(*message1);
+ message1->CopyFrom(*message2);
+ message2->CopyFrom(*temp);
+ if (GetArena(message1) == NULL) {
+ delete temp;
+ }
+ return;
+ }
+
+ if (has_bits_offset_ != -1) {
+ uint32* has_bits1 = MutableHasBits(message1);
+ uint32* has_bits2 = MutableHasBits(message2);
+ int has_bits_size = (descriptor_->field_count() + 31) / 32;
- for (int i = 0; i < has_bits_size; i++) {
- std::swap(has_bits1[i], has_bits2[i]);
+ for (int i = 0; i < has_bits_size; i++) {
+ std::swap(has_bits1[i], has_bits2[i]);
+ }
}
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 );
-#undef SWAP_VALUES
- case FieldDescriptor::CPPTYPE_MESSAGE:
- std::swap(*MutableRaw<Message*>(message1, field),
- *MutableRaw<Message*>(message2, field));
- break;
+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));
}
// -------------------------------------------------------------------
@@ -407,7 +710,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);
+ }
}
}
@@ -436,7 +743,11 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
- return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+ if (IsMapFieldInApi(field)) {
+ return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
+ } else {
+ return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+ }
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -451,6 +762,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);
@@ -479,23 +795,28 @@ void GeneratedMessageReflection::ClearField(
case FieldDescriptor::CPPTYPE_STRING: {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- const string* default_ptr = DefaultRaw<const string*>(field);
- string** value = MutableRaw<string*>(message, field);
- if (*value != default_ptr) {
- if (field->has_default_value()) {
- (*value)->assign(field->default_value_string());
- } else {
- (*value)->clear();
- }
- }
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
+ GetArena(message));
break;
+ }
}
break;
}
case FieldDescriptor::CPPTYPE_MESSAGE:
- (*MutableRaw<Message*>(message, field))->Clear();
+ if (has_bits_offset_ == -1) {
+ // Proto3 does not have has-bits and we need to set a message field
+ // to NULL in order to indicate its un-presence.
+ if (GetArena(message) == NULL) {
+ delete *MutableRaw<Message*>(message, field);
+ }
+ *MutableRaw<Message*>(message, field) = NULL;
+ } else {
+ (*MutableRaw<Message*>(message, field))->Clear();
+ }
break;
}
}
@@ -527,10 +848,16 @@ void GeneratedMessageReflection::ClearField(
}
case FieldDescriptor::CPPTYPE_MESSAGE: {
- // We don't know which subclass of RepeatedPtrFieldBase the type is,
- // so we use RepeatedPtrFieldBase directly.
- MutableRaw<RepeatedPtrFieldBase>(message, field)
- ->Clear<GenericTypeHandler<Message> >();
+ if (IsMapFieldInApi(field)) {
+ MutableRaw<MapFieldBase>(message, field)
+ ->MutableRepeatedField()
+ ->Clear<GenericTypeHandler<Message> >();
+ } else {
+ // We don't know which subclass of RepeatedPtrFieldBase the type is,
+ // so we use RepeatedPtrFieldBase directly.
+ MutableRaw<RepeatedPtrFieldBase>(message, field)
+ ->Clear<GenericTypeHandler<Message> >();
+ }
break;
}
}
@@ -572,8 +899,14 @@ void GeneratedMessageReflection::RemoveLast(
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- MutableRaw<RepeatedPtrFieldBase>(message, field)
+ if (IsMapFieldInApi(field)) {
+ MutableRaw<MapFieldBase>(message, field)
+ ->MutableRepeatedField()
+ ->RemoveLast<GenericTypeHandler<Message> >();
+ } else {
+ MutableRaw<RepeatedPtrFieldBase>(message, field)
->RemoveLast<GenericTypeHandler<Message> >();
+ }
break;
}
}
@@ -588,8 +921,14 @@ Message* GeneratedMessageReflection::ReleaseLast(
return static_cast<Message*>(
MutableExtensionSet(message)->ReleaseLast(field->number()));
} else {
- return MutableRaw<RepeatedPtrFieldBase>(message, field)
+ if (IsMapFieldInApi(field)) {
+ return MutableRaw<MapFieldBase>(message, field)
+ ->MutableRepeatedField()
+ ->ReleaseLast<GenericTypeHandler<Message> >();
+ } else {
+ return MutableRaw<RepeatedPtrFieldBase>(message, field)
->ReleaseLast<GenericTypeHandler<Message> >();
+ }
}
}
@@ -623,8 +962,14 @@ void GeneratedMessageReflection::SwapElements(
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
- MutableRaw<RepeatedPtrFieldBase>(message, field)
+ if (IsMapFieldInApi(field)) {
+ MutableRaw<MapFieldBase>(message, field)
+ ->MutableRepeatedField()
+ ->SwapElements(index1, index2);
+ } else {
+ MutableRaw<RepeatedPtrFieldBase>(message, field)
->SwapElements(index1, index2);
+ }
break;
}
}
@@ -648,6 +993,7 @@ void GeneratedMessageReflection::ListFields(
// Optimization: The default instance never has any fields set.
if (&message == default_instance_) return;
+ output->reserve(descriptor_->field_count());
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
@@ -655,7 +1001,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);
}
}
@@ -667,7 +1017,7 @@ void GeneratedMessageReflection::ListFields(
}
// ListFields() must sort output by field number.
- sort(output->begin(), output->end(), FieldNumberSorter());
+ std::sort(output->begin(), output->end(), FieldNumberSorter());
}
// -------------------------------------------------------------------
@@ -754,8 +1104,11 @@ string GeneratedMessageReflection::GetString(
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- return *GetField<const string*>(message, field);
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+ }
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -773,8 +1126,11 @@ const string& GeneratedMessageReflection::GetStringReference(
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- return *GetField<const string*>(message, field);
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+ }
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -794,12 +1150,15 @@ void GeneratedMessageReflection::SetString(
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
- string** ptr = MutableField<string*>(message, field);
- if (*ptr == DefaultRaw<const string*>(field)) {
- *ptr = new string(value);
- } else {
- (*ptr)->assign(value);
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ if (field->containing_oneof() && !HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault(
+ default_ptr);
}
+ MutableField<ArenaStringPtr>(message, field)->Set(default_ptr,
+ value, GetArena(message));
break;
}
}
@@ -881,42 +1240,80 @@ void GeneratedMessageReflection::AddString(
// -------------------------------------------------------------------
+inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
const Message& message, const FieldDescriptor* field) const {
- USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
+ // Usage checked by GetEnumValue.
+ int value = GetEnumValue(message, field);
+ return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
- int value;
+int GeneratedMessageReflection::GetEnumValue(
+ const Message& message, const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
+
+ int32 value;
if (field->is_extension()) {
value = GetExtensionSet(message).GetEnum(
field->number(), field->default_value_enum()->number());
} else {
value = GetField<int>(message, field);
}
- const EnumValueDescriptor* result =
- field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
- << field->full_name() << " of type "
- << field->enum_type()->full_name() << ".";
- return result;
+ return value;
}
void GeneratedMessageReflection::SetEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
+ // Usage checked by SetEnumValue.
USAGE_CHECK_ENUM_VALUE(SetEnum);
+ SetEnumValueInternal(message, field, value->number());
+}
+
+void GeneratedMessageReflection::SetEnumValue(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
+ USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "SetEnumValue accepts only valid integer values: value "
+ << value << " unexpected for field " << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ SetEnumValueInternal(message, field, value);
+}
+void GeneratedMessageReflection::SetEnumValueInternal(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
- value->number(), field);
+ value, field);
} else {
- SetField<int>(message, field, value->number());
+ SetField<int>(message, field, value);
}
}
const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
const Message& message, const FieldDescriptor* field, int index) const {
- USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
+ // Usage checked by GetRepeatedEnumValue.
+ int value = GetRepeatedEnumValue(message, field, index);
+ return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
+
+int GeneratedMessageReflection::GetRepeatedEnumValue(
+ const Message& message, const FieldDescriptor* field, int index) const {
+ USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
int value;
if (field->is_extension()) {
@@ -924,41 +1321,89 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
} else {
value = GetRepeatedField<int>(message, field, index);
}
- const EnumValueDescriptor* result =
- field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
- << field->full_name() << " of type "
- << field->enum_type()->full_name() << ".";
- return result;
+ return value;
}
void GeneratedMessageReflection::SetRepeatedEnum(
Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+ // Usage checked by SetRepeatedEnumValue.
USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
+ SetRepeatedEnumValueInternal(message, field, index, value->number());
+}
+void GeneratedMessageReflection::SetRepeatedEnumValue(
+ Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const {
+ USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "SetRepeatedEnumValue accepts only valid integer values: "
+ << "value " << value << " unexpected for field "
+ << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ SetRepeatedEnumValueInternal(message, field, index, value);
+}
+
+void GeneratedMessageReflection::SetRepeatedEnumValueInternal(
+ Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->SetRepeatedEnum(
- field->number(), index, value->number());
+ field->number(), index, value);
} else {
- SetRepeatedField<int>(message, field, index, value->number());
+ SetRepeatedField<int>(message, field, index, value);
}
}
void GeneratedMessageReflection::AddEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+ // Usage checked by AddEnumValue.
USAGE_CHECK_ENUM_VALUE(AddEnum);
+ AddEnumValueInternal(message, field, value->number());
+}
+
+void GeneratedMessageReflection::AddEnumValue(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
+ USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "AddEnumValue accepts only valid integer values: value "
+ << value << " unexpected for field " << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ AddEnumValueInternal(message, field, value);
+}
+void GeneratedMessageReflection::AddEnumValueInternal(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
field->options().packed(),
- value->number(), field);
+ value, field);
} else {
- AddField<int>(message, field, value->number());
+ AddField<int>(message, field, value);
}
}
@@ -997,17 +1442,91 @@ Message* GeneratedMessageReflection::MutableMessage(
MutableExtensionSet(message)->MutableMessage(field, factory));
} else {
Message* result;
- Message** result_holder = MutableField<Message*>(message, field);
+ 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(message->GetArena());
+ }
+ } else {
+ SetBit(message, field);
+ }
+
if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
- *result_holder = default_message->New();
+ *result_holder = default_message->New(message->GetArena());
}
result = *result_holder;
return result;
}
}
-Message* GeneratedMessageReflection::ReleaseMessage(
+void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage(
+ 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);
+ if (GetArena(message) == NULL) {
+ delete *sub_message_holder;
+ }
+ *sub_message_holder = sub_message;
+ }
+}
+
+void GeneratedMessageReflection::SetAllocatedMessage(
+ Message* message,
+ Message* sub_message,
+ const FieldDescriptor* field) const {
+ // If message and sub-message are in different memory ownership domains
+ // (different arenas, or one is on heap and one is not), then we may need to
+ // do a copy.
+ if (sub_message != NULL &&
+ sub_message->GetArena() != message->GetArena()) {
+ if (sub_message->GetArena() == NULL && message->GetArena() != NULL) {
+ // Case 1: parent is on an arena and child is heap-allocated. We can add
+ // the child to the arena's Own() list to free on arena destruction, then
+ // set our pointer.
+ message->GetArena()->Own(sub_message);
+ UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+ } else {
+ // Case 2: all other cases. We need to make a copy. MutableMessage() will
+ // either get the existing message object, or instantiate a new one as
+ // appropriate w.r.t. our arena.
+ Message* sub_message_copy = MutableMessage(message, field);
+ sub_message_copy->CopyFrom(*sub_message);
+ }
+ } else {
+ // Same memory ownership domains.
+ UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+ }
+}
+
+Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
Message* message,
const FieldDescriptor* field,
MessageFactory* factory) const {
@@ -1020,6 +1539,13 @@ Message* GeneratedMessageReflection::ReleaseMessage(
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;
@@ -1027,6 +1553,19 @@ Message* GeneratedMessageReflection::ReleaseMessage(
}
}
+Message* GeneratedMessageReflection::ReleaseMessage(
+ Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory) const {
+ Message* released = UnsafeArenaReleaseMessage(message, field, factory);
+ if (GetArena(message) != NULL && released != NULL) {
+ Message* copy_from_arena = released->New();
+ copy_from_arena->CopyFrom(*released);
+ released = copy_from_arena;
+ }
+ return released;
+}
+
const Message& GeneratedMessageReflection::GetRepeatedMessage(
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
@@ -1035,8 +1574,14 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
return static_cast<const Message&>(
GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
} else {
- return GetRaw<RepeatedPtrFieldBase>(message, field)
- .Get<GenericTypeHandler<Message> >(index);
+ if (IsMapFieldInApi(field)) {
+ return GetRaw<MapFieldBase>(message, field)
+ .GetRepeatedField()
+ .Get<GenericTypeHandler<Message> >(index);
+ } else {
+ return GetRaw<RepeatedPtrFieldBase>(message, field)
+ .Get<GenericTypeHandler<Message> >(index);
+ }
}
}
@@ -1049,8 +1594,14 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
MutableExtensionSet(message)->MutableRepeatedMessage(
field->number(), index));
} else {
- return MutableRaw<RepeatedPtrFieldBase>(message, field)
+ if (IsMapFieldInApi(field)) {
+ return MutableRaw<MapFieldBase>(message, field)
+ ->MutableRepeatedField()
+ ->Mutable<GenericTypeHandler<Message> >(index);
+ } else {
+ return MutableRaw<RepeatedPtrFieldBase>(message, field)
->Mutable<GenericTypeHandler<Message> >(index);
+ }
}
}
@@ -1065,11 +1616,18 @@ Message* GeneratedMessageReflection::AddMessage(
return static_cast<Message*>(
MutableExtensionSet(message)->AddMessage(field, factory));
} else {
+ Message* result = NULL;
+
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
// know how to allocate one.
- RepeatedPtrFieldBase* repeated =
- MutableRaw<RepeatedPtrFieldBase>(message, field);
- Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
+ RepeatedPtrFieldBase* repeated = NULL;
+ if (IsMapFieldInApi(field)) {
+ repeated =
+ MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+ } else {
+ repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+ }
+ result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
if (result == NULL) {
// We must allocate a new object.
const Message* prototype;
@@ -1078,13 +1636,36 @@ Message* GeneratedMessageReflection::AddMessage(
} else {
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
}
- result = prototype->New();
- repeated->AddAllocated<GenericTypeHandler<Message> >(result);
+ result = prototype->New(message->GetArena());
+ // We can guarantee here that repeated and result are either both heap
+ // allocated or arena owned. So it is safe to call the unsafe version
+ // of AddAllocated.
+ repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
}
+
return result;
}
}
+void GeneratedMessageReflection::AddAllocatedMessage(
+ Message* message, const FieldDescriptor* field,
+ Message* new_entry) const {
+ USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
+ } else {
+ RepeatedPtrFieldBase* repeated = NULL;
+ if (IsMapFieldInApi(field)) {
+ repeated =
+ MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+ } else {
+ repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+ }
+ repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry);
+ }
+}
+
void* GeneratedMessageReflection::MutableRawRepeatedField(
Message* message, const FieldDescriptor* field,
FieldDescriptor::CppType cpptype,
@@ -1097,11 +1678,122 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
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())
+ if (field->is_extension()) {
return MutableExtensionSet(message)->MutableRawRepeatedField(
- field->number());
- else
+ field->number(), field->type(), field->is_packed(), field);
+ } else {
+ // Trigger transform for MapField
+ if (IsMapFieldInApi(field)) {
+ return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
+ offsets_[field->index()])
+ ->MutableRepeatedField();
+ }
return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+ }
+}
+
+const void* GeneratedMessageReflection::GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype,
+ int ctype, const Descriptor* desc) const {
+ USAGE_CHECK_REPEATED("GetRawRepeatedField");
+ if (field->cpp_type() != cpptype)
+ ReportReflectionUsageTypeError(descriptor_,
+ field, "GetRawRepeatedField", 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()) {
+ // Should use extension_set::GetRawRepeatedField. However, the required
+ // parameter "default repeated value" is not very easy to get here.
+ // Map is not supported in extensions, it is acceptable to use
+ // extension_set::MutableRawRepeatedField which does not change the message.
+ return MutableExtensionSet(const_cast<Message*>(&message))
+ ->MutableRawRepeatedField(
+ field->number(), field->type(), field->is_packed(), field);
+ } else {
+ // Trigger transform for MapField
+ if (IsMapFieldInApi(field)) {
+ return &(reinterpret_cast<const MapFieldBase*>(
+ reinterpret_cast<const uint8*>(&message) +
+ offsets_[field->index()])->GetRepeatedField());
+ }
+ return reinterpret_cast<const 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);
+}
+
+bool GeneratedMessageReflection::ContainsMapKey(
+ const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "LookupMapValue",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
+}
+
+bool GeneratedMessageReflection::InsertOrLookupMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "InsertOrLookupMapValue",
+ "Field is not a map field.");
+ val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+ return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val);
+}
+
+bool GeneratedMessageReflection::DeleteMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "DeleteMapValue",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
+}
+
+MapIterator GeneratedMessageReflection::MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapBegin",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
+ return iter;
+}
+
+MapIterator GeneratedMessageReflection::MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapEnd",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
+ return iter;
+}
+
+int GeneratedMessageReflection::MapSize(
+ const Message& message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapSize",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).size();
}
// -----------------------------------------------------------------------------
@@ -1142,6 +1834,10 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
}
+bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
+ return CreateUnknownEnumValues(descriptor_->file());
+}
+
// ===================================================================
// Some private helpers.
@@ -1150,37 +1846,70 @@ 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);
}
inline const uint32* GeneratedMessageReflection::GetHasBits(
const Message& message) const {
+ if (has_bits_offset_ == -1) { // proto3 with no has-bits.
+ return NULL;
+ }
const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
return reinterpret_cast<const uint32*>(ptr);
}
inline uint32* GeneratedMessageReflection::MutableHasBits(
Message* message) const {
+ if (has_bits_offset_ == -1) {
+ return NULL;
+ }
void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
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);
@@ -1195,23 +1924,196 @@ inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
return reinterpret_cast<ExtensionSet*>(ptr);
}
+inline Arena* GeneratedMessageReflection::GetArena(Message* message) const {
+ if (arena_offset_ == kNoArenaPointer) {
+ return NULL;
+ }
+
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ // zero-overhead arena pointer overloading UnknownFields
+ return GetInternalMetadataWithArena(*message).arena();
+ }
+
+ // Baseline case: message class has a dedicated arena pointer.
+ void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+ return *reinterpret_cast<Arena**>(ptr);
+}
+
+inline const InternalMetadataWithArena&
+GeneratedMessageReflection::GetInternalMetadataWithArena(
+ const Message& message) const {
+ const void* ptr = reinterpret_cast<const uint8*>(&message) + arena_offset_;
+ return *reinterpret_cast<const InternalMetadataWithArena*>(ptr);
+}
+
+inline InternalMetadataWithArena*
+GeneratedMessageReflection::MutableInternalMetadataWithArena(
+ Message* message) const {
+ void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+ return reinterpret_cast<InternalMetadataWithArena*>(ptr);
+}
+
+inline bool
+GeneratedMessageReflection::GetIsDefaultInstance(
+ const Message& message) const {
+ if (is_default_instance_offset_ == kHasNoDefaultInstanceField) {
+ return false;
+ }
+ const void* ptr = reinterpret_cast<const uint8*>(&message) +
+ is_default_instance_offset_;
+ return *reinterpret_cast<const bool*>(ptr);
+}
+
// Simple accessors for manipulating has_bits_.
inline bool GeneratedMessageReflection::HasBit(
const Message& message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ // proto3: no has-bits. All fields present except messages, which are
+ // present only if their message-field pointer is non-NULL.
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ return !GetIsDefaultInstance(message) &&
+ GetRaw<const Message*>(message, field) != NULL;
+ } else {
+ // Non-message field (and non-oneof, since that was handled in HasField()
+ // before calling us), and singular (again, checked in HasField). So, this
+ // field must be a scalar.
+
+ // Scalar primitive (numeric or string/bytes) fields are present if
+ // their value is non-zero (numeric) or non-empty (string/bytes). N.B.:
+ // we must use this definition here, rather than the "scalar fields
+ // always present" in the proto3 docs, because MergeFrom() semantics
+ // require presence as "present on wire", and reflection-based merge
+ // (which uses HasField()) needs to be consistent with this.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(
+ default_ptr).size() > 0;
+ }
+ }
+ return false;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return GetRaw<bool>(message, field) != false;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return GetRaw<int32>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return GetRaw<int64>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return GetRaw<uint32>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return GetRaw<uint64>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return GetRaw<float>(message, field) != 0.0;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return GetRaw<double>(message, field) != 0.0;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return GetRaw<int>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ // handled above; avoid warning
+ GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
+ break;
+ }
+ }
+ }
return GetHasBits(message)[field->index() / 32] &
(1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::SetBit(
Message* message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::ClearBit(
Message* message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
}
+inline void GeneratedMessageReflection::SwapBit(
+ Message* message1, Message* message2, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
+ 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);
+ if (GetArena(message) == NULL) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING: {
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableField<ArenaStringPtr>(message, field)->
+ Destroy(default_ptr, GetArena(message));
+ 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.
@@ -1224,14 +2126,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);
}
@@ -1276,6 +2183,92 @@ inline Type* GeneratedMessageReflection::AddField(
return repeated->Add();
}
+MessageFactory* GeneratedMessageReflection::GetMessageFactory() const {
+ return message_factory_;
+}
+
+void* GeneratedMessageReflection::RepeatedFieldData(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpp_type,
+ const Descriptor* message_type) const {
+ GOOGLE_CHECK(field->is_repeated());
+ GOOGLE_CHECK(field->cpp_type() == cpp_type ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+ cpp_type == FieldDescriptor::CPPTYPE_INT32))
+ << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
+ << "the actual field type (for enums T should be the generated enum "
+ << "type or int32).";
+ if (message_type != NULL) {
+ GOOGLE_CHECK_EQ(message_type, field->message_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()];
+ }
+}
+
+MapFieldBase* GeneratedMessageReflection::MapData(
+ Message* message, const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "GetMapData",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field);
+}
+
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+ 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,
+ int object_size,
+ int arena_offset,
+ int is_default_instance_offset) {
+ return new GeneratedMessageReflection(descriptor,
+ default_instance,
+ offsets,
+ has_bits_offset,
+ unknown_fields_offset,
+ extensions_offset,
+ default_oneof_instance,
+ oneof_case_offset,
+ DescriptorPool::generated_pool(),
+ MessageFactory::generated_factory(),
+ object_size,
+ arena_offset,
+ is_default_instance_offset);
+}
+
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+ const Descriptor* descriptor,
+ const Message* default_instance,
+ const int offsets[],
+ int has_bits_offset,
+ int unknown_fields_offset,
+ int extensions_offset,
+ int object_size,
+ int arena_offset,
+ int is_default_instance_offset) {
+ return new GeneratedMessageReflection(descriptor,
+ default_instance,
+ offsets,
+ has_bits_offset,
+ unknown_fields_offset,
+ extensions_offset,
+ DescriptorPool::generated_pool(),
+ MessageFactory::generated_factory(),
+ object_size,
+ arena_offset,
+ is_default_instance_offset);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google

Powered by Google App Engine
This is Rietveld 408576698