BWAPI
|
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__