blob: 154f06f81d087982456fce523456ea36952465c5 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/repeated_field.h>
namespace google {
namespace protobuf {
namespace internal {
// -------------------------------------------------------------------
// Lookup functions
const FieldDescriptor*
ExtensionSet::FindKnownExtensionByName(const string& name) const {
const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
if (result != NULL && result->containing_type() == extendee_) {
return result;
}
if (extendee_->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() == extendee_ &&
extension->type() == FieldDescriptor::TYPE_MESSAGE &&
extension->is_optional() &&
extension->message_type() == type) {
// Found it.
return extension;
}
}
}
}
return NULL;
}
const FieldDescriptor*
ExtensionSet::FindKnownExtensionByNumber(int number) const {
return descriptor_pool_->FindExtensionByNumber(extendee_, number);
}
const FieldDescriptor*
ExtensionSet::FindKnownExtensionOrDie(int number) const {
const FieldDescriptor* descriptor = FindKnownExtensionByNumber(number);
if (descriptor == NULL) {
// This extension doesn't exist, so we have to crash. However, let's
// try to provide an informative error message.
if (descriptor_pool_ == DescriptorPool::generated_pool() &&
message_factory_ == MessageFactory::generated_factory()) {
// This is probably the ExtensionSet for a generated class.
GOOGLE_LOG(FATAL) << ": No extension is registered for \""
<< extendee_->full_name() << "\" with number "
<< number << ". Perhaps you were trying to access it via "
"the Reflection interface, but you provided a "
"FieldDescriptor which did not come from a linked-in "
"message type? This is not permitted; linkin-in message "
"types cannot use non-linked-in extensions. Try "
"converting to a DynamicMessage first.";
} else {
// This is probably a DynamicMessage.
GOOGLE_LOG(FATAL) << ": No extension is registered for \""
<< extendee_->full_name() << "\" with number "
<< number << ". If you were using a DynamicMessage, "
"remember that you are only allowed to access extensions "
"which are defined in the DescriptorPool which you passed "
"to DynamicMessageFactory's constructor.";
}
}
return descriptor;
}
const Message*
ExtensionSet::GetPrototype(const Descriptor* message_type) const {
return message_factory_->GetPrototype(message_type);
}
// ===================================================================
// Constructors and basic methods.
ExtensionSet::ExtensionSet(const Descriptor* extendee,
const DescriptorPool* pool,
MessageFactory* factory)
: extendee_(extendee),
descriptor_pool_(pool),
message_factory_(factory) {
}
ExtensionSet::~ExtensionSet() {
for (map<int, Extension>::iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
iter->second.Free();
}
}
void ExtensionSet::AppendToList(vector<const FieldDescriptor*>* output) const {
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
bool has = false;
if (iter->second.descriptor->is_repeated()) {
has = iter->second.GetSize() > 0;
} else {
has = !iter->second.is_cleared;
}
if (has) {
output->push_back(iter->second.descriptor);
}
}
}
bool ExtensionSet::Has(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) return false;
GOOGLE_DCHECK(!iter->second.descriptor->is_repeated());
return !iter->second.is_cleared;
}
int ExtensionSet::ExtensionSize(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) return false;
return iter->second.GetSize();
}
void ExtensionSet::ClearExtension(int number) {
map<int, Extension>::iterator iter = extensions_.find(number);
if (iter == extensions_.end()) return;
iter->second.Clear();
}
// ===================================================================
// Field accessors
#define GOOGLE_DCHECK_TYPE(DESCRIPTOR, LABEL, CPPTYPE) \
GOOGLE_DCHECK_EQ(DESCRIPTOR->label(), FieldDescriptor::LABEL_##LABEL); \
GOOGLE_DCHECK_EQ(DESCRIPTOR->cpp_type(), FieldDescriptor::CPPTYPE_##CPPTYPE)
// -------------------------------------------------------------------
// Primitives
#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \
\
LOWERCASE ExtensionSet::Get##CAMELCASE(int number) const { \
map<int, Extension>::const_iterator iter = extensions_.find(number); \
if (iter == extensions_.end()) { \
/* Not present. Return the default value. */ \
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, UPPERCASE); \
return descriptor->default_value_##LOWERCASE(); \
} else { \
GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, UPPERCASE); \
return iter->second.LOWERCASE##_value; \
} \
} \
\
void ExtensionSet::Set##CAMELCASE(int number, LOWERCASE value) { \
Extension* extension = &extensions_[number]; \
if (extension->descriptor == NULL) { \
/* Not previoulsy present. Initialize it. */ \
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, UPPERCASE); \
extension->descriptor = descriptor; \
extension->LOWERCASE##_value = descriptor->default_value_##LOWERCASE(); \
} else { \
GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, UPPERCASE); \
extension->is_cleared = false; \
} \
extension->LOWERCASE##_value = value; \
} \
\
LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) const { \
map<int, Extension>::const_iterator iter = extensions_.find(number); \
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, UPPERCASE); \
return iter->second.repeated_##LOWERCASE##_value->Get(index); \
} \
\
void ExtensionSet::SetRepeated##CAMELCASE( \
int number, int index, LOWERCASE value) { \
map<int, Extension>::iterator iter = extensions_.find(number); \
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, UPPERCASE); \
iter->second.repeated_##LOWERCASE##_value->Set(index, value); \
} \
\
void ExtensionSet::Add##CAMELCASE(int number, LOWERCASE value) { \
Extension* extension = &extensions_[number]; \
if (extension->descriptor == NULL) { \
/* Not previoulsy present. Initialize it. */ \
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
GOOGLE_DCHECK_TYPE(descriptor, REPEATED, UPPERCASE); \
extension->repeated_##LOWERCASE##_value = new RepeatedField<LOWERCASE>(); \
extension->descriptor = descriptor; \
} else { \
GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, UPPERCASE); \
} \
extension->repeated_##LOWERCASE##_value->Add(value); \
}
PRIMITIVE_ACCESSORS( INT32, int32, Int32)
PRIMITIVE_ACCESSORS( INT64, int64, Int64)
PRIMITIVE_ACCESSORS(UINT32, uint32, UInt32)
PRIMITIVE_ACCESSORS(UINT64, uint64, UInt64)
PRIMITIVE_ACCESSORS( FLOAT, float, Float)
PRIMITIVE_ACCESSORS(DOUBLE, double, Double)
PRIMITIVE_ACCESSORS( BOOL, bool, Bool)
#undef PRIMITIVE_ACCESSORS
// -------------------------------------------------------------------
// Enums
int ExtensionSet::GetEnum(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) {
// Not present. Return the default value.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, ENUM);
return descriptor->default_value_enum()->number();
} else {
GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, ENUM);
return iter->second.enum_value;
}
}
void ExtensionSet::SetEnum(int number, int value) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, ENUM);
extension->descriptor = descriptor;
extension->enum_value = descriptor->default_value_enum()->number();
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, ENUM);
extension->is_cleared = false;
}
GOOGLE_DCHECK(extension->descriptor->enum_type()->FindValueByNumber(value) != NULL);
extension->enum_value = value;
}
int ExtensionSet::GetRepeatedEnum(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, ENUM);
return iter->second.repeated_enum_value->Get(index);
}
void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, ENUM);
GOOGLE_DCHECK(iter->second.descriptor->enum_type()
->FindValueByNumber(value) != NULL);
iter->second.repeated_enum_value->Set(index, value);
}
void ExtensionSet::AddEnum(int number, int value) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, REPEATED, ENUM);
extension->repeated_enum_value = new RepeatedField<int>();
extension->descriptor = descriptor;
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, ENUM);
}
GOOGLE_DCHECK(extension->descriptor->enum_type()->FindValueByNumber(value) != NULL);
extension->repeated_enum_value->Add(value);
}
// -------------------------------------------------------------------
// Strings
const string& ExtensionSet::GetString(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) {
// Not present. Return the default value.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, STRING);
return descriptor->default_value_string();
} else {
GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, STRING);
return *iter->second.string_value;
}
}
string* ExtensionSet::MutableString(int number) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, STRING);
extension->descriptor = descriptor;
extension->string_value = new string;
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, STRING);
extension->is_cleared = false;
}
return extension->string_value;
}
const string& ExtensionSet::GetRepeatedString(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, STRING);
return iter->second.repeated_string_value->Get(index);
}
string* ExtensionSet::MutableRepeatedString(int number, int index) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, STRING);
return iter->second.repeated_string_value->Mutable(index);
}
string* ExtensionSet::AddString(int number) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, REPEATED, STRING);
extension->repeated_string_value = new RepeatedPtrField<string>();
extension->descriptor = descriptor;
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, STRING);
}
return extension->repeated_string_value->Add();
}
// -------------------------------------------------------------------
// Messages
const Message& ExtensionSet::GetMessage(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) {
// Not present. Return the default value.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, MESSAGE);
return *GetPrototype(descriptor->message_type());
} else {
GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, MESSAGE);
return *iter->second.message_value;
}
}
Message* ExtensionSet::MutableMessage(int number) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, MESSAGE);
extension->descriptor = descriptor;
extension->message_value = GetPrototype(descriptor->message_type())->New();
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, MESSAGE);
extension->is_cleared = false;
}
return extension->message_value;
}
const Message& ExtensionSet::GetRepeatedMessage(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, MESSAGE);
return iter->second.repeated_message_value->Get(index);
}
Message* ExtensionSet::MutableRepeatedMessage(int number, int index) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, MESSAGE);
return iter->second.repeated_message_value->Mutable(index);
}
Message* ExtensionSet::AddMessage(int number) {
Extension* extension = &extensions_[number];
if (extension->descriptor == NULL) {
// Not previoulsy present. Initialize it.
const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
GOOGLE_DCHECK_TYPE(descriptor, REPEATED, MESSAGE);
extension->repeated_message_value =
new RepeatedPtrField<Message>(GetPrototype(descriptor->message_type()));
extension->descriptor = descriptor;
} else {
GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, MESSAGE);
}
return extension->repeated_message_value->Add();
}
#undef GOOGLE_DCHECK_TYPE
// ===================================================================
void ExtensionSet::Clear() {
for (map<int, Extension>::iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
iter->second.Clear();
}
}
namespace {
// A helper function for merging RepeatedFields...
// TODO(kenton): Implement this as a method of RepeatedField? Make generated
// MergeFrom methods use it?
template <typename Type>
void MergeRepeatedFields(const RepeatedField<Type>& source,
RepeatedField<Type>* destination) {
destination->Reserve(destination->size() + source.size());
for (int i = 0; i < source.size(); i++) {
destination->Add(source.Get(i));
}
}
void MergeRepeatedFields(const RepeatedPtrField<string>& source,
RepeatedPtrField<string>* destination) {
destination->Reserve(destination->size() + source.size());
for (int i = 0; i < source.size(); i++) {
destination->Add()->assign(source.Get(i));
}
}
void MergeRepeatedFields(const RepeatedPtrField<Message>& source,
RepeatedPtrField<Message>* destination) {
destination->Reserve(destination->size() + source.size());
for (int i = 0; i < source.size(); i++) {
destination->Add()->MergeFrom(source.Get(i));
}
}
} // namespace
void ExtensionSet::MergeFrom(const ExtensionSet& other) {
GOOGLE_DCHECK_EQ(extendee_, other.extendee_);
for (map<int, Extension>::const_iterator iter = other.extensions_.begin();
iter != other.extensions_.end(); ++iter) {
const FieldDescriptor* field = iter->second.descriptor;
if (field->is_repeated()) {
const Extension& other_extension = iter->second;
Extension* extension = &extensions_[iter->first];
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
if (extension->descriptor == NULL) { \
extension->descriptor = field; \
extension->repeated_##LOWERCASE##_value = \
new REPEATED_TYPE; \
} \
MergeRepeatedFields( \
*other_extension.repeated_##LOWERCASE##_value, \
extension->repeated_##LOWERCASE##_value); \
break;
HANDLE_TYPE( INT32, int32, RepeatedField < int32>);
HANDLE_TYPE( INT64, int64, RepeatedField < int64>);
HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>);
HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>);
HANDLE_TYPE( FLOAT, float, RepeatedField < float>);
HANDLE_TYPE( DOUBLE, double, RepeatedField < double>);
HANDLE_TYPE( BOOL, bool, RepeatedField < bool>);
HANDLE_TYPE( ENUM, enum, RepeatedField < int>);
HANDLE_TYPE( STRING, string, RepeatedPtrField< string>);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_MESSAGE:
if (extension->descriptor == NULL) {
extension->descriptor = field;
extension->repeated_message_value = new RepeatedPtrField<Message>(
other_extension.repeated_message_value->prototype());
}
MergeRepeatedFields(
*other_extension.repeated_message_value,
extension->repeated_message_value);
break;
}
} else {
if (!iter->second.is_cleared) {
switch (field->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
Set##CAMELCASE(iter->first, iter->second.LOWERCASE##_value); \
break;
HANDLE_TYPE( INT32, int32, Int32);
HANDLE_TYPE( INT64, int64, Int64);
HANDLE_TYPE(UINT32, uint32, UInt32);
HANDLE_TYPE(UINT64, uint64, UInt64);
HANDLE_TYPE( FLOAT, float, Float);
HANDLE_TYPE(DOUBLE, double, Double);
HANDLE_TYPE( BOOL, bool, Bool);
HANDLE_TYPE( ENUM, enum, Enum);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
SetString(iter->first, *iter->second.string_value);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
MutableMessage(iter->first)->MergeFrom(*iter->second.message_value);
break;
}
}
}
}
}
bool ExtensionSet::IsInitialized() const {
// Extensions are never requried. However, we need to check that all
// embedded messages are initialized.
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
const Extension& extension = iter->second;
if (extension.descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (extension.descriptor->is_repeated()) {
for (int i = 0; i < extension.repeated_message_value->size(); i++) {
if (!extension.repeated_message_value->Get(i).IsInitialized()) {
return false;
}
}
} else {
if (!extension.is_cleared) {
if (!extension.message_value->IsInitialized()) return false;
}
}
}
}
return true;
}
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
Message::Reflection* reflection) {
const FieldDescriptor* field =
FindKnownExtensionByNumber(WireFormat::GetTagFieldNumber(tag));
return WireFormat::ParseAndMergeField(tag, field, reflection, input);
}
bool ExtensionSet::SerializeWithCachedSizes(
int start_field_number, int end_field_number,
const Message::Reflection* reflection,
io::CodedOutputStream* output) const {
map<int, Extension>::const_iterator iter;
for (iter = extensions_.lower_bound(start_field_number);
iter != extensions_.end() && iter->first < end_field_number;
++iter) {
if (!iter->second.SerializeFieldWithCachedSizes(reflection, output)) {
return false;
}
}
return true;
}
int ExtensionSet::ByteSize(const Message::Reflection* reflection) const {
int total_size = 0;
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
total_size += iter->second.ByteSize(reflection);
}
return total_size;
}
// ===================================================================
// Methods of ExtensionSet::Extension
void ExtensionSet::Extension::Clear() {
if (descriptor->is_repeated()) {
switch (descriptor->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
repeated_##LOWERCASE##_value->Clear(); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE( UINT32, uint32);
HANDLE_TYPE( UINT64, uint64);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( DOUBLE, double);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, enum);
HANDLE_TYPE( STRING, string);
HANDLE_TYPE(MESSAGE, message);
#undef HANDLE_TYPE
}
} else {
if (!is_cleared) {
switch (descriptor->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
LOWERCASE##_value = descriptor->default_value_##LOWERCASE(); \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE(UINT32, uint32);
HANDLE_TYPE(UINT64, uint64);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE(DOUBLE, double);
HANDLE_TYPE( BOOL, bool);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_ENUM:
enum_value = descriptor->default_value_enum()->number();
break;
case FieldDescriptor::CPPTYPE_STRING:
if (descriptor->has_default_value()) {
string_value->assign(descriptor->default_value_string());
} else {
string_value->clear();
}
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
message_value->Clear();
break;
}
is_cleared = true;
}
}
}
bool ExtensionSet::Extension::SerializeFieldWithCachedSizes(
const Message::Reflection* reflection,
io::CodedOutputStream* output) const {
if (descriptor->is_repeated() || !is_cleared) {
return WireFormat::SerializeFieldWithCachedSizes(
descriptor, reflection, output);
} else {
return true;
}
}
int64 ExtensionSet::Extension::ByteSize(
const Message::Reflection* reflection) const {
if (descriptor->is_repeated() || !is_cleared) {
return WireFormat::FieldByteSize(descriptor, reflection);
} else {
// Cleared, non-repeated field.
return 0;
}
}
int ExtensionSet::Extension::GetSize() const {
GOOGLE_DCHECK(descriptor->is_repeated());
switch (descriptor->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
return repeated_##LOWERCASE##_value->size()
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE( UINT32, uint32);
HANDLE_TYPE( UINT64, uint64);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( DOUBLE, double);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, enum);
HANDLE_TYPE( STRING, string);
HANDLE_TYPE(MESSAGE, message);
#undef HANDLE_TYPE
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return 0;
}
void ExtensionSet::Extension::Free() {
if (descriptor->is_repeated()) {
switch (descriptor->cpp_type()) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
delete repeated_##LOWERCASE##_value; \
break
HANDLE_TYPE( INT32, int32);
HANDLE_TYPE( INT64, int64);
HANDLE_TYPE( UINT32, uint32);
HANDLE_TYPE( UINT64, uint64);
HANDLE_TYPE( FLOAT, float);
HANDLE_TYPE( DOUBLE, double);
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, enum);
HANDLE_TYPE( STRING, string);
HANDLE_TYPE(MESSAGE, message);
#undef HANDLE_TYPE
}
} else {
switch (descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_STRING:
delete string_value;
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
delete message_value;
break;
default:
break;
}
}
}
} // namespace internal
} // namespace protobuf
} // namespace google