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 |