diff options
Diffstat (limited to 'third_party/protobuf/3.0.0/src/google/protobuf/util/type_resolver_util.cc')
-rw-r--r-- | third_party/protobuf/3.0.0/src/google/protobuf/util/type_resolver_util.cc | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/third_party/protobuf/3.0.0/src/google/protobuf/util/type_resolver_util.cc b/third_party/protobuf/3.0.0/src/google/protobuf/util/type_resolver_util.cc new file mode 100644 index 0000000000..963939032a --- /dev/null +++ b/third_party/protobuf/3.0.0/src/google/protobuf/util/type_resolver_util.cc @@ -0,0 +1,259 @@ +// 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. + +#include <google/protobuf/util/type_resolver_util.h> + +#include <google/protobuf/type.pb.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { +using google::protobuf::BoolValue; +using google::protobuf::Enum; +using google::protobuf::EnumValue; +using google::protobuf::Field; +using google::protobuf::Option; +using google::protobuf::Type; + +using util::Status; +using util::error::INVALID_ARGUMENT; +using util::error::NOT_FOUND; + +bool SplitTypeUrl(const string& type_url, string* url_prefix, + string* message_name) { + size_t pos = type_url.find_last_of("/"); + if (pos == string::npos) { + return false; + } + *url_prefix = type_url.substr(0, pos); + *message_name = type_url.substr(pos + 1); + return true; +} + +class DescriptorPoolTypeResolver : public TypeResolver { + public: + DescriptorPoolTypeResolver(const string& url_prefix, + const DescriptorPool* pool) + : url_prefix_(url_prefix), pool_(pool) {} + + Status ResolveMessageType(const string& type_url, Type* type) { + string url_prefix, message_name; + if (!SplitTypeUrl(type_url, &url_prefix, &message_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid type URL, type URLs must be of the form '", + url_prefix_, "/<typename>', got: ", type_url)); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, + "Invalid type URL, unknown type: " + message_name); + } + ConvertDescriptor(descriptor, type); + return Status(); + } + + Status ResolveEnumType(const string& type_url, Enum* enum_type) { + string url_prefix, type_name; + if (!SplitTypeUrl(type_url, &url_prefix, &type_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid type URL, type URLs must be of the form '", + url_prefix_, "/<typename>', got: ", type_url)); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, "Invalid type URL, unknown type: " + type_name); + } + ConvertEnumDescriptor(descriptor, enum_type); + return Status(); + } + + private: + void ConvertDescriptor(const Descriptor* descriptor, Type* type) { + type->Clear(); + type->set_name(descriptor->full_name()); + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Group fields cannot be represented with Type. We discard them. + continue; + } + ConvertFieldDescriptor(descriptor->field(i), type->add_fields()); + } + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + type->add_oneofs(descriptor->oneof_decl(i)->name()); + } + type->mutable_source_context()->set_file_name(descriptor->file()->name()); + ConvertMessageOptions(descriptor->options(), type->mutable_options()); + } + + void ConvertMessageOptions(const MessageOptions& options, + RepeatedPtrField<Option>* output) { + if (options.map_entry()) { + Option* option = output->Add(); + option->set_name("map_entry"); + BoolValue value; + value.set_value(true); + option->mutable_value()->PackFrom(value); + } + + // TODO(xiaofeng): Set other "options"? + } + + void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) { + field->set_kind(static_cast<Field::Kind>(descriptor->type())); + switch (descriptor->label()) { + case FieldDescriptor::LABEL_OPTIONAL: + field->set_cardinality(Field::CARDINALITY_OPTIONAL); + break; + case FieldDescriptor::LABEL_REPEATED: + field->set_cardinality(Field::CARDINALITY_REPEATED); + break; + case FieldDescriptor::LABEL_REQUIRED: + field->set_cardinality(Field::CARDINALITY_REQUIRED); + break; + } + field->set_number(descriptor->number()); + field->set_name(descriptor->name()); + field->set_json_name(descriptor->json_name()); + if (descriptor->has_default_value()) { + field->set_default_value(DefaultValueAsString(descriptor)); + } + if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { + field->set_type_url(GetTypeUrl(descriptor->message_type())); + } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + field->set_type_url(GetTypeUrl(descriptor->enum_type())); + } + if (descriptor->containing_oneof() != NULL) { + field->set_oneof_index(descriptor->containing_oneof()->index() + 1); + } + if (descriptor->is_packed()) { + field->set_packed(true); + } + + // TODO(xiaofeng): Set other field "options"? + } + + void ConvertEnumDescriptor(const EnumDescriptor* descriptor, + Enum* enum_type) { + enum_type->Clear(); + enum_type->set_name(descriptor->full_name()); + enum_type->mutable_source_context()->set_file_name( + descriptor->file()->name()); + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value_descriptor = descriptor->value(i); + EnumValue* value = enum_type->mutable_enumvalue()->Add(); + value->set_name(value_descriptor->name()); + value->set_number(value_descriptor->number()); + + // TODO(xiaofeng): Set EnumValue options. + } + // TODO(xiaofeng): Set Enum "options". + } + + string GetTypeUrl(const Descriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + string GetTypeUrl(const EnumDescriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + string DefaultValueAsString(const FieldDescriptor* descriptor) { + switch (descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return SimpleItoa(descriptor->default_value_int32()); + break; + case FieldDescriptor::CPPTYPE_INT64: + return SimpleItoa(descriptor->default_value_int64()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + return SimpleItoa(descriptor->default_value_uint32()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(descriptor->default_value_uint64()); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + return SimpleFtoa(descriptor->default_value_float()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + return SimpleDtoa(descriptor->default_value_double()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + return descriptor->default_value_bool() ? "true" : "false"; + break; + case FieldDescriptor::CPPTYPE_STRING: + if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { + return CEscape(descriptor->default_value_string()); + } else { + return descriptor->default_value_string(); + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + return descriptor->default_value_enum()->name(); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; + break; + } + return ""; + } + + string url_prefix_; + const DescriptorPool* pool_; +}; + +} // namespace + +TypeResolver* NewTypeResolverForDescriptorPool(const string& url_prefix, + const DescriptorPool* pool) { + return new DescriptorPoolTypeResolver(url_prefix, pool); +} + +} // namespace util +} // namespace protobuf +} // namespace google |