LCOV - code coverage report
Current view: top level - toolkit/components/protobuf/src/google/protobuf - descriptor_database.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 47 225 20.9 %
Date: 2017-07-14 16:53:18 Functions: 8 60 13.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/wire_format_lite_inl.h>
      41             : #include <google/protobuf/stubs/strutil.h>
      42             : #include <google/protobuf/stubs/stl_util.h>
      43             : #include <google/protobuf/stubs/map_util.h>
      44             : 
      45             : namespace google {
      46             : namespace protobuf {
      47             : 
      48           0 : DescriptorDatabase::~DescriptorDatabase() {}
      49             : 
      50             : // ===================================================================
      51             : 
      52             : template <typename Value>
      53           6 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
      54             :     const FileDescriptorProto& file,
      55             :     Value value) {
      56           6 :   if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
      57           0 :     GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
      58           0 :     return false;
      59             :   }
      60             : 
      61             :   // We must be careful here -- calling file.package() if file.has_package() is
      62             :   // false could access an uninitialized static-storage variable if we are being
      63             :   // run at startup time.
      64          12 :   string path = file.has_package() ? file.package() : string();
      65           6 :   if (!path.empty()) path += '.';
      66             : 
      67          72 :   for (int i = 0; i < file.message_type_size(); i++) {
      68          66 :     if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
      69          66 :     if (!AddNestedExtensions(file.message_type(i), value)) return false;
      70             :   }
      71           6 :   for (int i = 0; i < file.enum_type_size(); i++) {
      72           0 :     if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
      73             :   }
      74           6 :   for (int i = 0; i < file.extension_size(); i++) {
      75           0 :     if (!AddSymbol(path + file.extension(i).name(), value)) return false;
      76           0 :     if (!AddExtension(file.extension(i), value)) return false;
      77             :   }
      78           6 :   for (int i = 0; i < file.service_size(); i++) {
      79           0 :     if (!AddSymbol(path + file.service(i).name(), value)) return false;
      80             :   }
      81             : 
      82           6 :   return true;
      83             : }
      84             : 
      85             : template <typename Value>
      86          66 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
      87             :     const string& name, Value value) {
      88             :   // We need to make sure not to violate our map invariant.
      89             : 
      90             :   // If the symbol name is invalid it could break our lookup algorithm (which
      91             :   // relies on the fact that '.' sorts before all other characters that are
      92             :   // valid in symbol names).
      93          66 :   if (!ValidateSymbolName(name)) {
      94           0 :     GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
      95           0 :     return false;
      96             :   }
      97             : 
      98             :   // Try to look up the symbol to make sure a super-symbol doesn't already
      99             :   // exist.
     100          66 :   typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
     101             : 
     102          66 :   if (iter == by_symbol_.end()) {
     103             :     // Apparently the map is currently empty.  Just insert and be done with it.
     104           3 :     by_symbol_.insert(typename map<string, Value>::value_type(name, value));
     105           3 :     return true;
     106             :   }
     107             : 
     108          63 :   if (IsSubSymbol(iter->first, name)) {
     109           0 :     GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
     110           0 :                   "symbol \"" << iter->first << "\".";
     111           0 :     return false;
     112             :   }
     113             : 
     114             :   // OK, that worked.  Now we have to make sure that no symbol in the map is
     115             :   // a sub-symbol of the one we are inserting.  The only symbol which could
     116             :   // be so is the first symbol that is greater than the new symbol.  Since
     117             :   // |iter| points at the last symbol that is less than or equal, we just have
     118             :   // to increment it.
     119          63 :   ++iter;
     120             : 
     121          63 :   if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
     122           0 :     GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
     123           0 :                   "symbol \"" << iter->first << "\".";
     124           0 :     return false;
     125             :   }
     126             : 
     127             :   // OK, no conflicts.
     128             : 
     129             :   // Insert the new symbol using the iterator as a hint, the new entry will
     130             :   // appear immediately before the one the iterator is pointing at.
     131          63 :   by_symbol_.insert(iter, typename map<string, Value>::value_type(name, value));
     132             : 
     133          63 :   return true;
     134             : }
     135             : 
     136             : template <typename Value>
     137          78 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
     138             :     const DescriptorProto& message_type,
     139             :     Value value) {
     140          90 :   for (int i = 0; i < message_type.nested_type_size(); i++) {
     141          12 :     if (!AddNestedExtensions(message_type.nested_type(i), value)) return false;
     142             :   }
     143          78 :   for (int i = 0; i < message_type.extension_size(); i++) {
     144           0 :     if (!AddExtension(message_type.extension(i), value)) return false;
     145             :   }
     146          78 :   return true;
     147             : }
     148             : 
     149             : template <typename Value>
     150           0 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
     151             :     const FieldDescriptorProto& field,
     152             :     Value value) {
     153           0 :   if (!field.extendee().empty() && field.extendee()[0] == '.') {
     154             :     // The extension is fully-qualified.  We can use it as a lookup key in
     155             :     // the by_symbol_ table.
     156           0 :     if (!InsertIfNotPresent(&by_extension_,
     157           0 :                             make_pair(field.extendee().substr(1),
     158           0 :                                       field.number()),
     159             :                             value)) {
     160           0 :       GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
     161           0 :                     "extend " << field.extendee() << " { "
     162           0 :                  << field.name() << " = " << field.number() << " }";
     163           0 :       return false;
     164             :     }
     165             :   } else {
     166             :     // Not fully-qualified.  We can't really do anything here, unfortunately.
     167             :     // We don't consider this an error, though, because the descriptor is
     168             :     // valid.
     169             :   }
     170           0 :   return true;
     171             : }
     172             : 
     173             : template <typename Value>
     174           0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
     175             :     const string& filename) {
     176           0 :   return FindWithDefault(by_name_, filename, Value());
     177             : }
     178             : 
     179             : template <typename Value>
     180           0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
     181             :     const string& name) {
     182           0 :   typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
     183             : 
     184           0 :   return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ?
     185           0 :          iter->second : Value();
     186             : }
     187             : 
     188             : template <typename Value>
     189           0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
     190             :     const string& containing_type,
     191             :     int field_number) {
     192           0 :   return FindWithDefault(by_extension_,
     193             :                          make_pair(containing_type, field_number),
     194           0 :                          Value());
     195             : }
     196             : 
     197             : template <typename Value>
     198           0 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
     199             :     const string& containing_type,
     200             :     vector<int>* output) {
     201             :   typename map<pair<string, int>, Value >::const_iterator it =
     202           0 :       by_extension_.lower_bound(make_pair(containing_type, 0));
     203           0 :   bool success = false;
     204             : 
     205           0 :   for (; it != by_extension_.end() && it->first.first == containing_type;
     206             :        ++it) {
     207           0 :     output->push_back(it->first.second);
     208           0 :     success = true;
     209             :   }
     210             : 
     211           0 :   return success;
     212             : }
     213             : 
     214             : template <typename Value>
     215             : typename map<string, Value>::iterator
     216          66 : SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
     217             :     const string& name) {
     218             :   // Find the last key in the map which sorts less than or equal to the
     219             :   // symbol name.  Since upper_bound() returns the *first* key that sorts
     220             :   // *greater* than the input, we want the element immediately before that.
     221          66 :   typename map<string, Value>::iterator iter = by_symbol_.upper_bound(name);
     222          66 :   if (iter != by_symbol_.begin()) --iter;
     223          66 :   return iter;
     224             : }
     225             : 
     226             : template <typename Value>
     227         105 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
     228             :     const string& sub_symbol, const string& super_symbol) {
     229         210 :   return sub_symbol == super_symbol ||
     230         105 :          (HasPrefixString(super_symbol, sub_symbol) &&
     231         105 :              super_symbol[sub_symbol.size()] == '.');
     232             : }
     233             : 
     234             : template <typename Value>
     235          66 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
     236             :     const string& name) {
     237        2223 :   for (int i = 0; i < name.size(); i++) {
     238             :     // I don't trust ctype.h due to locales.  :(
     239        8340 :     if (name[i] != '.' && name[i] != '_' &&
     240        6039 :         (name[i] < '0' || name[i] > '9') &&
     241        8040 :         (name[i] < 'A' || name[i] > 'Z') &&
     242        3714 :         (name[i] < 'a' || name[i] > 'z')) {
     243           0 :       return false;
     244             :     }
     245             :   }
     246          66 :   return true;
     247             : }
     248             : 
     249             : // -------------------------------------------------------------------
     250             : 
     251           0 : SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
     252           0 : SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
     253           0 :   STLDeleteElements(&files_to_delete_);
     254           0 : }
     255             : 
     256           0 : bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
     257           0 :   FileDescriptorProto* new_file = new FileDescriptorProto;
     258           0 :   new_file->CopyFrom(file);
     259           0 :   return AddAndOwn(new_file);
     260             : }
     261             : 
     262           0 : bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
     263           0 :   files_to_delete_.push_back(file);
     264           0 :   return index_.AddFile(*file, file);
     265             : }
     266             : 
     267           0 : bool SimpleDescriptorDatabase::FindFileByName(
     268             :     const string& filename,
     269             :     FileDescriptorProto* output) {
     270           0 :   return MaybeCopy(index_.FindFile(filename), output);
     271             : }
     272             : 
     273           0 : bool SimpleDescriptorDatabase::FindFileContainingSymbol(
     274             :     const string& symbol_name,
     275             :     FileDescriptorProto* output) {
     276           0 :   return MaybeCopy(index_.FindSymbol(symbol_name), output);
     277             : }
     278             : 
     279           0 : bool SimpleDescriptorDatabase::FindFileContainingExtension(
     280             :     const string& containing_type,
     281             :     int field_number,
     282             :     FileDescriptorProto* output) {
     283           0 :   return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
     284             : }
     285             : 
     286           0 : bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
     287             :     const string& extendee_type,
     288             :     vector<int>* output) {
     289           0 :   return index_.FindAllExtensionNumbers(extendee_type, output);
     290             : }
     291             : 
     292             : 
     293           0 : bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
     294             :                                          FileDescriptorProto* output) {
     295           0 :   if (file == NULL) return false;
     296           0 :   output->CopyFrom(*file);
     297           0 :   return true;
     298             : }
     299             : 
     300             : // -------------------------------------------------------------------
     301             : 
     302           3 : EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
     303           0 : EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
     304           0 :   for (int i = 0; i < files_to_delete_.size(); i++) {
     305           0 :     operator delete(files_to_delete_[i]);
     306             :   }
     307           0 : }
     308             : 
     309           6 : bool EncodedDescriptorDatabase::Add(
     310             :     const void* encoded_file_descriptor, int size) {
     311          12 :   FileDescriptorProto file;
     312           6 :   if (file.ParseFromArray(encoded_file_descriptor, size)) {
     313           6 :     return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
     314             :   } else {
     315           0 :     GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
     316           0 :                   "EncodedDescriptorDatabase::Add().";
     317           0 :     return false;
     318             :   }
     319             : }
     320             : 
     321           0 : bool EncodedDescriptorDatabase::AddCopy(
     322             :     const void* encoded_file_descriptor, int size) {
     323           0 :   void* copy = operator new(size);
     324           0 :   memcpy(copy, encoded_file_descriptor, size);
     325           0 :   files_to_delete_.push_back(copy);
     326           0 :   return Add(copy, size);
     327             : }
     328             : 
     329           0 : bool EncodedDescriptorDatabase::FindFileByName(
     330             :     const string& filename,
     331             :     FileDescriptorProto* output) {
     332           0 :   return MaybeParse(index_.FindFile(filename), output);
     333             : }
     334             : 
     335           0 : bool EncodedDescriptorDatabase::FindFileContainingSymbol(
     336             :     const string& symbol_name,
     337             :     FileDescriptorProto* output) {
     338           0 :   return MaybeParse(index_.FindSymbol(symbol_name), output);
     339             : }
     340             : 
     341           0 : bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
     342             :     const string& symbol_name,
     343             :     string* output) {
     344           0 :   pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
     345           0 :   if (encoded_file.first == NULL) return false;
     346             : 
     347             :   // Optimization:  The name should be the first field in the encoded message.
     348             :   //   Try to just read it directly.
     349           0 :   io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
     350           0 :                              encoded_file.second);
     351             : 
     352             :   const uint32 kNameTag = internal::WireFormatLite::MakeTag(
     353             :       FileDescriptorProto::kNameFieldNumber,
     354           0 :       internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
     355             : 
     356           0 :   if (input.ReadTag() == kNameTag) {
     357             :     // Success!
     358           0 :     return internal::WireFormatLite::ReadString(&input, output);
     359             :   } else {
     360             :     // Slow path.  Parse whole message.
     361           0 :     FileDescriptorProto file_proto;
     362           0 :     if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
     363           0 :       return false;
     364             :     }
     365           0 :     *output = file_proto.name();
     366           0 :     return true;
     367             :   }
     368             : }
     369             : 
     370           0 : bool EncodedDescriptorDatabase::FindFileContainingExtension(
     371             :     const string& containing_type,
     372             :     int field_number,
     373             :     FileDescriptorProto* output) {
     374           0 :   return MaybeParse(index_.FindExtension(containing_type, field_number),
     375           0 :                     output);
     376             : }
     377             : 
     378           0 : bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
     379             :     const string& extendee_type,
     380             :     vector<int>* output) {
     381           0 :   return index_.FindAllExtensionNumbers(extendee_type, output);
     382             : }
     383             : 
     384           0 : bool EncodedDescriptorDatabase::MaybeParse(
     385             :     pair<const void*, int> encoded_file,
     386             :     FileDescriptorProto* output) {
     387           0 :   if (encoded_file.first == NULL) return false;
     388           0 :   return output->ParseFromArray(encoded_file.first, encoded_file.second);
     389             : }
     390             : 
     391             : // ===================================================================
     392             : 
     393           0 : DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
     394           0 :   : pool_(pool) {}
     395           0 : DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
     396             : 
     397           0 : bool DescriptorPoolDatabase::FindFileByName(
     398             :     const string& filename,
     399             :     FileDescriptorProto* output) {
     400           0 :   const FileDescriptor* file = pool_.FindFileByName(filename);
     401           0 :   if (file == NULL) return false;
     402           0 :   output->Clear();
     403           0 :   file->CopyTo(output);
     404           0 :   return true;
     405             : }
     406             : 
     407           0 : bool DescriptorPoolDatabase::FindFileContainingSymbol(
     408             :     const string& symbol_name,
     409             :     FileDescriptorProto* output) {
     410           0 :   const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
     411           0 :   if (file == NULL) return false;
     412           0 :   output->Clear();
     413           0 :   file->CopyTo(output);
     414           0 :   return true;
     415             : }
     416             : 
     417           0 : bool DescriptorPoolDatabase::FindFileContainingExtension(
     418             :     const string& containing_type,
     419             :     int field_number,
     420             :     FileDescriptorProto* output) {
     421           0 :   const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
     422           0 :   if (extendee == NULL) return false;
     423             : 
     424             :   const FieldDescriptor* extension =
     425           0 :     pool_.FindExtensionByNumber(extendee, field_number);
     426           0 :   if (extension == NULL) return false;
     427             : 
     428           0 :   output->Clear();
     429           0 :   extension->file()->CopyTo(output);
     430           0 :   return true;
     431             : }
     432             : 
     433           0 : bool DescriptorPoolDatabase::FindAllExtensionNumbers(
     434             :     const string& extendee_type,
     435             :     vector<int>* output) {
     436           0 :   const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
     437           0 :   if (extendee == NULL) return false;
     438             : 
     439           0 :   vector<const FieldDescriptor*> extensions;
     440           0 :   pool_.FindAllExtensions(extendee, &extensions);
     441             : 
     442           0 :   for (int i = 0; i < extensions.size(); ++i) {
     443           0 :     output->push_back(extensions[i]->number());
     444             :   }
     445             : 
     446           0 :   return true;
     447             : }
     448             : 
     449             : // ===================================================================
     450             : 
     451           0 : MergedDescriptorDatabase::MergedDescriptorDatabase(
     452             :     DescriptorDatabase* source1,
     453           0 :     DescriptorDatabase* source2) {
     454           0 :   sources_.push_back(source1);
     455           0 :   sources_.push_back(source2);
     456           0 : }
     457           0 : MergedDescriptorDatabase::MergedDescriptorDatabase(
     458           0 :     const vector<DescriptorDatabase*>& sources)
     459           0 :   : sources_(sources) {}
     460           0 : MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
     461             : 
     462           0 : bool MergedDescriptorDatabase::FindFileByName(
     463             :     const string& filename,
     464             :     FileDescriptorProto* output) {
     465           0 :   for (int i = 0; i < sources_.size(); i++) {
     466           0 :     if (sources_[i]->FindFileByName(filename, output)) {
     467           0 :       return true;
     468             :     }
     469             :   }
     470           0 :   return false;
     471             : }
     472             : 
     473           0 : bool MergedDescriptorDatabase::FindFileContainingSymbol(
     474             :     const string& symbol_name,
     475             :     FileDescriptorProto* output) {
     476           0 :   for (int i = 0; i < sources_.size(); i++) {
     477           0 :     if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
     478             :       // The symbol was found in source i.  However, if one of the previous
     479             :       // sources defines a file with the same name (which presumably doesn't
     480             :       // contain the symbol, since it wasn't found in that source), then we
     481             :       // must hide it from the caller.
     482           0 :       FileDescriptorProto temp;
     483           0 :       for (int j = 0; j < i; j++) {
     484           0 :         if (sources_[j]->FindFileByName(output->name(), &temp)) {
     485             :           // Found conflicting file in a previous source.
     486           0 :           return false;
     487             :         }
     488             :       }
     489           0 :       return true;
     490             :     }
     491             :   }
     492           0 :   return false;
     493             : }
     494             : 
     495           0 : bool MergedDescriptorDatabase::FindFileContainingExtension(
     496             :     const string& containing_type,
     497             :     int field_number,
     498             :     FileDescriptorProto* output) {
     499           0 :   for (int i = 0; i < sources_.size(); i++) {
     500           0 :     if (sources_[i]->FindFileContainingExtension(
     501           0 :           containing_type, field_number, output)) {
     502             :       // The symbol was found in source i.  However, if one of the previous
     503             :       // sources defines a file with the same name (which presumably doesn't
     504             :       // contain the symbol, since it wasn't found in that source), then we
     505             :       // must hide it from the caller.
     506           0 :       FileDescriptorProto temp;
     507           0 :       for (int j = 0; j < i; j++) {
     508           0 :         if (sources_[j]->FindFileByName(output->name(), &temp)) {
     509             :           // Found conflicting file in a previous source.
     510           0 :           return false;
     511             :         }
     512             :       }
     513           0 :       return true;
     514             :     }
     515             :   }
     516           0 :   return false;
     517             : }
     518             : 
     519           0 : bool MergedDescriptorDatabase::FindAllExtensionNumbers(
     520             :     const string& extendee_type,
     521             :     vector<int>* output) {
     522           0 :   set<int> merged_results;
     523           0 :   vector<int> results;
     524           0 :   bool success = false;
     525             : 
     526           0 :   for (int i = 0; i < sources_.size(); i++) {
     527           0 :     if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
     528             :       copy(results.begin(), results.end(),
     529           0 :            insert_iterator<set<int> >(merged_results, merged_results.begin()));
     530           0 :       success = true;
     531             :     }
     532           0 :     results.clear();
     533             :   }
     534             : 
     535             :   copy(merged_results.begin(), merged_results.end(),
     536           0 :        insert_iterator<vector<int> >(*output, output->end()));
     537             : 
     538           0 :   return success;
     539             : }
     540             : 
     541             : 
     542             : }  // namespace protobuf
     543             : }  // namespace google

Generated by: LCOV version 1.13