|  | @@ -41,6 +41,7 @@
 | 
	
		
			
				|  |  |  #include <google/protobuf/stubs/map_util.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/stubs/stl_util.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  namespace google {
 | 
	
		
			
				|  |  |  namespace protobuf {
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -389,11 +390,14 @@ bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
 | 
	
		
			
				|  |  |  // -------------------------------------------------------------------
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class EncodedDescriptorDatabase::DescriptorIndex {
 | 
	
		
			
				|  |  | +  using String = std::string;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    using Value = std::pair<const void*, int>;
 | 
	
		
			
				|  |  |    // Helpers to recursively add particular descriptors and all their contents
 | 
	
		
			
				|  |  |    // to the index.
 | 
	
		
			
				|  |  | -  bool AddFile(const FileDescriptorProto& file, Value value);
 | 
	
		
			
				|  |  | +  template <typename FileProto>
 | 
	
		
			
				|  |  | +  bool AddFile(const FileProto& file, Value value);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    Value FindFile(StringPiece filename);
 | 
	
		
			
				|  |  |    Value FindSymbol(StringPiece name);
 | 
	
	
		
			
				|  | @@ -406,11 +410,15 @@ class EncodedDescriptorDatabase::DescriptorIndex {
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  |    friend class EncodedDescriptorDatabase;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  bool AddSymbol(StringPiece name, Value value);
 | 
	
		
			
				|  |  | +  bool AddSymbol(StringPiece package, StringPiece symbol,
 | 
	
		
			
				|  |  | +                 Value value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  template <typename DescProto>
 | 
	
		
			
				|  |  |    bool AddNestedExtensions(StringPiece filename,
 | 
	
		
			
				|  |  | -                           const DescriptorProto& message_type, Value value);
 | 
	
		
			
				|  |  | -  bool AddExtension(StringPiece filename,
 | 
	
		
			
				|  |  | -                    const FieldDescriptorProto& field, Value value);
 | 
	
		
			
				|  |  | +                           const DescProto& message_type, Value value);
 | 
	
		
			
				|  |  | +  template <typename FieldProto>
 | 
	
		
			
				|  |  | +  bool AddExtension(StringPiece filename, const FieldProto& field,
 | 
	
		
			
				|  |  | +                    Value value);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // All the maps below have two representations:
 | 
	
		
			
				|  |  |    //  - a std::set<> where we insert initially.
 | 
	
	
		
			
				|  | @@ -421,27 +429,72 @@ class EncodedDescriptorDatabase::DescriptorIndex {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    void EnsureFlat();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  struct Entry {
 | 
	
		
			
				|  |  | -    std::string name;
 | 
	
		
			
				|  |  | +  struct FileEntry {
 | 
	
		
			
				|  |  | +    String name;
 | 
	
		
			
				|  |  |      Value data;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  | -  struct Compare {
 | 
	
		
			
				|  |  | -    bool operator()(const Entry& a, const Entry& b) const {
 | 
	
		
			
				|  |  | +  struct FileCompare {
 | 
	
		
			
				|  |  | +    bool operator()(const FileEntry& a, const FileEntry& b) const {
 | 
	
		
			
				|  |  |        return a.name < b.name;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    bool operator()(const Entry& a, StringPiece b) const {
 | 
	
		
			
				|  |  | +    bool operator()(const FileEntry& a, StringPiece b) const {
 | 
	
		
			
				|  |  |        return a.name < b;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    bool operator()(StringPiece a, const Entry& b) const {
 | 
	
		
			
				|  |  | +    bool operator()(StringPiece a, const FileEntry& b) const {
 | 
	
		
			
				|  |  |        return a < b.name;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  | -  std::set<Entry, Compare> by_name_;
 | 
	
		
			
				|  |  | -  std::vector<Entry> by_name_flat_;
 | 
	
		
			
				|  |  | -  std::set<Entry, Compare> by_symbol_;
 | 
	
		
			
				|  |  | -  std::vector<Entry> by_symbol_flat_;
 | 
	
		
			
				|  |  | +  std::set<FileEntry, FileCompare> by_name_;
 | 
	
		
			
				|  |  | +  std::vector<FileEntry> by_name_flat_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  struct SymbolEntry {
 | 
	
		
			
				|  |  | +    String package;
 | 
	
		
			
				|  |  | +    String symbol;
 | 
	
		
			
				|  |  | +    Value data;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    std::string AsString() const {
 | 
	
		
			
				|  |  | +      return StrCat(package, package.empty() ? "" : ".", symbol);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  struct SymbolCompare {
 | 
	
		
			
				|  |  | +    static std::string AsString(const SymbolEntry& entry) {
 | 
	
		
			
				|  |  | +      return entry.AsString();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    static StringPiece AsString(StringPiece str) { return str; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    static std::pair<StringPiece, StringPiece> GetParts(
 | 
	
		
			
				|  |  | +        const SymbolEntry& entry) {
 | 
	
		
			
				|  |  | +      if (entry.package.empty()) return {entry.symbol, StringPiece{}};
 | 
	
		
			
				|  |  | +      return {entry.package, entry.symbol};
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    static std::pair<StringPiece, StringPiece> GetParts(
 | 
	
		
			
				|  |  | +        StringPiece str) {
 | 
	
		
			
				|  |  | +      return {str, {}};
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    template <typename T, typename U>
 | 
	
		
			
				|  |  | +    bool operator()(const T& lhs, const U& rhs) const {
 | 
	
		
			
				|  |  | +      auto lhs_parts = GetParts(lhs);
 | 
	
		
			
				|  |  | +      auto rhs_parts = GetParts(rhs);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Fast path to avoid making the whole string for common cases.
 | 
	
		
			
				|  |  | +      if (int res =
 | 
	
		
			
				|  |  | +              lhs_parts.first.substr(0, rhs_parts.first.size())
 | 
	
		
			
				|  |  | +                  .compare(rhs_parts.first.substr(0, lhs_parts.first.size()))) {
 | 
	
		
			
				|  |  | +        // If the packages already differ, exit early.
 | 
	
		
			
				|  |  | +        return res < 0;
 | 
	
		
			
				|  |  | +      } else if (lhs_parts.first.size() == rhs_parts.first.size()) {
 | 
	
		
			
				|  |  | +        return lhs_parts.second < rhs_parts.second;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return AsString(lhs) < AsString(rhs);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  std::set<SymbolEntry, SymbolCompare> by_symbol_;
 | 
	
		
			
				|  |  | +  std::vector<SymbolEntry> by_symbol_flat_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    struct ExtensionEntry {
 | 
	
		
			
				|  |  | -    std::string extendee;
 | 
	
		
			
				|  |  | +    String extendee;
 | 
	
		
			
				|  |  |      int extension_number;
 | 
	
		
			
				|  |  |      Value data;
 | 
	
		
			
				|  |  |    };
 | 
	
	
		
			
				|  | @@ -535,34 +588,30 @@ bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
 | 
	
		
			
				|  |  |    return index_->FindAllExtensionNumbers(extendee_type, output);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -bool EncodedDescriptorDatabase::DescriptorIndex::AddFile(
 | 
	
		
			
				|  |  | -    const FileDescriptorProto& file, Value value) {
 | 
	
		
			
				|  |  | -  if (!InsertIfNotPresent(&by_name_, Entry{file.name(), value}) ||
 | 
	
		
			
				|  |  | +template <typename FileProto>
 | 
	
		
			
				|  |  | +bool EncodedDescriptorDatabase::DescriptorIndex::AddFile(const FileProto& file,
 | 
	
		
			
				|  |  | +                                                         Value value) {
 | 
	
		
			
				|  |  | +  if (!InsertIfNotPresent(&by_name_, FileEntry{file.name(), value}) ||
 | 
	
		
			
				|  |  |        std::binary_search(by_name_flat_.begin(), by_name_flat_.end(),
 | 
	
		
			
				|  |  |                           file.name(), by_name_.key_comp())) {
 | 
	
		
			
				|  |  |      GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // We must be careful here -- calling file.package() if file.has_package() is
 | 
	
		
			
				|  |  | -  // false could access an uninitialized static-storage variable if we are being
 | 
	
		
			
				|  |  | -  // run at startup time.
 | 
	
		
			
				|  |  | -  std::string path = file.has_package() ? file.package() : std::string();
 | 
	
		
			
				|  |  | -  if (!path.empty()) path += '.';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  StringPiece package = file.package();
 | 
	
		
			
				|  |  |    for (const auto& message_type : file.message_type()) {
 | 
	
		
			
				|  |  | -    if (!AddSymbol(path + message_type.name(), value)) return false;
 | 
	
		
			
				|  |  | +    if (!AddSymbol(package, message_type.name(), value)) return false;
 | 
	
		
			
				|  |  |      if (!AddNestedExtensions(file.name(), message_type, value)) return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    for (const auto& enum_type : file.enum_type()) {
 | 
	
		
			
				|  |  | -    if (!AddSymbol(path + enum_type.name(), value)) return false;
 | 
	
		
			
				|  |  | +    if (!AddSymbol(package, enum_type.name(), value)) return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    for (const auto& extension : file.extension()) {
 | 
	
		
			
				|  |  | -    if (!AddSymbol(path + extension.name(), value)) return false;
 | 
	
		
			
				|  |  | +    if (!AddSymbol(package, extension.name(), value)) return false;
 | 
	
		
			
				|  |  |      if (!AddExtension(file.name(), extension, value)) return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    for (const auto& service : file.service()) {
 | 
	
		
			
				|  |  | -    if (!AddSymbol(path + service.name(), value)) return false;
 | 
	
		
			
				|  |  | +    if (!AddSymbol(package, service.name(), value)) return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return true;
 | 
	
	
		
			
				|  | @@ -572,10 +621,10 @@ template <typename Iter, typename Iter2>
 | 
	
		
			
				|  |  |  static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter,
 | 
	
		
			
				|  |  |                                       Iter2 end) {
 | 
	
		
			
				|  |  |    if (*iter != end) {
 | 
	
		
			
				|  |  | -    if (IsSubSymbol((*iter)->name, symbol_name)) {
 | 
	
		
			
				|  |  | +    if (IsSubSymbol((*iter)->AsString(), symbol_name)) {
 | 
	
		
			
				|  |  |        GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name
 | 
	
		
			
				|  |  | -                 << "\" conflicts with the existing symbol \"" << (*iter)->name
 | 
	
		
			
				|  |  | -                 << "\".";
 | 
	
		
			
				|  |  | +                 << "\" conflicts with the existing symbol \""
 | 
	
		
			
				|  |  | +                 << (*iter)->AsString() << "\".";
 | 
	
		
			
				|  |  |        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -586,10 +635,10 @@ static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter,
 | 
	
		
			
				|  |  |      // to increment it.
 | 
	
		
			
				|  |  |      ++*iter;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (*iter != end && IsSubSymbol(symbol_name, (*iter)->name)) {
 | 
	
		
			
				|  |  | +    if (*iter != end && IsSubSymbol(symbol_name, (*iter)->AsString())) {
 | 
	
		
			
				|  |  |        GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name
 | 
	
		
			
				|  |  | -                 << "\" conflicts with the existing symbol \"" << (*iter)->name
 | 
	
		
			
				|  |  | -                 << "\".";
 | 
	
		
			
				|  |  | +                 << "\" conflicts with the existing symbol \""
 | 
	
		
			
				|  |  | +                 << (*iter)->AsString() << "\".";
 | 
	
		
			
				|  |  |        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -597,28 +646,30 @@ static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol(
 | 
	
		
			
				|  |  | -    StringPiece name, Value value) {
 | 
	
		
			
				|  |  | +    StringPiece package, StringPiece symbol, Value value) {
 | 
	
		
			
				|  |  | +  SymbolEntry entry = {String(package), String(symbol), value};
 | 
	
		
			
				|  |  | +  std::string entry_as_string = entry.AsString();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    // We need to make sure not to violate our map invariant.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // If the symbol name is invalid it could break our lookup algorithm (which
 | 
	
		
			
				|  |  |    // relies on the fact that '.' sorts before all other characters that are
 | 
	
		
			
				|  |  |    // valid in symbol names).
 | 
	
		
			
				|  |  | -  if (!ValidateSymbolName(name)) {
 | 
	
		
			
				|  |  | -    GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
 | 
	
		
			
				|  |  | +  if (!ValidateSymbolName(package) || !ValidateSymbolName(symbol)) {
 | 
	
		
			
				|  |  | +    GOOGLE_LOG(ERROR) << "Invalid symbol name: " << entry_as_string;
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  Entry entry = {std::string(name), value};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    auto iter = FindLastLessOrEqual(&by_symbol_, entry);
 | 
	
		
			
				|  |  | -  if (!CheckForMutualSubsymbols(name, &iter, by_symbol_.end())) {
 | 
	
		
			
				|  |  | +  if (!CheckForMutualSubsymbols(entry_as_string, &iter, by_symbol_.end())) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Same, but on by_symbol_flat_
 | 
	
		
			
				|  |  |    auto flat_iter =
 | 
	
		
			
				|  |  | -      FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp());
 | 
	
		
			
				|  |  | -  if (!CheckForMutualSubsymbols(name, &flat_iter, by_symbol_flat_.end())) {
 | 
	
		
			
				|  |  | +      FindLastLessOrEqual(&by_symbol_flat_, entry, by_symbol_.key_comp());
 | 
	
		
			
				|  |  | +  if (!CheckForMutualSubsymbols(entry_as_string, &flat_iter,
 | 
	
		
			
				|  |  | +                                by_symbol_flat_.end())) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -626,14 +677,14 @@ bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Insert the new symbol using the iterator as a hint, the new entry will
 | 
	
		
			
				|  |  |    // appear immediately before the one the iterator is pointing at.
 | 
	
		
			
				|  |  | -  by_symbol_.insert(iter, std::move(entry));
 | 
	
		
			
				|  |  | +  by_symbol_.insert(iter, entry);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +template <typename DescProto>
 | 
	
		
			
				|  |  |  bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions(
 | 
	
		
			
				|  |  | -    StringPiece filename, const DescriptorProto& message_type,
 | 
	
		
			
				|  |  | -    Value value) {
 | 
	
		
			
				|  |  | +    StringPiece filename, const DescProto& message_type, Value value) {
 | 
	
		
			
				|  |  |    for (const auto& nested_type : message_type.nested_type()) {
 | 
	
		
			
				|  |  |      if (!AddNestedExtensions(filename, nested_type, value)) return false;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -643,9 +694,9 @@ bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions(
 | 
	
		
			
				|  |  |    return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +template <typename FieldProto>
 | 
	
		
			
				|  |  |  bool EncodedDescriptorDatabase::DescriptorIndex::AddExtension(
 | 
	
		
			
				|  |  | -    StringPiece filename, const FieldDescriptorProto& field,
 | 
	
		
			
				|  |  | -    Value value) {
 | 
	
		
			
				|  |  | +    StringPiece filename, const FieldProto& field, Value value) {
 | 
	
		
			
				|  |  |    if (!field.extendee().empty() && field.extendee()[0] == '.') {
 | 
	
		
			
				|  |  |      // The extension is fully-qualified.  We can use it as a lookup key in
 | 
	
		
			
				|  |  |      // the by_symbol_ table.
 | 
	
	
		
			
				|  | @@ -682,7 +733,7 @@ EncodedDescriptorDatabase::DescriptorIndex::FindSymbolOnlyFlat(
 | 
	
		
			
				|  |  |    auto iter =
 | 
	
		
			
				|  |  |        FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  return iter != by_symbol_flat_.end() && IsSubSymbol(iter->name, name)
 | 
	
		
			
				|  |  | +  return iter != by_symbol_flat_.end() && IsSubSymbol(iter->AsString(), name)
 | 
	
		
			
				|  |  |               ? iter->data
 | 
	
		
			
				|  |  |               : Value();
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -740,11 +791,11 @@ void EncodedDescriptorDatabase::DescriptorIndex::FindAllFileNames(
 | 
	
		
			
				|  |  |    output->resize(by_name_.size() + by_name_flat_.size());
 | 
	
		
			
				|  |  |    int i = 0;
 | 
	
		
			
				|  |  |    for (const auto& entry : by_name_) {
 | 
	
		
			
				|  |  | -    (*output)[i] = entry.name;
 | 
	
		
			
				|  |  | +    (*output)[i] = std::string(entry.name);
 | 
	
		
			
				|  |  |      i++;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    for (const auto& entry : by_name_flat_) {
 | 
	
		
			
				|  |  | -    (*output)[i] = entry.name;
 | 
	
		
			
				|  |  | +    (*output)[i] = std::string(entry.name);
 | 
	
		
			
				|  |  |      i++;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 |