aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/descriptor_database.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/descriptor_database.cc')
-rw-r--r--src/google/protobuf/descriptor_database.cc291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
new file mode 100644
index 00000000..944280c0
--- /dev/null
+++ b/src/google/protobuf/descriptor_database.cc
@@ -0,0 +1,291 @@
+// 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/descriptor_database.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/map-util.h>
+
+namespace google {
+namespace protobuf {
+
+DescriptorDatabase::~DescriptorDatabase() {}
+
+// ===================================================================
+
+SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
+SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
+ STLDeleteElements(&files_to_delete_);
+}
+
+void SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
+ FileDescriptorProto* new_file = new FileDescriptorProto;
+ new_file->CopyFrom(file);
+ AddAndOwn(new_file);
+}
+
+void SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
+ files_to_delete_.push_back(file);
+ InsertOrUpdate(&files_by_name_, file->name(), file);
+
+ string path = file->package();
+ if (!path.empty()) path += '.';
+
+ for (int i = 0; i < file->message_type_size(); i++) {
+ AddMessage(path, file->message_type(i), file);
+ }
+ for (int i = 0; i < file->enum_type_size(); i++) {
+ AddEnum(path, file->enum_type(i), file);
+ }
+ for (int i = 0; i < file->extension_size(); i++) {
+ AddField(path, file->extension(i), file);
+ }
+ for (int i = 0; i < file->service_size(); i++) {
+ AddService(path, file->service(i), file);
+ }
+}
+
+void SimpleDescriptorDatabase::AddMessage(
+ const string& path,
+ const DescriptorProto& message_type,
+ const FileDescriptorProto* file) {
+ string full_name = path + message_type.name();
+ InsertOrUpdate(&files_by_symbol_, full_name, file);
+
+ string sub_path = full_name + '.';
+ for (int i = 0; i < message_type.nested_type_size(); i++) {
+ AddMessage(sub_path, message_type.nested_type(i), file);
+ }
+ for (int i = 0; i < message_type.enum_type_size(); i++) {
+ AddEnum(sub_path, message_type.enum_type(i), file);
+ }
+ for (int i = 0; i < message_type.field_size(); i++) {
+ AddField(sub_path, message_type.field(i), file);
+ }
+ for (int i = 0; i < message_type.extension_size(); i++) {
+ AddField(sub_path, message_type.extension(i), file);
+ }
+}
+
+void SimpleDescriptorDatabase::AddField(
+ const string& path,
+ const FieldDescriptorProto& field,
+ const FileDescriptorProto* file) {
+ string full_name = path + field.name();
+ InsertOrUpdate(&files_by_symbol_, full_name, file);
+
+ if (field.has_extendee()) {
+ // This field is an extension.
+ if (!field.extendee().empty() && field.extendee()[0] == '.') {
+ // The extension is fully-qualified. We can use it as a lookup key in
+ // the files_by_symbol_ table.
+ InsertOrUpdate(&files_by_extension_,
+ make_pair(field.extendee().substr(1), field.number()),
+ file);
+ } else {
+ // Not fully-qualified. We can't really do anything here, unfortunately.
+ }
+ }
+}
+
+void SimpleDescriptorDatabase::AddEnum(
+ const string& path,
+ const EnumDescriptorProto& enum_type,
+ const FileDescriptorProto* file) {
+ string full_name = path + enum_type.name();
+ InsertOrUpdate(&files_by_symbol_, full_name, file);
+
+ string sub_path = full_name + '.';
+ for (int i = 0; i < enum_type.value_size(); i++) {
+ InsertOrUpdate(&files_by_symbol_,
+ sub_path + enum_type.value(i).name(),
+ file);
+ }
+}
+
+void SimpleDescriptorDatabase::AddService(
+ const string& path,
+ const ServiceDescriptorProto& service,
+ const FileDescriptorProto* file) {
+ string full_name = path + service.name();
+ InsertOrUpdate(&files_by_symbol_, full_name, file);
+
+ string sub_path = full_name + '.';
+ for (int i = 0; i < service.method_size(); i++) {
+ InsertOrUpdate(&files_by_symbol_,
+ sub_path + service.method(i).name(),
+ file);
+ }
+}
+
+bool SimpleDescriptorDatabase::FindFileByName(
+ const string& filename,
+ FileDescriptorProto* output) {
+ const FileDescriptorProto* result = FindPtrOrNull(files_by_name_, filename);
+ if (result == NULL) {
+ return false;
+ } else {
+ output->CopyFrom(*result);
+ return true;
+ }
+}
+
+bool SimpleDescriptorDatabase::FindFileContainingSymbol(
+ const string& symbol_name,
+ FileDescriptorProto* output) {
+ const FileDescriptorProto* result =
+ FindPtrOrNull(files_by_symbol_, symbol_name);
+ if (result == NULL) {
+ return false;
+ } else {
+ output->CopyFrom(*result);
+ return true;
+ }
+}
+
+bool SimpleDescriptorDatabase::FindFileContainingExtension(
+ const string& containing_type,
+ int field_number,
+ FileDescriptorProto* output) {
+ const FileDescriptorProto* result =
+ FindPtrOrNull(files_by_extension_,
+ make_pair(containing_type, field_number));
+ if (result == NULL) {
+ return false;
+ } else {
+ output->CopyFrom(*result);
+ return true;
+ }
+}
+
+// ===================================================================
+
+DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
+ : pool_(pool) {}
+DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
+
+bool DescriptorPoolDatabase::FindFileByName(
+ const string& filename,
+ FileDescriptorProto* output) {
+ const FileDescriptor* file = pool_.FindFileByName(filename);
+ if (file == NULL) return false;
+ output->Clear();
+ file->CopyTo(output);
+ return true;
+}
+
+bool DescriptorPoolDatabase::FindFileContainingSymbol(
+ const string& symbol_name,
+ FileDescriptorProto* output) {
+ const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
+ if (file == NULL) return false;
+ output->Clear();
+ file->CopyTo(output);
+ return true;
+}
+
+bool DescriptorPoolDatabase::FindFileContainingExtension(
+ const string& containing_type,
+ int field_number,
+ FileDescriptorProto* output) {
+ const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
+ if (extendee == NULL) return false;
+
+ const FieldDescriptor* extension =
+ pool_.FindExtensionByNumber(extendee, field_number);
+ if (extension == NULL) return false;
+
+ output->Clear();
+ extension->file()->CopyTo(output);
+ return true;
+}
+
+// ===================================================================
+
+MergedDescriptorDatabase::MergedDescriptorDatabase(
+ DescriptorDatabase* source1,
+ DescriptorDatabase* source2) {
+ sources_.push_back(source1);
+ sources_.push_back(source2);
+}
+MergedDescriptorDatabase::MergedDescriptorDatabase(
+ const vector<DescriptorDatabase*>& sources)
+ : sources_(sources) {}
+MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
+
+bool MergedDescriptorDatabase::FindFileByName(
+ const string& filename,
+ FileDescriptorProto* output) {
+ for (int i = 0; i < sources_.size(); i++) {
+ if (sources_[i]->FindFileByName(filename, output)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MergedDescriptorDatabase::FindFileContainingSymbol(
+ const string& symbol_name,
+ FileDescriptorProto* output) {
+ for (int i = 0; i < sources_.size(); i++) {
+ if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
+ // The symbol was found in source i. However, if one of the previous
+ // sources defines a file with the same name (which presumably doesn't
+ // contain the symbol, since it wasn't found in that source), then we
+ // must hide it from the caller.
+ FileDescriptorProto temp;
+ for (int j = 0; j < i; j++) {
+ if (sources_[j]->FindFileByName(output->name(), &temp)) {
+ // Found conflicting file in a previous source.
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MergedDescriptorDatabase::FindFileContainingExtension(
+ const string& containing_type,
+ int field_number,
+ FileDescriptorProto* output) {
+ for (int i = 0; i < sources_.size(); i++) {
+ if (sources_[i]->FindFileContainingExtension(
+ containing_type, field_number, output)) {
+ // The symbol was found in source i. However, if one of the previous
+ // sources defines a file with the same name (which presumably doesn't
+ // contain the symbol, since it wasn't found in that source), then we
+ // must hide it from the caller.
+ FileDescriptorProto temp;
+ for (int j = 0; j < i; j++) {
+ if (sources_[j]->FindFileByName(output->name(), &temp)) {
+ // Found conflicting file in a previous source.
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace protobuf
+} // namespace google