From 40ee551715c3a784ea6132dbf604b0e665ca2def Mon Sep 17 00:00:00 2001 From: temporal Date: Thu, 10 Jul 2008 02:12:20 +0000 Subject: Initial checkin. --- .../protobuf/generated_message_reflection.cc | 665 +++++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 src/google/protobuf/generated_message_reflection.cc (limited to 'src/google/protobuf/generated_message_reflection.cc') diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc new file mode 100644 index 00000000..ec17572b --- /dev/null +++ b/src/google/protobuf/generated_message_reflection.cc @@ -0,0 +1,665 @@ +// 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 + +namespace google { +namespace protobuf { +namespace internal { + +namespace { const string kEmptyString; } + +// =================================================================== +// 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::Message::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::Message::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::Message::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, + void* base, const void* default_base, + const int offsets[], uint32 has_bits[], + ExtensionSet* extensions) + : descriptor_ (descriptor), + base_ (base), + default_base_(default_base), + offsets_ (offsets), + has_bits_ (has_bits), + extensions_ (extensions) { +} + +GeneratedMessageReflection::~GeneratedMessageReflection() {} + +const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields() const { + return unknown_fields_; +} +UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields() { + return &unknown_fields_; +} + +// ------------------------------------------------------------------- + +bool GeneratedMessageReflection::HasField(const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(HasField); + USAGE_CHECK_SINGULAR(HasField); + + if (field->is_extension()) { + return extensions_->Has(field->number()); + } else { + return HasBit(field); + } +} + +int GeneratedMessageReflection::FieldSize(const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(HasField); + USAGE_CHECK_REPEATED(HasField); + + if (field->is_extension()) { + return extensions_->ExtensionSize(field->number()); + } else { + return GetRaw(field).GenericSize(); + } +} + +void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) { + USAGE_CHECK_MESSAGE_TYPE(ClearField); + + if (field->is_extension()) { + extensions_->ClearExtension(field->number()); + } else if (!field->is_repeated()) { + if (HasBit(field)) { + ClearBit(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(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(field) = field->default_value_enum()->number(); + break; + + case FieldDescriptor::CPPTYPE_STRING: { + const string* default_ptr = DefaultRaw(field); + string** value = MutableRaw(field); + if (*value != default_ptr) { + if (field->has_default_value()) { + (*value)->assign(field->default_value_string()); + } else { + (*value)->clear(); + } + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + (*MutableRaw(field))->Clear(); + break; + } + } + } else { + MutableRaw(field)->GenericClear(); + } +} + +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( + vector* output) const { + output->clear(); + + // Optimization: The default instance never has any fields set. + if (base_ == default_base_) return; + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_repeated()) { + if (GetRaw(field).GenericSize() > 0) { + output->push_back(field); + } + } else { + if (HasBit(field)) { + output->push_back(field); + } + } + } + + if (extensions_ != NULL) { + extensions_->AppendToList(output); + } + + // ListFields() must sort output by field number. + sort(output->begin(), output->end(), FieldNumberSorter()); +} + +// ------------------------------------------------------------------- + +#undef DEFINE_PRIMITIVE_ACCESSORS +#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ + PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \ + const FieldDescriptor* field) const { \ + USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return extensions_->Get##TYPENAME(field->number()); \ + } else { \ + return GetField(field); \ + } \ + } \ + \ + void GeneratedMessageReflection::Set##TYPENAME( \ + const FieldDescriptor* field, PASSTYPE value) { \ + USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return extensions_->Set##TYPENAME(field->number(), value); \ + } else { \ + SetField(field, value); \ + } \ + } \ + \ + PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \ + const FieldDescriptor* field, int index) const { \ + USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + return extensions_->GetRepeated##TYPENAME(field->number(), index); \ + } else { \ + return GetRepeatedField(field, index); \ + } \ + } \ + \ + void GeneratedMessageReflection::SetRepeated##TYPENAME( \ + const FieldDescriptor* field, int index, PASSTYPE value) { \ + USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + extensions_->SetRepeated##TYPENAME(field->number(), index, value); \ + } else { \ + SetRepeatedField(field, index, value); \ + } \ + } \ + \ + void GeneratedMessageReflection::Add##TYPENAME( \ + const FieldDescriptor* field, PASSTYPE value) { \ + USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + extensions_->Add##TYPENAME(field->number(), value); \ + } else { \ + AddField(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 FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetString, SINGULAR, STRING); + if (field->is_extension()) { + return extensions_->GetString(field->number()); + } else { + return *GetField(field); + } +} + +const string& GeneratedMessageReflection::GetStringReference( + const FieldDescriptor* field, string* scratch) const { + USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); + if (field->is_extension()) { + return extensions_->GetString(field->number()); + } else { + return *GetField(field); + } +} + + +void GeneratedMessageReflection::SetString( + const FieldDescriptor* field, const string& value) { + USAGE_CHECK_ALL(SetString, SINGULAR, STRING); + if (field->is_extension()) { + return extensions_->SetString(field->number(), value); + } else { + string** ptr = MutableField(field); + if (*ptr == DefaultRaw(field)) { + *ptr = new string(value); + } else { + (*ptr)->assign(value); + } + } +} + + +string GeneratedMessageReflection::GetRepeatedString( + const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + return extensions_->GetRepeatedString(field->number(), index); + } else { + return GetRepeatedField(field, index); + } +} + +const string& GeneratedMessageReflection::GetRepeatedStringReference( + const FieldDescriptor* field, int index, string* scratch) const { + USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); + if (field->is_extension()) { + return extensions_->GetRepeatedString(field->number(), index); + } else { + return GetRepeatedField(field, index); + } +} + + +void GeneratedMessageReflection::SetRepeatedString( + const FieldDescriptor* field, int index, const string& value) { + USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + extensions_->SetRepeatedString(field->number(), index, value); + } else { + SetRepeatedField(field, index, value); + } +} + + +void GeneratedMessageReflection::AddString( + const FieldDescriptor* field, const string& value) { + USAGE_CHECK_ALL(AddString, REPEATED, STRING); + if (field->is_extension()) { + extensions_->AddString(field->number(), value); + } else { + AddField(field, value); + } +} + + +// ------------------------------------------------------------------- + +const EnumValueDescriptor* GeneratedMessageReflection::GetEnum( + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM); + + int value; + if (field->is_extension()) { + value = extensions_->GetEnum(field->number()); + } else { + value = GetField(field); + } + const EnumValueDescriptor* result = + field->enum_type()->FindValueByNumber(value); + GOOGLE_CHECK(result != NULL); + return result; +} + +void GeneratedMessageReflection::SetEnum(const FieldDescriptor* field, + const EnumValueDescriptor* value) { + USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM); + USAGE_CHECK_ENUM_VALUE(SetEnum); + + if (field->is_extension()) { + extensions_->SetEnum(field->number(), value->number()); + } else { + SetField(field, value->number()); + } +} + +const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum( + const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM); + + int value; + if (field->is_extension()) { + value = extensions_->GetRepeatedEnum(field->number(), index); + } else { + value = GetRepeatedField(field, index); + } + const EnumValueDescriptor* result = + field->enum_type()->FindValueByNumber(value); + GOOGLE_CHECK(result != NULL); + return result; +} + +void GeneratedMessageReflection::SetRepeatedEnum( + const FieldDescriptor* field, int index, + const EnumValueDescriptor* value) { + USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM); + USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum); + + if (field->is_extension()) { + extensions_->SetRepeatedEnum(field->number(), index, value->number()); + } else { + SetRepeatedField(field, index, value->number()); + } +} + +void GeneratedMessageReflection::AddEnum(const FieldDescriptor* field, + const EnumValueDescriptor* value) { + USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM); + USAGE_CHECK_ENUM_VALUE(AddEnum); + + if (field->is_extension()) { + extensions_->AddEnum(field->number(), value->number()); + } else { + AddField(field, value->number()); + } +} + +// ------------------------------------------------------------------- + +const Message& GeneratedMessageReflection::GetMessage( + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); + + if (field->is_extension()) { + return extensions_->GetMessage(field->number()); + } else { + const Message* result = GetRaw(field); + if (result == NULL) { + result = DefaultRaw(field); + } + return *result; + } +} + +Message* GeneratedMessageReflection::MutableMessage( + const FieldDescriptor* field) { + USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + + if (field->is_extension()) { + return extensions_->MutableMessage(field->number()); + } else { + Message** result = MutableField(field); + if (*result == NULL) { + const Message* default_message = DefaultRaw(field); + *result = default_message->New(); + (*result)->CopyFrom(*default_message); + } + return *result; + } +} + +const Message& GeneratedMessageReflection::GetRepeatedMessage( + const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + return extensions_->GetRepeatedMessage(field->number(), index); + } else { + return GetRepeatedField(field, index); + } +} + +Message* GeneratedMessageReflection::MutableRepeatedMessage( + const FieldDescriptor* field, int index) { + USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + return extensions_->MutableRepeatedMessage(field->number(), index); + } else { + return MutableRepeatedField(field, index); + } +} + +Message* GeneratedMessageReflection::AddMessage(const FieldDescriptor* field) { + USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + return extensions_->AddMessage(field->number()); + } else { + return AddField(field); + } +} + +// ------------------------------------------------------------------- + +const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( + const string& name) const { + if (extensions_ == NULL) return NULL; + return extensions_->FindKnownExtensionByName(name); +} + +const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( + int number) const { + if (extensions_ == NULL) return NULL; + return extensions_->FindKnownExtensionByNumber(number); +} + +// =================================================================== +// Some private helpers. + +// These simple template accessors obtain pointers (or references) to +// the given field. +template +inline const Type& GeneratedMessageReflection::GetRaw( + const FieldDescriptor* field) const { + const void* ptr = reinterpret_cast(base_) + + offsets_[field->index()]; + return *reinterpret_cast(ptr); +} + +template +inline Type* GeneratedMessageReflection::MutableRaw( + const FieldDescriptor* field) { + void* ptr = reinterpret_cast(base_) + offsets_[field->index()]; + return reinterpret_cast(ptr); +} + +template +inline const Type& GeneratedMessageReflection::DefaultRaw( + const FieldDescriptor* field) const { + const void* ptr = reinterpret_cast(default_base_) + + offsets_[field->index()]; + return *reinterpret_cast(ptr); +} + +// Simple accessors for manipulating has_bits_. +inline bool GeneratedMessageReflection::HasBit( + const FieldDescriptor* field) const { + return has_bits_[field->index() / 32] & (1 << (field->index() % 32)); +} + +inline void GeneratedMessageReflection::SetBit( + const FieldDescriptor* field) { + has_bits_[field->index() / 32] |= (1 << (field->index() % 32)); +} + +inline void GeneratedMessageReflection::ClearBit( + const FieldDescriptor* field) { + has_bits_[field->index() / 32] &= ~(1 << (field->index() % 32)); +} + +// 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 +inline const Type& GeneratedMessageReflection::GetField( + const FieldDescriptor* field) const { + return GetRaw(field); +} + +template +inline void GeneratedMessageReflection::SetField( + const FieldDescriptor* field, const Type& value) { + *MutableRaw(field) = value; + SetBit(field); +} + +template +inline Type* GeneratedMessageReflection::MutableField( + const FieldDescriptor* field) { + SetBit(field); + return MutableRaw(field); +} + +template +inline const Type& GeneratedMessageReflection::GetRepeatedField( + const FieldDescriptor* field, int index) const { + return *reinterpret_cast( + GetRaw(field).GenericGet(index)); +} + +template +inline void GeneratedMessageReflection::SetRepeatedField( + const FieldDescriptor* field, int index, const Type& value) { + GenericRepeatedField* repeated = MutableRaw(field); + *reinterpret_cast(repeated->GenericMutable(index)) = value; +} + +template +inline Type* GeneratedMessageReflection::MutableRepeatedField( + const FieldDescriptor* field, int index) { + GenericRepeatedField* repeated = MutableRaw(field); + return reinterpret_cast(repeated->GenericMutable(index)); +} + +template +inline void GeneratedMessageReflection::AddField( + const FieldDescriptor* field, const Type& value) { + GenericRepeatedField* repeated = MutableRaw(field); + *reinterpret_cast(repeated->GenericAdd()) = value; +} + +template +inline Type* GeneratedMessageReflection::AddField( + const FieldDescriptor* field) { + GenericRepeatedField* repeated = MutableRaw(field); + return reinterpret_cast(repeated->GenericAdd()); +} + +} // namespace internal +} // namespace protobuf +} // namespace google -- cgit v1.2.3