BWAPI
Undermind/proxy/cpp/include/google/protobuf/descriptor_database.h
Go to the documentation of this file.
00001 // Protocol Buffers - Google's data interchange format
00002 // Copyright 2008 Google Inc.  All rights reserved.
00003 // http://code.google.com/p/protobuf/
00004 //
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are
00007 // met:
00008 //
00009 //     * Redistributions of source code must retain the above copyright
00010 // notice, this list of conditions and the following disclaimer.
00011 //     * Redistributions in binary form must reproduce the above
00012 // copyright notice, this list of conditions and the following disclaimer
00013 // in the documentation and/or other materials provided with the
00014 // distribution.
00015 //     * Neither the name of Google Inc. nor the names of its
00016 // contributors may be used to endorse or promote products derived from
00017 // this software without specific prior written permission.
00018 //
00019 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00031 // Author: kenton@google.com (Kenton Varda)
00032 //  Based on original Protocol Buffers design by
00033 //  Sanjay Ghemawat, Jeff Dean, and others.
00034 //
00035 // Interface for manipulating databases of descriptors.
00036 
00037 #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
00038 #define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
00039 
00040 #include <map>
00041 #include <string>
00042 #include <utility>
00043 #include <vector>
00044 #include <google/protobuf/descriptor.h>
00045 
00046 namespace google {
00047 namespace protobuf {
00048 
00049 // Defined in this file.
00050 class DescriptorDatabase;
00051 class SimpleDescriptorDatabase;
00052 class EncodedDescriptorDatabase;
00053 class DescriptorPoolDatabase;
00054 class MergedDescriptorDatabase;
00055 
00056 // Abstract interface for a database of descriptors.
00057 //
00058 // This is useful if you want to create a DescriptorPool which loads
00059 // descriptors on-demand from some sort of large database.  If the database
00060 // is large, it may be inefficient to enumerate every .proto file inside it
00061 // calling DescriptorPool::BuildFile() for each one.  Instead, a DescriptorPool
00062 // can be created which wraps a DescriptorDatabase and only builds particular
00063 // descriptors when they are needed.
00064 class LIBPROTOBUF_EXPORT DescriptorDatabase {
00065  public:
00066   inline DescriptorDatabase() {}
00067   virtual ~DescriptorDatabase();
00068 
00069   // Find a file by file name.  Fills in in *output and returns true if found.
00070   // Otherwise, returns false, leaving the contents of *output undefined.
00071   virtual bool FindFileByName(const string& filename,
00072                               FileDescriptorProto* output) = 0;
00073 
00074   // Find the file that declares the given fully-qualified symbol name.
00075   // If found, fills in *output and returns true, otherwise returns false
00076   // and leaves *output undefined.
00077   virtual bool FindFileContainingSymbol(const string& symbol_name,
00078                                         FileDescriptorProto* output) = 0;
00079 
00080   // Find the file which defines an extension extending the given message type
00081   // with the given field number.  If found, fills in *output and returns true,
00082   // otherwise returns false and leaves *output undefined.  containing_type
00083   // must be a fully-qualified type name.
00084   virtual bool FindFileContainingExtension(const string& containing_type,
00085                                            int field_number,
00086                                            FileDescriptorProto* output) = 0;
00087 
00088   // Finds the tag numbers used by all known extensions of
00089   // extendee_type, and appends them to output in an undefined
00090   // order. This method is best-effort: it's not guaranteed that the
00091   // database will find all extensions, and it's not guaranteed that
00092   // FindFileContainingExtension will return true on all of the found
00093   // numbers. Returns true if the search was successful, otherwise
00094   // returns false and leaves output unchanged.
00095   //
00096   // This method has a default implementation that always returns
00097   // false.
00098   virtual bool FindAllExtensionNumbers(const string& extendee_type,
00099                                        vector<int>* output) {
00100     return false;
00101   }
00102 
00103  private:
00104   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
00105 };
00106 
00107 // A DescriptorDatabase into which you can insert files manually.
00108 //
00109 // FindFileContainingSymbol() is fully-implemented.  When you add a file, its
00110 // symbols will be indexed for this purpose.  Note that the implementation
00111 // may return false positives, but only if it isn't possible for the symbol
00112 // to be defined in any other file.  In particular, if a file defines a symbol
00113 // "Foo", then searching for "Foo.[anything]" will match that file.  This way,
00114 // the database does not need to aggressively index all children of a symbol.
00115 //
00116 // FindFileContainingExtension() is mostly-implemented.  It works if and only
00117 // if the original FieldDescriptorProto defining the extension has a
00118 // fully-qualified type name in its "extendee" field (i.e. starts with a '.').
00119 // If the extendee is a relative name, SimpleDescriptorDatabase will not
00120 // attempt to resolve the type, so it will not know what type the extension is
00121 // extending.  Therefore, calling FindFileContainingExtension() with the
00122 // extension's containing type will never actually find that extension.  Note
00123 // that this is an unlikely problem, as all FileDescriptorProtos created by the
00124 // protocol compiler (as well as ones created by calling
00125 // FileDescriptor::CopyTo()) will always use fully-qualified names for all
00126 // types.  You only need to worry if you are constructing FileDescriptorProtos
00127 // yourself, or are calling compiler::Parser directly.
00128 class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
00129  public:
00130   SimpleDescriptorDatabase();
00131   ~SimpleDescriptorDatabase();
00132 
00133   // Adds the FileDescriptorProto to the database, making a copy.  The object
00134   // can be deleted after Add() returns.  Returns false if the file conflicted
00135   // with a file already in the database, in which case an error will have
00136   // been written to GOOGLE_LOG(ERROR).
00137   bool Add(const FileDescriptorProto& file);
00138 
00139   // Adds the FileDescriptorProto to the database and takes ownership of it.
00140   bool AddAndOwn(const FileDescriptorProto* file);
00141 
00142   // implements DescriptorDatabase -----------------------------------
00143   bool FindFileByName(const string& filename,
00144                       FileDescriptorProto* output);
00145   bool FindFileContainingSymbol(const string& symbol_name,
00146                                 FileDescriptorProto* output);
00147   bool FindFileContainingExtension(const string& containing_type,
00148                                    int field_number,
00149                                    FileDescriptorProto* output);
00150   bool FindAllExtensionNumbers(const string& extendee_type,
00151                                vector<int>* output);
00152 
00153  private:
00154   // So that it can use DescriptorIndex.
00155   friend class EncodedDescriptorDatabase;
00156 
00157   // An index mapping file names, symbol names, and extension numbers to
00158   // some sort of values.
00159   template <typename Value>
00160   class DescriptorIndex {
00161    public:
00162     // Helpers to recursively add particular descriptors and all their contents
00163     // to the index.
00164     bool AddFile(const FileDescriptorProto& file,
00165                  Value value);
00166     bool AddSymbol(const string& name, Value value);
00167     bool AddNestedExtensions(const DescriptorProto& message_type,
00168                              Value value);
00169     bool AddExtension(const FieldDescriptorProto& field,
00170                       Value value);
00171 
00172     Value FindFile(const string& filename);
00173     Value FindSymbol(const string& name);
00174     Value FindExtension(const string& containing_type, int field_number);
00175     bool FindAllExtensionNumbers(const string& containing_type,
00176                                  vector<int>* output);
00177 
00178    private:
00179     map<string, Value> by_name_;
00180     map<string, Value> by_symbol_;
00181     map<pair<string, int>, Value> by_extension_;
00182 
00183     // Invariant:  The by_symbol_ map does not contain any symbols which are
00184     // prefixes of other symbols in the map.  For example, "foo.bar" is a
00185     // prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
00186     //
00187     // This invariant is important because it means that given a symbol name,
00188     // we can find a key in the map which is a prefix of the symbol in O(lg n)
00189     // time, and we know that there is at most one such key.
00190     //
00191     // The prefix lookup algorithm works like so:
00192     // 1) Find the last key in the map which is less than or equal to the
00193     //    search key.
00194     // 2) If the found key is a prefix of the search key, then return it.
00195     //    Otherwise, there is no match.
00196     //
00197     // I am sure this algorithm has been described elsewhere, but since I
00198     // wasn't able to find it quickly I will instead prove that it works
00199     // myself.  The key to the algorithm is that if a match exists, step (1)
00200     // will find it.  Proof:
00201     // 1) Define the "search key" to be the key we are looking for, the "found
00202     //    key" to be the key found in step (1), and the "match key" to be the
00203     //    key which actually matches the serach key (i.e. the key we're trying
00204     //    to find).
00205     // 2) The found key must be less than or equal to the search key by
00206     //    definition.
00207     // 3) The match key must also be less than or equal to the search key
00208     //    (because it is a prefix).
00209     // 4) The match key cannot be greater than the found key, because if it
00210     //    were, then step (1) of the algorithm would have returned the match
00211     //    key instead (since it finds the *greatest* key which is less than or
00212     //    equal to the search key).
00213     // 5) Therefore, the found key must be between the match key and the search
00214     //    key, inclusive.
00215     // 6) Since the search key must be a sub-symbol of the match key, if it is
00216     //    not equal to the match key, then search_key[match_key.size()] must
00217     //    be '.'.
00218     // 7) Since '.' sorts before any other character that is valid in a symbol
00219     //    name, then if the found key is not equal to the match key, then
00220     //    found_key[match_key.size()] must also be '.', because any other value
00221     //    would make it sort after the search key.
00222     // 8) Therefore, if the found key is not equal to the match key, then the
00223     //    found key must be a sub-symbol of the match key.  However, this would
00224     //    contradict our map invariant which says that no symbol in the map is
00225     //    a sub-symbol of any other.
00226     // 9) Therefore, the found key must match the match key.
00227     //
00228     // The above proof assumes the match key exists.  In the case that the
00229     // match key does not exist, then step (1) will return some other symbol.
00230     // That symbol cannot be a super-symbol of the search key since if it were,
00231     // then it would be a match, and we're assuming the match key doesn't exist.
00232     // Therefore, step 2 will correctly return no match.
00233 
00234     // Find the last entry in the by_symbol_ map whose key is less than or
00235     // equal to the given name.
00236     typename map<string, Value>::iterator FindLastLessOrEqual(
00237         const string& name);
00238 
00239     // True if either the arguments are equal or super_symbol identifies a
00240     // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
00241     // "foo.bar.baz", but not a parent of "foo.barbaz").
00242     bool IsSubSymbol(const string& sub_symbol, const string& super_symbol);
00243 
00244     // Returns true if and only if all characters in the name are alphanumerics,
00245     // underscores, or periods.
00246     bool ValidateSymbolName(const string& name);
00247   };
00248 
00249 
00250   DescriptorIndex<const FileDescriptorProto*> index_;
00251   vector<const FileDescriptorProto*> files_to_delete_;
00252 
00253   // If file is non-NULL, copy it into *output and return true, otherwise
00254   // return false.
00255   bool MaybeCopy(const FileDescriptorProto* file,
00256                  FileDescriptorProto* output);
00257 
00258   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
00259 };
00260 
00261 // Very similar to SimpleDescriptorDatabase, but stores all the descriptors
00262 // as raw bytes and generally tries to use as little memory as possible.
00263 //
00264 // The same caveats regarding FindFileContainingExtension() apply as with
00265 // SimpleDescriptorDatabase.
00266 class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
00267  public:
00268   EncodedDescriptorDatabase();
00269   ~EncodedDescriptorDatabase();
00270 
00271   // Adds the FileDescriptorProto to the database.  The descriptor is provided
00272   // in encoded form.  The database does not make a copy of the bytes, nor
00273   // does it take ownership; it's up to the caller to make sure the bytes
00274   // remain valid for the life of the database.  Returns false and logs an error
00275   // if the bytes are not a valid FileDescriptorProto or if the file conflicted
00276   // with a file already in the database.
00277   bool Add(const void* encoded_file_descriptor, int size);
00278 
00279   // Like Add(), but makes a copy of the data, so that the caller does not
00280   // need to keep it around.
00281   bool AddCopy(const void* encoded_file_descriptor, int size);
00282 
00283   // Like FindFileContainingSymbol but returns only the name of the file.
00284   bool FindNameOfFileContainingSymbol(const string& symbol_name,
00285                                       string* output);
00286 
00287   // implements DescriptorDatabase -----------------------------------
00288   bool FindFileByName(const string& filename,
00289                       FileDescriptorProto* output);
00290   bool FindFileContainingSymbol(const string& symbol_name,
00291                                 FileDescriptorProto* output);
00292   bool FindFileContainingExtension(const string& containing_type,
00293                                    int field_number,
00294                                    FileDescriptorProto* output);
00295   bool FindAllExtensionNumbers(const string& extendee_type,
00296                                vector<int>* output);
00297 
00298  private:
00299   SimpleDescriptorDatabase::DescriptorIndex<pair<const void*, int> > index_;
00300   vector<void*> files_to_delete_;
00301 
00302   // If encoded_file.first is non-NULL, parse the data into *output and return
00303   // true, otherwise return false.
00304   bool MaybeParse(pair<const void*, int> encoded_file,
00305                   FileDescriptorProto* output);
00306 
00307   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
00308 };
00309 
00310 // A DescriptorDatabase that fetches files from a given pool.
00311 class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
00312  public:
00313   DescriptorPoolDatabase(const DescriptorPool& pool);
00314   ~DescriptorPoolDatabase();
00315 
00316   // implements DescriptorDatabase -----------------------------------
00317   bool FindFileByName(const string& filename,
00318                       FileDescriptorProto* output);
00319   bool FindFileContainingSymbol(const string& symbol_name,
00320                                 FileDescriptorProto* output);
00321   bool FindFileContainingExtension(const string& containing_type,
00322                                    int field_number,
00323                                    FileDescriptorProto* output);
00324   bool FindAllExtensionNumbers(const string& extendee_type,
00325                                vector<int>* output);
00326 
00327  private:
00328   const DescriptorPool& pool_;
00329   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
00330 };
00331 
00332 // A DescriptorDatabase that wraps two or more others.  It first searches the
00333 // first database and, if that fails, tries the second, and so on.
00334 class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
00335  public:
00336   // Merge just two databases.  The sources remain property of the caller.
00337   MergedDescriptorDatabase(DescriptorDatabase* source1,
00338                            DescriptorDatabase* source2);
00339   // Merge more than two databases.  The sources remain property of the caller.
00340   // The vector may be deleted after the constructor returns but the
00341   // DescriptorDatabases need to stick around.
00342   MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
00343   ~MergedDescriptorDatabase();
00344 
00345   // implements DescriptorDatabase -----------------------------------
00346   bool FindFileByName(const string& filename,
00347                       FileDescriptorProto* output);
00348   bool FindFileContainingSymbol(const string& symbol_name,
00349                                 FileDescriptorProto* output);
00350   bool FindFileContainingExtension(const string& containing_type,
00351                                    int field_number,
00352                                    FileDescriptorProto* output);
00353   // Merges the results of calling all databases. Returns true iff any
00354   // of the databases returned true.
00355   bool FindAllExtensionNumbers(const string& extendee_type,
00356                                vector<int>* output);
00357 
00358  private:
00359   vector<DescriptorDatabase*> sources_;
00360   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
00361 };
00362 
00363 }  // namespace protobuf
00364 
00365 }  // namespace google
00366 #endif  // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines