From 40ee551715c3a784ea6132dbf604b0e665ca2def Mon Sep 17 00:00:00 2001 From: temporal Date: Thu, 10 Jul 2008 02:12:20 +0000 Subject: Initial checkin. --- src/google/protobuf/extension_set.cc | 735 +++++++++++++++++++++++++++++++++++ 1 file changed, 735 insertions(+) create mode 100644 src/google/protobuf/extension_set.cc (limited to 'src/google/protobuf/extension_set.cc') diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc new file mode 100644 index 00000000..154f06f8 --- /dev/null +++ b/src/google/protobuf/extension_set.cc @@ -0,0 +1,735 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include + +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::iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + iter->second.Free(); + } +} + +void ExtensionSet::AppendToList(vector* output) const { + for (map::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::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::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) return false; + return iter->second.GetSize(); +} + +void ExtensionSet::ClearExtension(int number) { + map::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::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::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::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(); \ + 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::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::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::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(); + 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::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::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::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(); + 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::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::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::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(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::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 +void MergeRepeatedFields(const RepeatedField& source, + RepeatedField* destination) { + destination->Reserve(destination->size() + source.size()); + for (int i = 0; i < source.size(); i++) { + destination->Add(source.Get(i)); + } +} + +void MergeRepeatedFields(const RepeatedPtrField& source, + RepeatedPtrField* 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& source, + RepeatedPtrField* 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::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( + 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::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::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::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 -- cgit v1.2.3