blob: 2313181cc995220fe39ce23236e365b467e05276 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// 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
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// 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/descriptor.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/generated_message_util.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) {
const EnumValueDescriptor* d = descriptor->FindValueByName(name);
if (d == NULL) return false;
*value = d->number();
return true;
}
const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
const EnumValueDescriptor* d = descriptor->FindValueByNumber(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).
namespace {
void ReportReflectionUsageError(
const Descriptor* descriptor, const FieldDescriptor* field,
const char* method, const char* description) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : " << description;
}
const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
"INVALID_CPPTYPE",
"CPPTYPE_INT32",
"CPPTYPE_INT64",
"CPPTYPE_UINT32",
"CPPTYPE_UINT64",
"CPPTYPE_DOUBLE",
"CPPTYPE_FLOAT",
"CPPTYPE_BOOL",
"CPPTYPE_ENUM",
"CPPTYPE_STRING",
"CPPTYPE_MESSAGE"
};
static void ReportReflectionUsageTypeError(
const Descriptor* descriptor, const FieldDescriptor* field,
const char* method,
FieldDescriptor::CppType expected_type) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : Field is not the right type for this message:\n"
" Expected : " << cpptype_names_[expected_type] << "\n"
" Field type: " << cpptype_names_[field->cpp_type()];
}
static void ReportReflectionUsageEnumTypeError(
const Descriptor* descriptor, const FieldDescriptor* field,
const char* method, const EnumValueDescriptor* value) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : Enum value did not match field type:\n"
" Expected : " << field->enum_type()->full_name() << "\n"
" Actual : " << value->full_name();
}
#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
if (!(CONDITION)) \
ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \
USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \
USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \
if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \
ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \
FieldDescriptor::CPPTYPE_##CPPTYPE)
#define USAGE_CHECK_ENUM_VALUE(METHOD) \
if (value->type() != field->enum_type()) \
ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \
USAGE_CHECK_EQ(field->containing_type(), descriptor_, \
METHOD, "Field does not match message type.");
#define USAGE_CHECK_SINGULAR(METHOD) \
USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
"Field is repeated; the method requires a singular field.")
#define USAGE_CHECK_REPEATED(METHOD) \
USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
"Field is singular; the method requires a repeated field.")
#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \
USAGE_CHECK_MESSAGE_TYPE(METHOD); \
USAGE_CHECK_##LABEL(METHOD); \
USAGE_CHECK_TYPE(METHOD, CPPTYPE)
} // namespace
// ===================================================================
GeneratedMessageReflection::GeneratedMessageReflection(
const Descriptor* descriptor,
const Message* default_instance,
const int offsets[],
int has_bits_offset,
int unknown_fields_offset,
int extensions_offset,
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
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() :
descriptor_pool),
message_factory_ (factory) {
}
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);
}
int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
// object_size_ already includes the in-memory representation of each field
// in the message, so we only need to account for additional memory used by
// the fields.
int total_size = object_size_;
total_size += GetUnknownFields(message).SpaceUsedExcludingSelf();
if (extensions_offset_ != -1) {
total_size += GetExtensionSet(message).SpaceUsedExcludingSelf();
}
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field) \
.SpaceUsedExcludingSelf(); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, int);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
total_size += GetRaw<RepeatedPtrField<string> >(message, field)
.SpaceUsedExcludingSelf();
break;
}
break;
case FieldDescriptor::CPPTYPE_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 :
case FieldDescriptor::CPPTYPE_UINT32:
case FieldDescriptor::CPPTYPE_UINT64:
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT :
case FieldDescriptor::CPPTYPE_BOOL :
case FieldDescriptor::CPPTYPE_ENUM :
// Field is inline, so we've already counted it.
break;
case FieldDescriptor::CPPTYPE_STRING: {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
// 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<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
// include sizeof(string) as well.
total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
}
break;
}
}
break;
}
case FieldDescriptor::CPPTYPE_MESSAGE:
if (&message == default_instance_) {
// For singular fields, the prototype just stores a pointer to the
// external type's prototype, so there is no extra memory usage.
} else {
const Message* sub_message = GetRaw<const Message*>(message, field);
if (sub_message != NULL) {
total_size += sub_message->SpaceUsed();
}
}
break;
}
}
}
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:
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
MutableRaw<RepeatedPtrFieldBase>(message1, field)->
Swap<GenericTypeHandler<string> >(
MutableRaw<RepeatedPtrFieldBase>(message2, field));
break;
}
break;
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:
if (GetArena(message1) == GetArena(message2)) {
std::swap(*MutableRaw<Message*>(message1, field),
*MutableRaw<Message*>(message2, field));
} else {
Message** sub_msg1 = MutableRaw<Message*>(message1, field);
Message** sub_msg2 = MutableRaw<Message*>(message2, field);
if (*sub_msg1 == NULL && *sub_msg2 == NULL) break;
if (*sub_msg1 && *sub_msg2) {
(*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2);
break;
}
if (*sub_msg1 == NULL) {
*sub_msg1 = (*sub_msg2)->New(message1->GetArena());
(*sub_msg1)->CopyFrom(**sub_msg2);
ClearField(message2, field);
} else {
*sub_msg2 = (*sub_msg1)->New(message2->GetArena());
(*sub_msg2)->CopyFrom(**sub_msg1);
ClearField(message1, field);
}
}
break;
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
{
Arena* arena1 = GetArena(message1);
Arena* arena2 = GetArena(message2);
ArenaStringPtr* string1 =
MutableRaw<ArenaStringPtr>(message1, field);
ArenaStringPtr* string2 =
MutableRaw<ArenaStringPtr>(message2, field);
if (arena1 == arena2) {
string1->Swap(string2);
} else {
const string* default_ptr =
&DefaultRaw<ArenaStringPtr>(field).Get(NULL);
const string temp = string1->Get(default_ptr);
string1->Set(default_ptr, string2->Get(default_ptr), arena1);
string2->Set(default_ptr, temp, arena2);
}
}
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 {
if (message1 == message2) return;
// TODO(kenton): Other Reflection methods should probably check this too.
GOOGLE_CHECK_EQ(message1->GetReflection(), this)
<< "First argument to Swap() (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 Swap() (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.";
// 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 < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (!field->containing_oneof()) {
SwapField(message1, message2, field);
}
}
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
SwapOneofField(message1, message2, descriptor_->oneof_decl(i));
}
if (extensions_offset_ != -1) {
MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
}
MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
}
void GeneratedMessageReflection::SwapFields(
Message* message1,
Message* message2,
const vector<const FieldDescriptor*>& fields) const {
if (message1 == message2) return;
// 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.";
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);
}
}
}
}
// -------------------------------------------------------------------
bool GeneratedMessageReflection::HasField(const Message& message,
const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(HasField);
USAGE_CHECK_SINGULAR(HasField);
if (field->is_extension()) {
return GetExtensionSet(message).Has(field->number());
} else {
if (field->containing_oneof()) {
return HasOneofField(message, field);
} else {
return HasBit(message, field);
}
}
}
int GeneratedMessageReflection::FieldSize(const Message& message,
const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(FieldSize);
USAGE_CHECK_REPEATED(FieldSize);
if (field->is_extension()) {
return GetExtensionSet(message).ExtensionSize(field->number());
} else {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, int);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
} else {
return GetRaw<RepeatedPtrFieldBase>(message, field).size();
}
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return 0;
}
}
void GeneratedMessageReflection::ClearField(
Message* message, const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(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);
// We need to set the field back to its default value.
switch (field->cpp_type()) {
#define CLEAR_TYPE(CPPTYPE, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
*MutableRaw<TYPE>(message, field) = \
field->default_value_##TYPE(); \
break;
CLEAR_TYPE(INT32 , int32 );
CLEAR_TYPE(INT64 , int64 );
CLEAR_TYPE(UINT32, uint32);
CLEAR_TYPE(UINT64, uint64);
CLEAR_TYPE(FLOAT , float );
CLEAR_TYPE(DOUBLE, double);
CLEAR_TYPE(BOOL , bool );
#undef CLEAR_TYPE
case FieldDescriptor::CPPTYPE_ENUM:
*MutableRaw<int>(message, field) =
field->default_value_enum()->number();
break;
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);
MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
GetArena(message));
break;
}
}
break;
}
case FieldDescriptor::CPPTYPE_MESSAGE:
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;
}
}
} else {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear(); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, int);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING: {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
break;
}
break;
}
case FieldDescriptor::CPPTYPE_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;
}
}
}
}
void GeneratedMessageReflection::RemoveLast(
Message* message,
const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
USAGE_CHECK_REPEATED(RemoveLast);
if (field->is_extension()) {
MutableExtensionSet(message)->RemoveLast(field->number());
} else {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast(); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, int);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
break;
}
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
MutableRaw<MapFieldBase>(message, field)
->MutableRepeatedField()
->RemoveLast<GenericTypeHandler<Message> >();
} else {
MutableRaw<RepeatedPtrFieldBase>(message, field)
->RemoveLast<GenericTypeHandler<Message> >();
}
break;
}
}
}
Message* GeneratedMessageReflection::ReleaseLast(
Message* message,
const FieldDescriptor* field) const {
USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
if (field->is_extension()) {
return static_cast<Message*>(
MutableExtensionSet(message)->ReleaseLast(field->number()));
} else {
if (IsMapFieldInApi(field)) {
return MutableRaw<MapFieldBase>(message, field)
->MutableRepeatedField()
->ReleaseLast<GenericTypeHandler<Message> >();
} else {
return MutableRaw<RepeatedPtrFieldBase>(message, field)
->ReleaseLast<GenericTypeHandler<Message> >();
}
}
}
void GeneratedMessageReflection::SwapElements(
Message* message,
const FieldDescriptor* field,
int index1,
int index2) const {
USAGE_CHECK_MESSAGE_TYPE(Swap);
USAGE_CHECK_REPEATED(Swap);
if (field->is_extension()) {
MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
} else {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
MutableRaw<RepeatedField<LOWERCASE> >(message, field) \
->SwapElements(index1, index2); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, int);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
MutableRaw<MapFieldBase>(message, field)
->MutableRepeatedField()
->SwapElements(index1, index2);
} else {
MutableRaw<RepeatedPtrFieldBase>(message, field)
->SwapElements(index1, index2);
}
break;
}
}
}
namespace {
// Comparison functor for sorting FieldDescriptors by field number.
struct FieldNumberSorter {
bool operator()(const FieldDescriptor* left,
const FieldDescriptor* right) const {
return left->number() < right->number();
}
};
} // namespace
void GeneratedMessageReflection::ListFields(
const Message& message,
vector<const FieldDescriptor*>* output) const {
output->clear();
// 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()) {
if (FieldSize(message, field) > 0) {
output->push_back(field);
}
} else {
if (field->containing_oneof()) {
if (HasOneofField(message, field)) {
output->push_back(field);
}
} else if (HasBit(message, field)) {
output->push_back(field);
}
}
}
if (extensions_offset_ != -1) {
GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_,
output);
}
// ListFields() must sort output by field number.
std::sort(output->begin(), output->end(), FieldNumberSorter());
}
// -------------------------------------------------------------------
#undef DEFINE_PRIMITIVE_ACCESSORS
#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \
const Message& message, const FieldDescriptor* field) const { \
USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return GetExtensionSet(message).Get##TYPENAME( \
field->number(), field->default_value_##PASSTYPE()); \
} else { \
return GetField<TYPE>(message, field); \
} \
} \
\
void GeneratedMessageReflection::Set##TYPENAME( \
Message* message, const FieldDescriptor* field, \
PASSTYPE value) const { \
USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return MutableExtensionSet(message)->Set##TYPENAME( \
field->number(), field->type(), value, field); \
} else { \
SetField<TYPE>(message, field, value); \
} \
} \
\
PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \
const Message& message, \
const FieldDescriptor* field, int index) const { \
USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
return GetExtensionSet(message).GetRepeated##TYPENAME( \
field->number(), index); \
} else { \
return GetRepeatedField<TYPE>(message, field, index); \
} \
} \
\
void GeneratedMessageReflection::SetRepeated##TYPENAME( \
Message* message, const FieldDescriptor* field, \
int index, PASSTYPE value) const { \
USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
MutableExtensionSet(message)->SetRepeated##TYPENAME( \
field->number(), index, value); \
} else { \
SetRepeatedField<TYPE>(message, field, index, value); \
} \
} \
\
void GeneratedMessageReflection::Add##TYPENAME( \
Message* message, const FieldDescriptor* field, \
PASSTYPE value) const { \
USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
MutableExtensionSet(message)->Add##TYPENAME( \
field->number(), field->type(), field->options().packed(), value, \
field); \
} else { \
AddField<TYPE>(message, field, value); \
} \
}
DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 )
DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 )
DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32)
DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64)
DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT )
DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL )
#undef DEFINE_PRIMITIVE_ACCESSORS
// -------------------------------------------------------------------
string GeneratedMessageReflection::GetString(
const Message& message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
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.";
return GetEmptyString(); // Make compiler happy.
}
}
const string& GeneratedMessageReflection::GetStringReference(
const Message& message,
const FieldDescriptor* field, string* scratch) const {
USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
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.";
return GetEmptyString(); // Make compiler happy.
}
}
void GeneratedMessageReflection::SetString(
Message* message, const FieldDescriptor* field,
const string& value) const {
USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
if (field->is_extension()) {
return MutableExtensionSet(message)->SetString(field->number(),
field->type(), value, field);
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
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;
}
}
}
}
string GeneratedMessageReflection::GetRepeatedString(
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
return GetRepeatedPtrField<string>(message, field, index);
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return GetEmptyString(); // Make compiler happy.
}
}
const string& GeneratedMessageReflection::GetRepeatedStringReference(
const Message& message, const FieldDescriptor* field,
int index, string* scratch) const {
USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
return GetRepeatedPtrField<string>(message, field, index);
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return GetEmptyString(); // Make compiler happy.
}
}
void GeneratedMessageReflection::SetRepeatedString(
Message* message, const FieldDescriptor* field,
int index, const string& value) const {
USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
if (field->is_extension()) {
MutableExtensionSet(message)->SetRepeatedString(
field->number(), index, value);
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
*MutableRepeatedField<string>(message, field, index) = value;
break;
}
}
}
void GeneratedMessageReflection::AddString(
Message* message, const FieldDescriptor* field,
const string& value) const {
USAGE_CHECK_ALL(AddString, REPEATED, STRING);
if (field->is_extension()) {
MutableExtensionSet(message)->AddString(field->number(),
field->type(), value, field);
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
*AddField<string>(message, field) = value;
break;
}
}
}
// -------------------------------------------------------------------
inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
const Message& message, const FieldDescriptor* field) const {
// Usage checked by GetEnumValue.
int value = GetEnumValue(message, field);
return field->enum_type()->FindValueByNumberCreatingIfUnknown(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);
}
return value;
}
void GeneratedMessageReflection::SetEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
// 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, field);
} else {
SetField<int>(message, field, value);
}
}
const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
const Message& message, const FieldDescriptor* field, int index) const {
// 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()) {
value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index);
} else {
value = GetRepeatedField<int>(message, field, index);
}
return value;
}
void GeneratedMessageReflection::SetRepeatedEnum(
Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) const {
// 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);
} else {
SetRepeatedField<int>(message, field, index, value);
}
}
void GeneratedMessageReflection::AddEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
// 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, field);
} else {
AddField<int>(message, field, value);
}
}
// -------------------------------------------------------------------
const Message& GeneratedMessageReflection::GetMessage(
const Message& message, const FieldDescriptor* field,
MessageFactory* factory) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
return static_cast<const Message&>(
GetExtensionSet(message).GetMessage(
field->number(), field->message_type(), factory));
} else {
const Message* result;
result = GetRaw<const Message*>(message, field);
if (result == NULL) {
result = DefaultRaw<const Message*>(field);
}
return *result;
}
}
Message* GeneratedMessageReflection::MutableMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory) const {
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
return static_cast<Message*>(
MutableExtensionSet(message)->MutableMessage(field, factory));
} else {
Message* result;
Message** result_holder = MutableRaw<Message*>(message, field);
if (field->containing_oneof()) {
if (!HasOneofField(*message, field)) {
ClearOneof(message, field->containing_oneof());
result_holder = MutableField<Message*>(message, field);
const Message* default_message = DefaultRaw<const Message*>(field);
*result_holder = default_message->New(message->GetArena());
}
} else {
SetBit(message, field);
}
if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
*result_holder = default_message->New(message->GetArena());
}
result = *result_holder;
return result;
}
}
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 {
USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
return static_cast<Message*>(
MutableExtensionSet(message)->ReleaseMessage(field, factory));
} else {
ClearBit(message, field);
if (field->containing_oneof()) {
if (HasOneofField(*message, field)) {
*MutableOneofCase(message, field->containing_oneof()) = 0;
} else {
return NULL;
}
}
Message** result = MutableRaw<Message*>(message, field);
Message* ret = *result;
*result = NULL;
return ret;
}
}
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);
if (field->is_extension()) {
return static_cast<const Message&>(
GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
} else {
if (IsMapFieldInApi(field)) {
return GetRaw<MapFieldBase>(message, field)
.GetRepeatedField()
.Get<GenericTypeHandler<Message> >(index);
} else {
return GetRaw<RepeatedPtrFieldBase>(message, field)
.Get<GenericTypeHandler<Message> >(index);
}
}
}
Message* GeneratedMessageReflection::MutableRepeatedMessage(
Message* message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
if (field->is_extension()) {
return static_cast<Message*>(
MutableExtensionSet(message)->MutableRepeatedMessage(
field->number(), index));
} else {
if (IsMapFieldInApi(field)) {
return MutableRaw<MapFieldBase>(message, field)
->MutableRepeatedField()
->Mutable<GenericTypeHandler<Message> >(index);
} else {
return MutableRaw<RepeatedPtrFieldBase>(message, field)
->Mutable<GenericTypeHandler<Message> >(index);
}
}
}
Message* GeneratedMessageReflection::AddMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory) const {
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
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 = 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;
if (repeated->size() == 0) {
prototype = factory->GetPrototype(field->message_type());
} else {
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
}
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,
int ctype, const Descriptor* desc) const {
USAGE_CHECK_REPEATED("MutableRawRepeatedField");
if (field->cpp_type() != cpptype)
ReportReflectionUsageTypeError(descriptor_,
field, "MutableRawRepeatedField", cpptype);
if (ctype >= 0)
GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
if (desc != NULL)
GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
if (field->is_extension()) {
return MutableExtensionSet(message)->MutableRawRepeatedField(
field->number(), field->type(), field->is_packed(), field);
} else {
// 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)->InsertOrLookupMapValue(
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();
}
// -----------------------------------------------------------------------------
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
const string& name) const {
if (extensions_offset_ == -1) return NULL;
const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
if (result != NULL && result->containing_type() == descriptor_) {
return result;
}
if (descriptor_->options().message_set_wire_format()) {
// MessageSet extensions may be identified by type name.
const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
if (type != NULL) {
// Look for a matching extension in the foreign type's scope.
for (int i = 0; i < type->extension_count(); i++) {
const FieldDescriptor* extension = type->extension(i);
if (extension->containing_type() == descriptor_ &&
extension->type() == FieldDescriptor::TYPE_MESSAGE &&
extension->is_optional() &&
extension->message_type() == type) {
// Found it.
return extension;
}
}
}
}
return NULL;
}
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
int number) const {
if (extensions_offset_ == -1) return NULL;
return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
}
bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
return CreateUnknownEnumValues(descriptor_->file());
}
// ===================================================================
// Some private helpers.
// These simple template accessors obtain pointers (or references) to
// the given field.
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_[index];
return *reinterpret_cast<const Type*>(ptr);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRaw(
Message* message, const FieldDescriptor* field) const {
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 = 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);
const void* ptr = reinterpret_cast<const uint8*>(&message) +
extensions_offset_;
return *reinterpret_cast<const ExtensionSet*>(ptr);
}
inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
Message* message) const {
GOOGLE_DCHECK_NE(extensions_offset_, -1);
void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_;
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.
template <typename Type>
inline const Type& GeneratedMessageReflection::GetField(
const Message& message, const FieldDescriptor* field) const {
return GetRaw<Type>(message, field);
}
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;
field->containing_oneof() ?
SetOneofCase(message, field) : SetBit(message, field);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableField(
Message* message, const FieldDescriptor* field) const {
field->containing_oneof() ?
SetOneofCase(message, field) : SetBit(message, field);
return MutableRaw<Type>(message, field);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRepeatedField(
const Message& message, const FieldDescriptor* field, int index) const {
return GetRaw<RepeatedField<Type> >(message, field).Get(index);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field, int index) const {
return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
}
template <typename Type>
inline void GeneratedMessageReflection::SetRepeatedField(
Message* message, const FieldDescriptor* field,
int index, Type value) const {
MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRepeatedField(
Message* message, const FieldDescriptor* field, int index) const {
RepeatedPtrField<Type>* repeated =
MutableRaw<RepeatedPtrField<Type> >(message, field);
return repeated->Mutable(index);
}
template <typename Type>
inline void GeneratedMessageReflection::AddField(
Message* message, const FieldDescriptor* field, const Type& value) const {
MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
}
template <typename Type>
inline Type* GeneratedMessageReflection::AddField(
Message* message, const FieldDescriptor* field) const {
RepeatedPtrField<Type>* repeated =
MutableRaw<RepeatedPtrField<Type> >(message, field);
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