1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/descriptor_database.h>
36
37 #include <set>
38
39 #include <google/protobuf/descriptor.pb.h>
40 #include <google/protobuf/stubs/strutil.h>
41 #include <google/protobuf/stubs/map_util.h>
42 #include <google/protobuf/stubs/stl_util.h>
43
44 namespace google {
45 namespace protobuf {
46
47 namespace {
RecordMessageNames(const DescriptorProto & desc_proto,const std::string & prefix,std::set<std::string> * output)48 void RecordMessageNames(const DescriptorProto& desc_proto,
49 const std::string& prefix,
50 std::set<std::string>* output) {
51 GOOGLE_CHECK(desc_proto.has_name());
52 std::string full_name = prefix.empty()
53 ? desc_proto.name()
54 : StrCat(prefix, ".", desc_proto.name());
55 output->insert(full_name);
56
57 for (const auto& d : desc_proto.nested_type()) {
58 RecordMessageNames(d, full_name, output);
59 }
60 }
61
RecordMessageNames(const FileDescriptorProto & file_proto,std::set<std::string> * output)62 void RecordMessageNames(const FileDescriptorProto& file_proto,
63 std::set<std::string>* output) {
64 for (const auto& d : file_proto.message_type()) {
65 RecordMessageNames(d, file_proto.package(), output);
66 }
67 }
68
69 template <typename Fn>
ForAllFileProtos(DescriptorDatabase * db,Fn callback,std::vector<std::string> * output)70 bool ForAllFileProtos(DescriptorDatabase* db, Fn callback,
71 std::vector<std::string>* output) {
72 std::vector<std::string> file_names;
73 if (!db->FindAllFileNames(&file_names)) {
74 return false;
75 }
76 std::set<std::string> set;
77 FileDescriptorProto file_proto;
78 for (const auto& f : file_names) {
79 file_proto.Clear();
80 if (!db->FindFileByName(f, &file_proto)) {
81 GOOGLE_LOG(ERROR) << "File not found in database (unexpected): " << f;
82 return false;
83 }
84 callback(file_proto, &set);
85 }
86 output->insert(output->end(), set.begin(), set.end());
87 return true;
88 }
89 } // namespace
90
~DescriptorDatabase()91 DescriptorDatabase::~DescriptorDatabase() {}
92
FindAllPackageNames(std::vector<std::string> * output)93 bool DescriptorDatabase::FindAllPackageNames(std::vector<std::string>* output) {
94 return ForAllFileProtos(
95 this,
96 [](const FileDescriptorProto& file_proto, std::set<std::string>* set) {
97 set->insert(file_proto.package());
98 },
99 output);
100 }
101
FindAllMessageNames(std::vector<std::string> * output)102 bool DescriptorDatabase::FindAllMessageNames(std::vector<std::string>* output) {
103 return ForAllFileProtos(
104 this,
105 [](const FileDescriptorProto& file_proto, std::set<std::string>* set) {
106 RecordMessageNames(file_proto, set);
107 },
108 output);
109 }
110
111 // ===================================================================
112
SimpleDescriptorDatabase()113 SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
~SimpleDescriptorDatabase()114 SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {}
115
116 template <typename Value>
AddFile(const FileDescriptorProto & file,Value value)117 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
118 const FileDescriptorProto& file, Value value) {
119 if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
120 GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
121 return false;
122 }
123
124 // We must be careful here -- calling file.package() if file.has_package() is
125 // false could access an uninitialized static-storage variable if we are being
126 // run at startup time.
127 std::string path = file.has_package() ? file.package() : std::string();
128 if (!path.empty()) path += '.';
129
130 for (int i = 0; i < file.message_type_size(); i++) {
131 if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
132 if (!AddNestedExtensions(file.name(), file.message_type(i), value))
133 return false;
134 }
135 for (int i = 0; i < file.enum_type_size(); i++) {
136 if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
137 }
138 for (int i = 0; i < file.extension_size(); i++) {
139 if (!AddSymbol(path + file.extension(i).name(), value)) return false;
140 if (!AddExtension(file.name(), file.extension(i), value)) return false;
141 }
142 for (int i = 0; i < file.service_size(); i++) {
143 if (!AddSymbol(path + file.service(i).name(), value)) return false;
144 }
145
146 return true;
147 }
148
149 template <typename Value>
AddSymbol(const std::string & name,Value value)150 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
151 const std::string& name, Value value) {
152 // We need to make sure not to violate our map invariant.
153
154 // If the symbol name is invalid it could break our lookup algorithm (which
155 // relies on the fact that '.' sorts before all other characters that are
156 // valid in symbol names).
157 if (!ValidateSymbolName(name)) {
158 GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
159 return false;
160 }
161
162 // Try to look up the symbol to make sure a super-symbol doesn't already
163 // exist.
164 typename std::map<std::string, Value>::iterator iter =
165 FindLastLessOrEqual(name);
166
167 if (iter == by_symbol_.end()) {
168 // Apparently the map is currently empty. Just insert and be done with it.
169 by_symbol_.insert(
170 typename std::map<std::string, Value>::value_type(name, value));
171 return true;
172 }
173
174 if (IsSubSymbol(iter->first, name)) {
175 GOOGLE_LOG(ERROR) << "Symbol name \"" << name
176 << "\" conflicts with the existing "
177 "symbol \""
178 << iter->first << "\".";
179 return false;
180 }
181
182 // OK, that worked. Now we have to make sure that no symbol in the map is
183 // a sub-symbol of the one we are inserting. The only symbol which could
184 // be so is the first symbol that is greater than the new symbol. Since
185 // |iter| points at the last symbol that is less than or equal, we just have
186 // to increment it.
187 ++iter;
188
189 if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
190 GOOGLE_LOG(ERROR) << "Symbol name \"" << name
191 << "\" conflicts with the existing "
192 "symbol \""
193 << iter->first << "\".";
194 return false;
195 }
196
197 // OK, no conflicts.
198
199 // Insert the new symbol using the iterator as a hint, the new entry will
200 // appear immediately before the one the iterator is pointing at.
201 by_symbol_.insert(
202 iter, typename std::map<std::string, Value>::value_type(name, value));
203
204 return true;
205 }
206
207 template <typename Value>
AddNestedExtensions(const std::string & filename,const DescriptorProto & message_type,Value value)208 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
209 const std::string& filename, const DescriptorProto& message_type,
210 Value value) {
211 for (int i = 0; i < message_type.nested_type_size(); i++) {
212 if (!AddNestedExtensions(filename, message_type.nested_type(i), value))
213 return false;
214 }
215 for (int i = 0; i < message_type.extension_size(); i++) {
216 if (!AddExtension(filename, message_type.extension(i), value)) return false;
217 }
218 return true;
219 }
220
221 template <typename Value>
AddExtension(const std::string & filename,const FieldDescriptorProto & field,Value value)222 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
223 const std::string& filename, const FieldDescriptorProto& field,
224 Value value) {
225 if (!field.extendee().empty() && field.extendee()[0] == '.') {
226 // The extension is fully-qualified. We can use it as a lookup key in
227 // the by_symbol_ table.
228 if (!InsertIfNotPresent(
229 &by_extension_,
230 std::make_pair(field.extendee().substr(1), field.number()),
231 value)) {
232 GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
233 "extend "
234 << field.extendee() << " { " << field.name() << " = "
235 << field.number() << " } from:" << filename;
236 return false;
237 }
238 } else {
239 // Not fully-qualified. We can't really do anything here, unfortunately.
240 // We don't consider this an error, though, because the descriptor is
241 // valid.
242 }
243 return true;
244 }
245
246 template <typename Value>
FindFile(const std::string & filename)247 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
248 const std::string& filename) {
249 return FindWithDefault(by_name_, filename, Value());
250 }
251
252 template <typename Value>
FindSymbol(const std::string & name)253 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
254 const std::string& name) {
255 typename std::map<std::string, Value>::iterator iter =
256 FindLastLessOrEqual(name);
257
258 return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name))
259 ? iter->second
260 : Value();
261 }
262
263 template <typename Value>
FindExtension(const std::string & containing_type,int field_number)264 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
265 const std::string& containing_type, int field_number) {
266 return FindWithDefault(
267 by_extension_, std::make_pair(containing_type, field_number), Value());
268 }
269
270 template <typename Value>
FindAllExtensionNumbers(const std::string & containing_type,std::vector<int> * output)271 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
272 const std::string& containing_type, std::vector<int>* output) {
273 typename std::map<std::pair<std::string, int>, Value>::const_iterator it =
274 by_extension_.lower_bound(std::make_pair(containing_type, 0));
275 bool success = false;
276
277 for (; it != by_extension_.end() && it->first.first == containing_type;
278 ++it) {
279 output->push_back(it->first.second);
280 success = true;
281 }
282
283 return success;
284 }
285
286 template <typename Value>
FindAllFileNames(std::vector<std::string> * output)287 void SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllFileNames(
288 std::vector<std::string>* output) {
289 output->resize(by_name_.size());
290 int i = 0;
291 for (const auto& kv : by_name_) {
292 (*output)[i] = kv.first;
293 i++;
294 }
295 }
296
297 template <typename Value>
298 typename std::map<std::string, Value>::iterator
FindLastLessOrEqual(const std::string & name)299 SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
300 const std::string& name) {
301 // Find the last key in the map which sorts less than or equal to the
302 // symbol name. Since upper_bound() returns the *first* key that sorts
303 // *greater* than the input, we want the element immediately before that.
304 typename std::map<std::string, Value>::iterator iter =
305 by_symbol_.upper_bound(name);
306 if (iter != by_symbol_.begin()) --iter;
307 return iter;
308 }
309
310 template <typename Value>
IsSubSymbol(const std::string & sub_symbol,const std::string & super_symbol)311 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
312 const std::string& sub_symbol, const std::string& super_symbol) {
313 return sub_symbol == super_symbol ||
314 (HasPrefixString(super_symbol, sub_symbol) &&
315 super_symbol[sub_symbol.size()] == '.');
316 }
317
318 template <typename Value>
ValidateSymbolName(const std::string & name)319 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
320 const std::string& name) {
321 for (int i = 0; i < name.size(); i++) {
322 // I don't trust ctype.h due to locales. :(
323 if (name[i] != '.' && name[i] != '_' && (name[i] < '0' || name[i] > '9') &&
324 (name[i] < 'A' || name[i] > 'Z') && (name[i] < 'a' || name[i] > 'z')) {
325 return false;
326 }
327 }
328 return true;
329 }
330
331 // -------------------------------------------------------------------
332
Add(const FileDescriptorProto & file)333 bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
334 FileDescriptorProto* new_file = new FileDescriptorProto;
335 new_file->CopyFrom(file);
336 return AddAndOwn(new_file);
337 }
338
AddAndOwn(const FileDescriptorProto * file)339 bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
340 files_to_delete_.emplace_back(file);
341 return index_.AddFile(*file, file);
342 }
343
FindFileByName(const std::string & filename,FileDescriptorProto * output)344 bool SimpleDescriptorDatabase::FindFileByName(const std::string& filename,
345 FileDescriptorProto* output) {
346 return MaybeCopy(index_.FindFile(filename), output);
347 }
348
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)349 bool SimpleDescriptorDatabase::FindFileContainingSymbol(
350 const std::string& symbol_name, FileDescriptorProto* output) {
351 return MaybeCopy(index_.FindSymbol(symbol_name), output);
352 }
353
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)354 bool SimpleDescriptorDatabase::FindFileContainingExtension(
355 const std::string& containing_type, int field_number,
356 FileDescriptorProto* output) {
357 return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
358 }
359
FindAllExtensionNumbers(const std::string & extendee_type,std::vector<int> * output)360 bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
361 const std::string& extendee_type, std::vector<int>* output) {
362 return index_.FindAllExtensionNumbers(extendee_type, output);
363 }
364
365
FindAllFileNames(std::vector<std::string> * output)366 bool SimpleDescriptorDatabase::FindAllFileNames(
367 std::vector<std::string>* output) {
368 index_.FindAllFileNames(output);
369 return true;
370 }
371
MaybeCopy(const FileDescriptorProto * file,FileDescriptorProto * output)372 bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
373 FileDescriptorProto* output) {
374 if (file == NULL) return false;
375 output->CopyFrom(*file);
376 return true;
377 }
378
379 // -------------------------------------------------------------------
380
EncodedDescriptorDatabase()381 EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
~EncodedDescriptorDatabase()382 EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
383 for (int i = 0; i < files_to_delete_.size(); i++) {
384 operator delete(files_to_delete_[i]);
385 }
386 }
387
Add(const void * encoded_file_descriptor,int size)388 bool EncodedDescriptorDatabase::Add(const void* encoded_file_descriptor,
389 int size) {
390 FileDescriptorProto file;
391 if (file.ParseFromArray(encoded_file_descriptor, size)) {
392 return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size));
393 } else {
394 GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
395 "EncodedDescriptorDatabase::Add().";
396 return false;
397 }
398 }
399
AddCopy(const void * encoded_file_descriptor,int size)400 bool EncodedDescriptorDatabase::AddCopy(const void* encoded_file_descriptor,
401 int size) {
402 void* copy = operator new(size);
403 memcpy(copy, encoded_file_descriptor, size);
404 files_to_delete_.push_back(copy);
405 return Add(copy, size);
406 }
407
FindFileByName(const std::string & filename,FileDescriptorProto * output)408 bool EncodedDescriptorDatabase::FindFileByName(const std::string& filename,
409 FileDescriptorProto* output) {
410 return MaybeParse(index_.FindFile(filename), output);
411 }
412
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)413 bool EncodedDescriptorDatabase::FindFileContainingSymbol(
414 const std::string& symbol_name, FileDescriptorProto* output) {
415 return MaybeParse(index_.FindSymbol(symbol_name), output);
416 }
417
FindNameOfFileContainingSymbol(const std::string & symbol_name,std::string * output)418 bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
419 const std::string& symbol_name, std::string* output) {
420 std::pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
421 if (encoded_file.first == NULL) return false;
422
423 // Optimization: The name should be the first field in the encoded message.
424 // Try to just read it directly.
425 io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
426 encoded_file.second);
427
428 const uint32 kNameTag = internal::WireFormatLite::MakeTag(
429 FileDescriptorProto::kNameFieldNumber,
430 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
431
432 if (input.ReadTagNoLastTag() == kNameTag) {
433 // Success!
434 return internal::WireFormatLite::ReadString(&input, output);
435 } else {
436 // Slow path. Parse whole message.
437 FileDescriptorProto file_proto;
438 if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
439 return false;
440 }
441 *output = file_proto.name();
442 return true;
443 }
444 }
445
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)446 bool EncodedDescriptorDatabase::FindFileContainingExtension(
447 const std::string& containing_type, int field_number,
448 FileDescriptorProto* output) {
449 return MaybeParse(index_.FindExtension(containing_type, field_number),
450 output);
451 }
452
FindAllExtensionNumbers(const std::string & extendee_type,std::vector<int> * output)453 bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
454 const std::string& extendee_type, std::vector<int>* output) {
455 return index_.FindAllExtensionNumbers(extendee_type, output);
456 }
457
FindAllFileNames(std::vector<std::string> * output)458 bool EncodedDescriptorDatabase::FindAllFileNames(
459 std::vector<std::string>* output) {
460 index_.FindAllFileNames(output);
461 return true;
462 }
463
MaybeParse(std::pair<const void *,int> encoded_file,FileDescriptorProto * output)464 bool EncodedDescriptorDatabase::MaybeParse(
465 std::pair<const void*, int> encoded_file, FileDescriptorProto* output) {
466 if (encoded_file.first == NULL) return false;
467 return output->ParseFromArray(encoded_file.first, encoded_file.second);
468 }
469
470 // ===================================================================
471
DescriptorPoolDatabase(const DescriptorPool & pool)472 DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
473 : pool_(pool) {}
~DescriptorPoolDatabase()474 DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
475
FindFileByName(const std::string & filename,FileDescriptorProto * output)476 bool DescriptorPoolDatabase::FindFileByName(const std::string& filename,
477 FileDescriptorProto* output) {
478 const FileDescriptor* file = pool_.FindFileByName(filename);
479 if (file == NULL) return false;
480 output->Clear();
481 file->CopyTo(output);
482 return true;
483 }
484
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)485 bool DescriptorPoolDatabase::FindFileContainingSymbol(
486 const std::string& symbol_name, FileDescriptorProto* output) {
487 const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
488 if (file == NULL) return false;
489 output->Clear();
490 file->CopyTo(output);
491 return true;
492 }
493
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)494 bool DescriptorPoolDatabase::FindFileContainingExtension(
495 const std::string& containing_type, int field_number,
496 FileDescriptorProto* output) {
497 const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
498 if (extendee == NULL) return false;
499
500 const FieldDescriptor* extension =
501 pool_.FindExtensionByNumber(extendee, field_number);
502 if (extension == NULL) return false;
503
504 output->Clear();
505 extension->file()->CopyTo(output);
506 return true;
507 }
508
FindAllExtensionNumbers(const std::string & extendee_type,std::vector<int> * output)509 bool DescriptorPoolDatabase::FindAllExtensionNumbers(
510 const std::string& extendee_type, std::vector<int>* output) {
511 const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
512 if (extendee == NULL) return false;
513
514 std::vector<const FieldDescriptor*> extensions;
515 pool_.FindAllExtensions(extendee, &extensions);
516
517 for (int i = 0; i < extensions.size(); ++i) {
518 output->push_back(extensions[i]->number());
519 }
520
521 return true;
522 }
523
524 // ===================================================================
525
MergedDescriptorDatabase(DescriptorDatabase * source1,DescriptorDatabase * source2)526 MergedDescriptorDatabase::MergedDescriptorDatabase(
527 DescriptorDatabase* source1, DescriptorDatabase* source2) {
528 sources_.push_back(source1);
529 sources_.push_back(source2);
530 }
MergedDescriptorDatabase(const std::vector<DescriptorDatabase * > & sources)531 MergedDescriptorDatabase::MergedDescriptorDatabase(
532 const std::vector<DescriptorDatabase*>& sources)
533 : sources_(sources) {}
~MergedDescriptorDatabase()534 MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
535
FindFileByName(const std::string & filename,FileDescriptorProto * output)536 bool MergedDescriptorDatabase::FindFileByName(const std::string& filename,
537 FileDescriptorProto* output) {
538 for (int i = 0; i < sources_.size(); i++) {
539 if (sources_[i]->FindFileByName(filename, output)) {
540 return true;
541 }
542 }
543 return false;
544 }
545
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)546 bool MergedDescriptorDatabase::FindFileContainingSymbol(
547 const std::string& symbol_name, FileDescriptorProto* output) {
548 for (int i = 0; i < sources_.size(); i++) {
549 if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
550 // The symbol was found in source i. However, if one of the previous
551 // sources defines a file with the same name (which presumably doesn't
552 // contain the symbol, since it wasn't found in that source), then we
553 // must hide it from the caller.
554 FileDescriptorProto temp;
555 for (int j = 0; j < i; j++) {
556 if (sources_[j]->FindFileByName(output->name(), &temp)) {
557 // Found conflicting file in a previous source.
558 return false;
559 }
560 }
561 return true;
562 }
563 }
564 return false;
565 }
566
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)567 bool MergedDescriptorDatabase::FindFileContainingExtension(
568 const std::string& containing_type, int field_number,
569 FileDescriptorProto* output) {
570 for (int i = 0; i < sources_.size(); i++) {
571 if (sources_[i]->FindFileContainingExtension(containing_type, field_number,
572 output)) {
573 // The symbol was found in source i. However, if one of the previous
574 // sources defines a file with the same name (which presumably doesn't
575 // contain the symbol, since it wasn't found in that source), then we
576 // must hide it from the caller.
577 FileDescriptorProto temp;
578 for (int j = 0; j < i; j++) {
579 if (sources_[j]->FindFileByName(output->name(), &temp)) {
580 // Found conflicting file in a previous source.
581 return false;
582 }
583 }
584 return true;
585 }
586 }
587 return false;
588 }
589
FindAllExtensionNumbers(const std::string & extendee_type,std::vector<int> * output)590 bool MergedDescriptorDatabase::FindAllExtensionNumbers(
591 const std::string& extendee_type, std::vector<int>* output) {
592 std::set<int> merged_results;
593 std::vector<int> results;
594 bool success = false;
595
596 for (int i = 0; i < sources_.size(); i++) {
597 if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
598 std::copy(results.begin(), results.end(),
599 std::insert_iterator<std::set<int> >(merged_results,
600 merged_results.begin()));
601 success = true;
602 }
603 results.clear();
604 }
605
606 std::copy(merged_results.begin(), merged_results.end(),
607 std::insert_iterator<std::vector<int> >(*output, output->end()));
608
609 return success;
610 }
611
612
613 } // namespace protobuf
614 } // namespace google
615