/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/descriptor.cc
C++ | 1943 lines | 1412 code | 279 blank | 252 comment | 292 complexity | 169581e021afaf1ffcb5e8223a3b3ca5 MD5 | raw file
1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 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/stubs/hash.h> 36#include <map> 37#include <set> 38#include <vector> 39#include <algorithm> 40#include <limits> 41 42#include <google/protobuf/descriptor.h> 43#include <google/protobuf/descriptor_database.h> 44#include <google/protobuf/descriptor.pb.h> 45#include <google/protobuf/dynamic_message.h> 46#include <google/protobuf/text_format.h> 47#include <google/protobuf/unknown_field_set.h> 48#include <google/protobuf/wire_format.h> 49#include <google/protobuf/io/coded_stream.h> 50#include <google/protobuf/io/tokenizer.h> 51#include <google/protobuf/io/zero_copy_stream_impl.h> 52#include <google/protobuf/stubs/common.h> 53#include <google/protobuf/stubs/once.h> 54#include <google/protobuf/stubs/strutil.h> 55#include <google/protobuf/stubs/substitute.h> 56#include <google/protobuf/stubs/map-util.h> 57#include <google/protobuf/stubs/stl_util-inl.h> 58 59#undef PACKAGE // autoheader #defines this. :( 60 61namespace google { 62namespace protobuf { 63 64const FieldDescriptor::CppType 65FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = { 66 static_cast<CppType>(0), // 0 is reserved for errors 67 68 CPPTYPE_DOUBLE, // TYPE_DOUBLE 69 CPPTYPE_FLOAT, // TYPE_FLOAT 70 CPPTYPE_INT64, // TYPE_INT64 71 CPPTYPE_UINT64, // TYPE_UINT64 72 CPPTYPE_INT32, // TYPE_INT32 73 CPPTYPE_UINT64, // TYPE_FIXED64 74 CPPTYPE_UINT32, // TYPE_FIXED32 75 CPPTYPE_BOOL, // TYPE_BOOL 76 CPPTYPE_STRING, // TYPE_STRING 77 CPPTYPE_MESSAGE, // TYPE_GROUP 78 CPPTYPE_MESSAGE, // TYPE_MESSAGE 79 CPPTYPE_STRING, // TYPE_BYTES 80 CPPTYPE_UINT32, // TYPE_UINT32 81 CPPTYPE_ENUM, // TYPE_ENUM 82 CPPTYPE_INT32, // TYPE_SFIXED32 83 CPPTYPE_INT64, // TYPE_SFIXED64 84 CPPTYPE_INT32, // TYPE_SINT32 85 CPPTYPE_INT64, // TYPE_SINT64 86}; 87 88const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { 89 "ERROR", // 0 is reserved for errors 90 91 "double", // TYPE_DOUBLE 92 "float", // TYPE_FLOAT 93 "int64", // TYPE_INT64 94 "uint64", // TYPE_UINT64 95 "int32", // TYPE_INT32 96 "fixed64", // TYPE_FIXED64 97 "fixed32", // TYPE_FIXED32 98 "bool", // TYPE_BOOL 99 "string", // TYPE_STRING 100 "group", // TYPE_GROUP 101 "message", // TYPE_MESSAGE 102 "bytes", // TYPE_BYTES 103 "uint32", // TYPE_UINT32 104 "enum", // TYPE_ENUM 105 "sfixed32", // TYPE_SFIXED32 106 "sfixed64", // TYPE_SFIXED64 107 "sint32", // TYPE_SINT32 108 "sint64", // TYPE_SINT64 109}; 110 111const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { 112 "ERROR", // 0 is reserved for errors 113 114 "optional", // LABEL_OPTIONAL 115 "required", // LABEL_REQUIRED 116 "repeated", // LABEL_REPEATED 117}; 118 119#ifndef _MSC_VER // MSVC doesn't need these and won't even accept them. 120const int FieldDescriptor::kMaxNumber; 121const int FieldDescriptor::kFirstReservedNumber; 122const int FieldDescriptor::kLastReservedNumber; 123#endif 124 125namespace { 126 127const string kEmptyString; 128 129string ToCamelCase(const string& input) { 130 bool capitalize_next = false; 131 string result; 132 result.reserve(input.size()); 133 134 for (int i = 0; i < input.size(); i++) { 135 if (input[i] == '_') { 136 capitalize_next = true; 137 } else if (capitalize_next) { 138 // Note: I distrust ctype.h due to locales. 139 if ('a' <= input[i] && input[i] <= 'z') { 140 result.push_back(input[i] - 'a' + 'A'); 141 } else { 142 result.push_back(input[i]); 143 } 144 capitalize_next = false; 145 } else { 146 result.push_back(input[i]); 147 } 148 } 149 150 // Lower-case the first letter. 151 if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') { 152 result[0] = result[0] - 'A' + 'a'; 153 } 154 155 return result; 156} 157 158// A DescriptorPool contains a bunch of hash_maps to implement the 159// various Find*By*() methods. Since hashtable lookups are O(1), it's 160// most efficient to construct a fixed set of large hash_maps used by 161// all objects in the pool rather than construct one or more small 162// hash_maps for each object. 163// 164// The keys to these hash_maps are (parent, name) or (parent, number) 165// pairs. Unfortunately STL doesn't provide hash functions for pair<>, 166// so we must invent our own. 167// 168// TODO(kenton): Use StringPiece rather than const char* in keys? It would 169// be a lot cleaner but we'd just have to convert it back to const char* 170// for the open source release. 171 172typedef pair<const void*, const char*> PointerStringPair; 173 174struct PointerStringPairEqual { 175 inline bool operator()(const PointerStringPair& a, 176 const PointerStringPair& b) const { 177 return a.first == b.first && strcmp(a.second, b.second) == 0; 178 } 179}; 180 181template<typename PairType> 182struct PointerIntegerPairHash { 183 size_t operator()(const PairType& p) const { 184 // FIXME(kenton): What is the best way to compute this hash? I have 185 // no idea! This seems a bit better than an XOR. 186 return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second; 187 } 188 189 // Used only by MSVC and platforms where hash_map is not available. 190 static const size_t bucket_size = 4; 191 static const size_t min_buckets = 8; 192 inline bool operator()(const PairType& a, const PairType& b) const { 193 return a.first < b.first || 194 (a.first == b.first && a.second < b.second); 195 } 196}; 197 198typedef pair<const Descriptor*, int> DescriptorIntPair; 199typedef pair<const EnumDescriptor*, int> EnumIntPair; 200 201struct PointerStringPairHash { 202 size_t operator()(const PointerStringPair& p) const { 203 // FIXME(kenton): What is the best way to compute this hash? I have 204 // no idea! This seems a bit better than an XOR. 205 hash<const char*> cstring_hash; 206 return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + 207 cstring_hash(p.second); 208 } 209 210 // Used only by MSVC and platforms where hash_map is not available. 211 static const size_t bucket_size = 4; 212 static const size_t min_buckets = 8; 213 inline bool operator()(const PointerStringPair& a, 214 const PointerStringPair& b) const { 215 if (a.first < b.first) return true; 216 if (a.first > b.first) return false; 217 return strcmp(a.second, b.second) < 0; 218 } 219}; 220 221 222struct Symbol { 223 enum Type { 224 NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, PACKAGE 225 }; 226 Type type; 227 union { 228 const Descriptor* descriptor; 229 const FieldDescriptor* field_descriptor; 230 const EnumDescriptor* enum_descriptor; 231 const EnumValueDescriptor* enum_value_descriptor; 232 const ServiceDescriptor* service_descriptor; 233 const MethodDescriptor* method_descriptor; 234 const FileDescriptor* package_file_descriptor; 235 }; 236 237 inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; } 238 inline bool IsNull() const { return type == NULL_SYMBOL; } 239 inline bool IsType() const { 240 return type == MESSAGE || type == ENUM; 241 } 242 inline bool IsAggregate() const { 243 return type == MESSAGE || type == PACKAGE 244 || type == ENUM || type == SERVICE; 245 } 246 247#define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \ 248 inline explicit Symbol(const TYPE* value) { \ 249 type = TYPE_CONSTANT; \ 250 this->FIELD = value; \ 251 } 252 253 CONSTRUCTOR(Descriptor , MESSAGE , descriptor ) 254 CONSTRUCTOR(FieldDescriptor , FIELD , field_descriptor ) 255 CONSTRUCTOR(EnumDescriptor , ENUM , enum_descriptor ) 256 CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor ) 257 CONSTRUCTOR(ServiceDescriptor , SERVICE , service_descriptor ) 258 CONSTRUCTOR(MethodDescriptor , METHOD , method_descriptor ) 259 CONSTRUCTOR(FileDescriptor , PACKAGE , package_file_descriptor) 260#undef CONSTRUCTOR 261 262 const FileDescriptor* GetFile() const { 263 switch (type) { 264 case NULL_SYMBOL: return NULL; 265 case MESSAGE : return descriptor ->file(); 266 case FIELD : return field_descriptor ->file(); 267 case ENUM : return enum_descriptor ->file(); 268 case ENUM_VALUE : return enum_value_descriptor->type()->file(); 269 case SERVICE : return service_descriptor ->file(); 270 case METHOD : return method_descriptor ->service()->file(); 271 case PACKAGE : return package_file_descriptor; 272 } 273 return NULL; 274 } 275}; 276 277const Symbol kNullSymbol; 278 279typedef hash_map<const char*, Symbol, 280 hash<const char*>, streq> 281 SymbolsByNameMap; 282typedef hash_map<PointerStringPair, Symbol, 283 PointerStringPairHash, PointerStringPairEqual> 284 SymbolsByParentMap; 285typedef hash_map<const char*, const FileDescriptor*, 286 hash<const char*>, streq> 287 FilesByNameMap; 288typedef hash_map<PointerStringPair, const FieldDescriptor*, 289 PointerStringPairHash, PointerStringPairEqual> 290 FieldsByNameMap; 291typedef hash_map<DescriptorIntPair, const FieldDescriptor*, 292 PointerIntegerPairHash<DescriptorIntPair> > 293 FieldsByNumberMap; 294typedef hash_map<EnumIntPair, const EnumValueDescriptor*, 295 PointerIntegerPairHash<EnumIntPair> > 296 EnumValuesByNumberMap; 297// This is a map rather than a hash_map, since we use it to iterate 298// through all the extensions that extend a given Descriptor, and an 299// ordered data structure that implements lower_bound is convenient 300// for that. 301typedef map<DescriptorIntPair, const FieldDescriptor*> 302 ExtensionsGroupedByDescriptorMap; 303 304} // anonymous namespace 305 306// =================================================================== 307// DescriptorPool::Tables 308 309class DescriptorPool::Tables { 310 public: 311 Tables(); 312 ~Tables(); 313 314 // Checkpoint the state of the tables. Future calls to Rollback() will 315 // return the Tables to this state. This is used when building files, since 316 // some kinds of validation errors cannot be detected until the file's 317 // descriptors have already been added to the tables. BuildFile() calls 318 // Checkpoint() before it starts building and Rollback() if it encounters 319 // an error. 320 void Checkpoint(); 321 322 // Roll back the Tables to the state of the last Checkpoint(), removing 323 // everything that was added after that point. 324 void Rollback(); 325 326 // The stack of files which are currently being built. Used to detect 327 // cyclic dependencies when loading files from a DescriptorDatabase. Not 328 // used when fallback_database_ == NULL. 329 vector<string> pending_files_; 330 331 // A set of files which we have tried to load from the fallback database 332 // and encountered errors. We will not attempt to load them again. 333 // Not used when fallback_database_ == NULL. 334 hash_set<string> known_bad_files_; 335 336 // The set of descriptors for which we've already loaded the full 337 // set of extensions numbers from fallback_database_. 338 hash_set<const Descriptor*> extensions_loaded_from_db_; 339 340 // ----------------------------------------------------------------- 341 // Finding items. 342 343 // Find symbols. This returns a null Symbol (symbol.IsNull() is true) 344 // if not found. 345 inline Symbol FindSymbol(const string& key) const; 346 347 // This implements the body of DescriptorPool::Find*ByName(). It should 348 // really be a private method of DescriptorPool, but that would require 349 // declaring Symbol in descriptor.h, which would drag all kinds of other 350 // stuff into the header. Yay C++. 351 Symbol FindByNameHelper( 352 const DescriptorPool* pool, const string& name) const; 353 354 // These return NULL if not found. 355 inline const FileDescriptor* FindFile(const string& key) const; 356 inline const FieldDescriptor* FindExtension(const Descriptor* extendee, 357 int number); 358 inline void FindAllExtensions(const Descriptor* extendee, 359 vector<const FieldDescriptor*>* out) const; 360 361 // ----------------------------------------------------------------- 362 // Adding items. 363 364 // These add items to the corresponding tables. They return false if 365 // the key already exists in the table. For AddSymbol(), the string passed 366 // in must be one that was constructed using AllocateString(), as it will 367 // be used as a key in the symbols_by_name_ map without copying. 368 bool AddSymbol(const string& full_name, Symbol symbol); 369 bool AddFile(const FileDescriptor* file); 370 bool AddExtension(const FieldDescriptor* field); 371 372 // ----------------------------------------------------------------- 373 // Allocating memory. 374 375 // Allocate an object which will be reclaimed when the pool is 376 // destroyed. Note that the object's destructor will never be called, 377 // so its fields must be plain old data (primitive data types and 378 // pointers). All of the descriptor types are such objects. 379 template<typename Type> Type* Allocate(); 380 381 // Allocate an array of objects which will be reclaimed when the 382 // pool in destroyed. Again, destructors are never called. 383 template<typename Type> Type* AllocateArray(int count); 384 385 // Allocate a string which will be destroyed when the pool is destroyed. 386 // The string is initialized to the given value for convenience. 387 string* AllocateString(const string& value); 388 389 // Allocate a protocol message object. Some older versions of GCC have 390 // trouble understanding explicit template instantiations in some cases, so 391 // in those cases we have to pass a dummy pointer of the right type as the 392 // parameter instead of specifying the type explicitly. 393 template<typename Type> Type* AllocateMessage(Type* dummy = NULL); 394 395 // Allocate a FileDescriptorTables object. 396 FileDescriptorTables* AllocateFileTables(); 397 398 private: 399 vector<string*> strings_; // All strings in the pool. 400 vector<Message*> messages_; // All messages in the pool. 401 vector<FileDescriptorTables*> file_tables_; // All file tables in the pool. 402 vector<void*> allocations_; // All other memory allocated in the pool. 403 404 SymbolsByNameMap symbols_by_name_; 405 FilesByNameMap files_by_name_; 406 ExtensionsGroupedByDescriptorMap extensions_; 407 408 int strings_before_checkpoint_; 409 int messages_before_checkpoint_; 410 int file_tables_before_checkpoint_; 411 int allocations_before_checkpoint_; 412 vector<const char* > symbols_after_checkpoint_; 413 vector<const char* > files_after_checkpoint_; 414 vector<DescriptorIntPair> extensions_after_checkpoint_; 415 416 // Allocate some bytes which will be reclaimed when the pool is 417 // destroyed. 418 void* AllocateBytes(int size); 419}; 420 421// Contains tables specific to a particular file. These tables are not 422// modified once the file has been constructed, so they need not be 423// protected by a mutex. This makes operations that depend only on the 424// contents of a single file -- e.g. Descriptor::FindFieldByName() -- 425// lock-free. 426// 427// For historical reasons, the definitions of the methods of 428// FileDescriptorTables and DescriptorPool::Tables are interleaved below. 429// These used to be a single class. 430class FileDescriptorTables { 431 public: 432 FileDescriptorTables(); 433 ~FileDescriptorTables(); 434 435 // Empty table, used with placeholder files. 436 static const FileDescriptorTables kEmpty; 437 438 // ----------------------------------------------------------------- 439 // Finding items. 440 441 // Find symbols. These return a null Symbol (symbol.IsNull() is true) 442 // if not found. 443 inline Symbol FindNestedSymbol(const void* parent, 444 const string& name) const; 445 inline Symbol FindNestedSymbolOfType(const void* parent, 446 const string& name, 447 const Symbol::Type type) const; 448 449 // These return NULL if not found. 450 inline const FieldDescriptor* FindFieldByNumber( 451 const Descriptor* parent, int number) const; 452 inline const FieldDescriptor* FindFieldByLowercaseName( 453 const void* parent, const string& lowercase_name) const; 454 inline const FieldDescriptor* FindFieldByCamelcaseName( 455 const void* parent, const string& camelcase_name) const; 456 inline const EnumValueDescriptor* FindEnumValueByNumber( 457 const EnumDescriptor* parent, int number) const; 458 459 // ----------------------------------------------------------------- 460 // Adding items. 461 462 // These add items to the corresponding tables. They return false if 463 // the key already exists in the table. For AddAliasUnderParent(), the 464 // string passed in must be one that was constructed using AllocateString(), 465 // as it will be used as a key in the symbols_by_parent_ map without copying. 466 bool AddAliasUnderParent(const void* parent, const string& name, 467 Symbol symbol); 468 bool AddFieldByNumber(const FieldDescriptor* field); 469 bool AddEnumValueByNumber(const EnumValueDescriptor* value); 470 471 // Adds the field to the lowercase_name and camelcase_name maps. Never 472 // fails because we allow duplicates; the first field by the name wins. 473 void AddFieldByStylizedNames(const FieldDescriptor* field); 474 475 private: 476 SymbolsByParentMap symbols_by_parent_; 477 FieldsByNameMap fields_by_lowercase_name_; 478 FieldsByNameMap fields_by_camelcase_name_; 479 FieldsByNumberMap fields_by_number_; // Not including extensions. 480 EnumValuesByNumberMap enum_values_by_number_; 481}; 482 483DescriptorPool::Tables::Tables() 484 : strings_before_checkpoint_(0), 485 messages_before_checkpoint_(0), 486 allocations_before_checkpoint_(0) {} 487 488DescriptorPool::Tables::~Tables() { 489 // Note that the deletion order is important, since the destructors of some 490 // messages may refer to objects in allocations_. 491 STLDeleteElements(&messages_); 492 for (int i = 0; i < allocations_.size(); i++) { 493 operator delete(allocations_[i]); 494 } 495 STLDeleteElements(&strings_); 496 STLDeleteElements(&file_tables_); 497} 498 499FileDescriptorTables::FileDescriptorTables() {} 500FileDescriptorTables::~FileDescriptorTables() {} 501 502const FileDescriptorTables FileDescriptorTables::kEmpty; 503 504void DescriptorPool::Tables::Checkpoint() { 505 strings_before_checkpoint_ = strings_.size(); 506 messages_before_checkpoint_ = messages_.size(); 507 file_tables_before_checkpoint_ = file_tables_.size(); 508 allocations_before_checkpoint_ = allocations_.size(); 509 510 symbols_after_checkpoint_.clear(); 511 files_after_checkpoint_.clear(); 512 extensions_after_checkpoint_.clear(); 513} 514 515void DescriptorPool::Tables::Rollback() { 516 for (int i = 0; i < symbols_after_checkpoint_.size(); i++) { 517 symbols_by_name_.erase(symbols_after_checkpoint_[i]); 518 } 519 for (int i = 0; i < files_after_checkpoint_.size(); i++) { 520 files_by_name_.erase(files_after_checkpoint_[i]); 521 } 522 for (int i = 0; i < extensions_after_checkpoint_.size(); i++) { 523 extensions_.erase(extensions_after_checkpoint_[i]); 524 } 525 526 symbols_after_checkpoint_.clear(); 527 files_after_checkpoint_.clear(); 528 extensions_after_checkpoint_.clear(); 529 530 STLDeleteContainerPointers( 531 strings_.begin() + strings_before_checkpoint_, strings_.end()); 532 STLDeleteContainerPointers( 533 messages_.begin() + messages_before_checkpoint_, messages_.end()); 534 STLDeleteContainerPointers( 535 file_tables_.begin() + file_tables_before_checkpoint_, file_tables_.end()); 536 for (int i = allocations_before_checkpoint_; i < allocations_.size(); i++) { 537 operator delete(allocations_[i]); 538 } 539 540 strings_.resize(strings_before_checkpoint_); 541 messages_.resize(messages_before_checkpoint_); 542 file_tables_.resize(file_tables_before_checkpoint_); 543 allocations_.resize(allocations_before_checkpoint_); 544} 545 546// ------------------------------------------------------------------- 547 548inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const { 549 const Symbol* result = FindOrNull(symbols_by_name_, key.c_str()); 550 if (result == NULL) { 551 return kNullSymbol; 552 } else { 553 return *result; 554 } 555} 556 557inline Symbol FileDescriptorTables::FindNestedSymbol( 558 const void* parent, const string& name) const { 559 const Symbol* result = 560 FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str())); 561 if (result == NULL) { 562 return kNullSymbol; 563 } else { 564 return *result; 565 } 566} 567 568inline Symbol FileDescriptorTables::FindNestedSymbolOfType( 569 const void* parent, const string& name, const Symbol::Type type) const { 570 Symbol result = FindNestedSymbol(parent, name); 571 if (result.type != type) return kNullSymbol; 572 return result; 573} 574 575Symbol DescriptorPool::Tables::FindByNameHelper( 576 const DescriptorPool* pool, const string& name) const { 577 MutexLockMaybe lock(pool->mutex_); 578 Symbol result = FindSymbol(name); 579 580 if (result.IsNull() && pool->underlay_ != NULL) { 581 // Symbol not found; check the underlay. 582 result = 583 pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name); 584 } 585 586 if (result.IsNull()) { 587 // Symbol still not found, so check fallback database. 588 if (pool->TryFindSymbolInFallbackDatabase(name)) { 589 result = FindSymbol(name); 590 } 591 } 592 593 return result; 594} 595 596inline const FileDescriptor* DescriptorPool::Tables::FindFile( 597 const string& key) const { 598 return FindPtrOrNull(files_by_name_, key.c_str()); 599} 600 601inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( 602 const Descriptor* parent, int number) const { 603 return FindPtrOrNull(fields_by_number_, make_pair(parent, number)); 604} 605 606inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( 607 const void* parent, const string& lowercase_name) const { 608 return FindPtrOrNull(fields_by_lowercase_name_, 609 PointerStringPair(parent, lowercase_name.c_str())); 610} 611 612inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( 613 const void* parent, const string& camelcase_name) const { 614 return FindPtrOrNull(fields_by_camelcase_name_, 615 PointerStringPair(parent, camelcase_name.c_str())); 616} 617 618inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( 619 const EnumDescriptor* parent, int number) const { 620 return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number)); 621} 622 623inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( 624 const Descriptor* extendee, int number) { 625 return FindPtrOrNull(extensions_, make_pair(extendee, number)); 626} 627 628inline void DescriptorPool::Tables::FindAllExtensions( 629 const Descriptor* extendee, vector<const FieldDescriptor*>* out) const { 630 ExtensionsGroupedByDescriptorMap::const_iterator it = 631 extensions_.lower_bound(make_pair(extendee, 0)); 632 for (; it != extensions_.end() && it->first.first == extendee; ++it) { 633 out->push_back(it->second); 634 } 635} 636 637// ------------------------------------------------------------------- 638 639bool DescriptorPool::Tables::AddSymbol( 640 const string& full_name, Symbol symbol) { 641 if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) { 642 symbols_after_checkpoint_.push_back(full_name.c_str()); 643 return true; 644 } else { 645 return false; 646 } 647} 648 649bool FileDescriptorTables::AddAliasUnderParent( 650 const void* parent, const string& name, Symbol symbol) { 651 PointerStringPair by_parent_key(parent, name.c_str()); 652 return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol); 653} 654 655bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) { 656 if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) { 657 files_after_checkpoint_.push_back(file->name().c_str()); 658 return true; 659 } else { 660 return false; 661 } 662} 663 664void FileDescriptorTables::AddFieldByStylizedNames( 665 const FieldDescriptor* field) { 666 const void* parent; 667 if (field->is_extension()) { 668 if (field->extension_scope() == NULL) { 669 parent = field->file(); 670 } else { 671 parent = field->extension_scope(); 672 } 673 } else { 674 parent = field->containing_type(); 675 } 676 677 PointerStringPair lowercase_key(parent, field->lowercase_name().c_str()); 678 InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field); 679 680 PointerStringPair camelcase_key(parent, field->camelcase_name().c_str()); 681 InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field); 682} 683 684bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) { 685 DescriptorIntPair key(field->containing_type(), field->number()); 686 return InsertIfNotPresent(&fields_by_number_, key, field); 687} 688 689bool FileDescriptorTables::AddEnumValueByNumber( 690 const EnumValueDescriptor* value) { 691 EnumIntPair key(value->type(), value->number()); 692 return InsertIfNotPresent(&enum_values_by_number_, key, value); 693} 694 695bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) { 696 DescriptorIntPair key(field->containing_type(), field->number()); 697 if (InsertIfNotPresent(&extensions_, key, field)) { 698 extensions_after_checkpoint_.push_back(key); 699 return true; 700 } else { 701 return false; 702 } 703} 704 705// ------------------------------------------------------------------- 706 707template<typename Type> 708Type* DescriptorPool::Tables::Allocate() { 709 return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type))); 710} 711 712template<typename Type> 713Type* DescriptorPool::Tables::AllocateArray(int count) { 714 return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count)); 715} 716 717string* DescriptorPool::Tables::AllocateString(const string& value) { 718 string* result = new string(value); 719 strings_.push_back(result); 720 return result; 721} 722 723template<typename Type> 724Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) { 725 Type* result = new Type; 726 messages_.push_back(result); 727 return result; 728} 729 730FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() { 731 FileDescriptorTables* result = new FileDescriptorTables; 732 file_tables_.push_back(result); 733 return result; 734} 735 736void* DescriptorPool::Tables::AllocateBytes(int size) { 737 // TODO(kenton): Would it be worthwhile to implement this in some more 738 // sophisticated way? Probably not for the open source release, but for 739 // internal use we could easily plug in one of our existing memory pool 740 // allocators... 741 if (size == 0) return NULL; 742 743 void* result = operator new(size); 744 allocations_.push_back(result); 745 return result; 746} 747 748// =================================================================== 749// DescriptorPool 750 751DescriptorPool::ErrorCollector::~ErrorCollector() {} 752 753DescriptorPool::DescriptorPool() 754 : mutex_(NULL), 755 fallback_database_(NULL), 756 default_error_collector_(NULL), 757 underlay_(NULL), 758 tables_(new Tables), 759 enforce_dependencies_(true), 760 allow_unknown_(false) {} 761 762DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, 763 ErrorCollector* error_collector) 764 : mutex_(new Mutex), 765 fallback_database_(fallback_database), 766 default_error_collector_(error_collector), 767 underlay_(NULL), 768 tables_(new Tables), 769 enforce_dependencies_(true), 770 allow_unknown_(false) { 771} 772 773DescriptorPool::DescriptorPool(const DescriptorPool* underlay) 774 : mutex_(NULL), 775 fallback_database_(NULL), 776 default_error_collector_(NULL), 777 underlay_(underlay), 778 tables_(new Tables), 779 enforce_dependencies_(true), 780 allow_unknown_(false) {} 781 782DescriptorPool::~DescriptorPool() { 783 if (mutex_ != NULL) delete mutex_; 784} 785 786// DescriptorPool::BuildFile() defined later. 787// DescriptorPool::BuildFileCollectingErrors() defined later. 788 789void DescriptorPool::InternalDontEnforceDependencies() { 790 enforce_dependencies_ = false; 791} 792 793bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { 794 MutexLockMaybe lock(mutex_); 795 return tables_->FindFile(filename) != NULL; 796} 797 798// generated_pool ==================================================== 799 800namespace { 801 802 803EncodedDescriptorDatabase* generated_database_ = NULL; 804DescriptorPool* generated_pool_ = NULL; 805GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_); 806 807void DeleteGeneratedPool() { 808 delete generated_database_; 809 generated_database_ = NULL; 810 delete generated_pool_; 811 generated_pool_ = NULL; 812} 813 814void InitGeneratedPool() { 815 generated_database_ = new EncodedDescriptorDatabase; 816 generated_pool_ = new DescriptorPool(generated_database_); 817 818 internal::OnShutdown(&DeleteGeneratedPool); 819} 820 821inline void InitGeneratedPoolOnce() { 822 ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); 823} 824 825} // anonymous namespace 826 827const DescriptorPool* DescriptorPool::generated_pool() { 828 InitGeneratedPoolOnce(); 829 return generated_pool_; 830} 831 832DescriptorPool* DescriptorPool::internal_generated_pool() { 833 InitGeneratedPoolOnce(); 834 return generated_pool_; 835} 836 837void DescriptorPool::InternalAddGeneratedFile( 838 const void* encoded_file_descriptor, int size) { 839 // So, this function is called in the process of initializing the 840 // descriptors for generated proto classes. Each generated .pb.cc file 841 // has an internal procedure called AddDescriptors() which is called at 842 // process startup, and that function calls this one in order to register 843 // the raw bytes of the FileDescriptorProto representing the file. 844 // 845 // We do not actually construct the descriptor objects right away. We just 846 // hang on to the bytes until they are actually needed. We actually construct 847 // the descriptor the first time one of the following things happens: 848 // * Someone calls a method like descriptor(), GetDescriptor(), or 849 // GetReflection() on the generated types, which requires returning the 850 // descriptor or an object based on it. 851 // * Someone looks up the descriptor in DescriptorPool::generated_pool(). 852 // 853 // Once one of these happens, the DescriptorPool actually parses the 854 // FileDescriptorProto and generates a FileDescriptor (and all its children) 855 // based on it. 856 // 857 // Note that FileDescriptorProto is itself a generated protocol message. 858 // Therefore, when we parse one, we have to be very careful to avoid using 859 // any descriptor-based operations, since this might cause infinite recursion 860 // or deadlock. 861 InitGeneratedPoolOnce(); 862 GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size)); 863} 864 865 866// Find*By* methods ================================================== 867 868// TODO(kenton): There's a lot of repeated code here, but I'm not sure if 869// there's any good way to factor it out. Think about this some time when 870// there's nothing more important to do (read: never). 871 872const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { 873 MutexLockMaybe lock(mutex_); 874 const FileDescriptor* result = tables_->FindFile(name); 875 if (result != NULL) return result; 876 if (underlay_ != NULL) { 877 const FileDescriptor* result = underlay_->FindFileByName(name); 878 if (result != NULL) return result; 879 } 880 if (TryFindFileInFallbackDatabase(name)) { 881 const FileDescriptor* result = tables_->FindFile(name); 882 if (result != NULL) return result; 883 } 884 return NULL; 885} 886 887const FileDescriptor* DescriptorPool::FindFileContainingSymbol( 888 const string& symbol_name) const { 889 MutexLockMaybe lock(mutex_); 890 Symbol result = tables_->FindSymbol(symbol_name); 891 if (!result.IsNull()) return result.GetFile(); 892 if (underlay_ != NULL) { 893 const FileDescriptor* result = 894 underlay_->FindFileContainingSymbol(symbol_name); 895 if (result != NULL) return result; 896 } 897 if (TryFindSymbolInFallbackDatabase(symbol_name)) { 898 Symbol result = tables_->FindSymbol(symbol_name); 899 if (!result.IsNull()) return result.GetFile(); 900 } 901 return NULL; 902} 903 904const Descriptor* DescriptorPool::FindMessageTypeByName( 905 const string& name) const { 906 Symbol result = tables_->FindByNameHelper(this, name); 907 return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL; 908} 909 910const FieldDescriptor* DescriptorPool::FindFieldByName( 911 const string& name) const { 912 Symbol result = tables_->FindByNameHelper(this, name); 913 if (result.type == Symbol::FIELD && 914 !result.field_descriptor->is_extension()) { 915 return result.field_descriptor; 916 } else { 917 return NULL; 918 } 919} 920 921const FieldDescriptor* DescriptorPool::FindExtensionByName( 922 const string& name) const { 923 Symbol result = tables_->FindByNameHelper(this, name); 924 if (result.type == Symbol::FIELD && 925 result.field_descriptor->is_extension()) { 926 return result.field_descriptor; 927 } else { 928 return NULL; 929 } 930} 931 932const EnumDescriptor* DescriptorPool::FindEnumTypeByName( 933 const string& name) const { 934 Symbol result = tables_->FindByNameHelper(this, name); 935 return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL; 936} 937 938const EnumValueDescriptor* DescriptorPool::FindEnumValueByName( 939 const string& name) const { 940 Symbol result = tables_->FindByNameHelper(this, name); 941 return (result.type == Symbol::ENUM_VALUE) ? 942 result.enum_value_descriptor : NULL; 943} 944 945const ServiceDescriptor* DescriptorPool::FindServiceByName( 946 const string& name) const { 947 Symbol result = tables_->FindByNameHelper(this, name); 948 return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL; 949} 950 951const MethodDescriptor* DescriptorPool::FindMethodByName( 952 const string& name) const { 953 Symbol result = tables_->FindByNameHelper(this, name); 954 return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL; 955} 956 957const FieldDescriptor* DescriptorPool::FindExtensionByNumber( 958 const Descriptor* extendee, int number) const { 959 MutexLockMaybe lock(mutex_); 960 const FieldDescriptor* result = tables_->FindExtension(extendee, number); 961 if (result != NULL) { 962 return result; 963 } 964 if (underlay_ != NULL) { 965 const FieldDescriptor* result = 966 underlay_->FindExtensionByNumber(extendee, number); 967 if (result != NULL) return result; 968 } 969 if (TryFindExtensionInFallbackDatabase(extendee, number)) { 970 const FieldDescriptor* result = tables_->FindExtension(extendee, number); 971 if (result != NULL) { 972 return result; 973 } 974 } 975 return NULL; 976} 977 978void DescriptorPool::FindAllExtensions( 979 const Descriptor* extendee, vector<const FieldDescriptor*>* out) const { 980 MutexLockMaybe lock(mutex_); 981 982 // Initialize tables_->extensions_ from the fallback database first 983 // (but do this only once per descriptor). 984 if (fallback_database_ != NULL && 985 tables_->extensions_loaded_from_db_.count(extendee) == 0) { 986 vector<int> numbers; 987 if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), 988 &numbers)) { 989 for (int i = 0; i < numbers.size(); ++i) { 990 int number = numbers[i]; 991 if (tables_->FindExtension(extendee, number) == NULL) { 992 TryFindExtensionInFallbackDatabase(extendee, number); 993 } 994 } 995 tables_->extensions_loaded_from_db_.insert(extendee); 996 } 997 } 998 999 tables_->FindAllExtensions(extendee, out); 1000 if (underlay_ != NULL) { 1001 underlay_->FindAllExtensions(extendee, out); 1002 } 1003} 1004 1005// ------------------------------------------------------------------- 1006 1007const FieldDescriptor* 1008Descriptor::FindFieldByNumber(int key) const { 1009 const FieldDescriptor* result = 1010 file()->tables_->FindFieldByNumber(this, key); 1011 if (result == NULL || result->is_extension()) { 1012 return NULL; 1013 } else { 1014 return result; 1015 } 1016} 1017 1018const FieldDescriptor* 1019Descriptor::FindFieldByLowercaseName(const string& key) const { 1020 const FieldDescriptor* result = 1021 file()->tables_->FindFieldByLowercaseName(this, key); 1022 if (result == NULL || result->is_extension()) { 1023 return NULL; 1024 } else { 1025 return result; 1026 } 1027} 1028 1029const FieldDescriptor* 1030Descriptor::FindFieldByCamelcaseName(const string& key) const { 1031 const FieldDescriptor* result = 1032 file()->tables_->FindFieldByCamelcaseName(this, key); 1033 if (result == NULL || result->is_extension()) { 1034 return NULL; 1035 } else { 1036 return result; 1037 } 1038} 1039 1040const FieldDescriptor* 1041Descriptor::FindFieldByName(const string& key) const { 1042 Symbol result = 1043 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); 1044 if (!result.IsNull() && !result.field_descriptor->is_extension()) { 1045 return result.field_descriptor; 1046 } else { 1047 return NULL; 1048 } 1049} 1050 1051const FieldDescriptor* 1052Descriptor::FindExtensionByName(const string& key) const { 1053 Symbol result = 1054 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); 1055 if (!result.IsNull() && result.field_descriptor->is_extension()) { 1056 return result.field_descriptor; 1057 } else { 1058 return NULL; 1059 } 1060} 1061 1062const FieldDescriptor* 1063Descriptor::FindExtensionByLowercaseName(const string& key) const { 1064 const FieldDescriptor* result = 1065 file()->tables_->FindFieldByLowercaseName(this, key); 1066 if (result == NULL || !result->is_extension()) { 1067 return NULL; 1068 } else { 1069 return result; 1070 } 1071} 1072 1073const FieldDescriptor* 1074Descriptor::FindExtensionByCamelcaseName(const string& key) const { 1075 const FieldDescriptor* result = 1076 file()->tables_->FindFieldByCamelcaseName(this, key); 1077 if (result == NULL || !result->is_extension()) { 1078 return NULL; 1079 } else { 1080 return result; 1081 } 1082} 1083 1084const Descriptor* 1085Descriptor::FindNestedTypeByName(const string& key) const { 1086 Symbol result = 1087 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); 1088 if (!result.IsNull()) { 1089 return result.descriptor; 1090 } else { 1091 return NULL; 1092 } 1093} 1094 1095const EnumDescriptor* 1096Descriptor::FindEnumTypeByName(const string& key) const { 1097 Symbol result = 1098 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); 1099 if (!result.IsNull()) { 1100 return result.enum_descriptor; 1101 } else { 1102 return NULL; 1103 } 1104} 1105 1106const EnumValueDescriptor* 1107Descriptor::FindEnumValueByName(const string& key) const { 1108 Symbol result = 1109 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); 1110 if (!result.IsNull()) { 1111 return result.enum_value_descriptor; 1112 } else { 1113 return NULL; 1114 } 1115} 1116 1117const EnumValueDescriptor* 1118EnumDescriptor::FindValueByName(const string& key) const { 1119 Symbol result = 1120 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); 1121 if (!result.IsNull()) { 1122 return result.enum_value_descriptor; 1123 } else { 1124 return NULL; 1125 } 1126} 1127 1128const EnumValueDescriptor* 1129EnumDescriptor::FindValueByNumber(int key) const { 1130 return file()->tables_->FindEnumValueByNumber(this, key); 1131} 1132 1133const MethodDescriptor* 1134ServiceDescriptor::FindMethodByName(const string& key) const { 1135 Symbol result = 1136 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD); 1137 if (!result.IsNull()) { 1138 return result.method_descriptor; 1139 } else { 1140 return NULL; 1141 } 1142} 1143 1144const Descriptor* 1145FileDescriptor::FindMessageTypeByName(const string& key) const { 1146 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); 1147 if (!result.IsNull()) { 1148 return result.descriptor; 1149 } else { 1150 return NULL; 1151 } 1152} 1153 1154const EnumDescriptor* 1155FileDescriptor::FindEnumTypeByName(const string& key) const { 1156 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); 1157 if (!result.IsNull()) { 1158 return result.enum_descriptor; 1159 } else { 1160 return NULL; 1161 } 1162} 1163 1164const EnumValueDescriptor* 1165FileDescriptor::FindEnumValueByName(const string& key) const { 1166 Symbol result = 1167 tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); 1168 if (!result.IsNull()) { 1169 return result.enum_value_descriptor; 1170 } else { 1171 return NULL; 1172 } 1173} 1174 1175const ServiceDescriptor* 1176FileDescriptor::FindServiceByName(const string& key) const { 1177 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE); 1178 if (!result.IsNull()) { 1179 return result.service_descriptor; 1180 } else { 1181 return NULL; 1182 } 1183} 1184 1185const FieldDescriptor* 1186FileDescriptor::FindExtensionByName(const string& key) const { 1187 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); 1188 if (!result.IsNull() && result.field_descriptor->is_extension()) { 1189 return result.field_descriptor; 1190 } else { 1191 return NULL; 1192 } 1193} 1194 1195const FieldDescriptor* 1196FileDescriptor::FindExtensionByLowercaseName(const string& key) const { 1197 const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key); 1198 if (result == NULL || !result->is_extension()) { 1199 return NULL; 1200 } else { 1201 return result; 1202 } 1203} 1204 1205const FieldDescriptor* 1206FileDescriptor::FindExtensionByCamelcaseName(const string& key) const { 1207 const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key); 1208 if (result == NULL || !result->is_extension()) { 1209 return NULL; 1210 } else { 1211 return result; 1212 } 1213} 1214 1215bool Descriptor::IsExtensionNumber(int number) const { 1216 // Linear search should be fine because we don't expect a message to have 1217 // more than a couple extension ranges. 1218 for (int i = 0; i < extension_range_count(); i++) { 1219 if (number >= extension_range(i)->start && 1220 number < extension_range(i)->end) { 1221 return true; 1222 } 1223 } 1224 return false; 1225} 1226 1227// ------------------------------------------------------------------- 1228 1229bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { 1230 if (fallback_database_ == NULL) return false; 1231 1232 if (tables_->known_bad_files_.count(name) > 0) return false; 1233 1234 FileDescriptorProto file_proto; 1235 if (!fallback_database_->FindFileByName(name, &file_proto) || 1236 BuildFileFromDatabase(file_proto) == NULL) { 1237 tables_->known_bad_files_.insert(name); 1238 return false; 1239 } 1240 1241 return true; 1242} 1243 1244bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { 1245 if (fallback_database_ == NULL) return false; 1246 1247 FileDescriptorProto file_proto; 1248 if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) { 1249 return false; 1250 } 1251 1252 if (tables_->FindFile(file_proto.name()) != NULL) { 1253 // We've already loaded this file, and it apparently doesn't contain the 1254 // symbol we're looking for. Some DescriptorDatabases return false 1255 // positives. 1256 return false; 1257 } 1258 1259 if (BuildFileFromDatabase(file_proto) == NULL) { 1260 return false; 1261 } 1262 1263 return true; 1264} 1265 1266bool DescriptorPool::TryFindExtensionInFallbackDatabase( 1267 const Descriptor* containing_type, int field_number) const { 1268 if (fallback_database_ == NULL) return false; 1269 1270 FileDescriptorProto file_proto; 1271 if (!fallback_database_->FindFileContainingExtension( 1272 containing_type->full_name(), field_number, &file_proto)) { 1273 return false; 1274 } 1275 1276 if (tables_->FindFile(file_proto.name()) != NULL) { 1277 // We've already loaded this file, and it apparently doesn't contain the 1278 // extension we're looking for. Some DescriptorDatabases return false 1279 // positives. 1280 return false; 1281 } 1282 1283 if (BuildFileFromDatabase(file_proto) == NULL) { 1284 return false; 1285 } 1286 1287 return true; 1288} 1289 1290// =================================================================== 1291 1292string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const { 1293 GOOGLE_CHECK(has_default_value()) << "No default value"; 1294 switch (cpp_type()) { 1295 case CPPTYPE_INT32: 1296 return SimpleItoa(default_value_int32()); 1297 break; 1298 case CPPTYPE_INT64: 1299 return SimpleItoa(default_value_int64()); 1300 break; 1301 case CPPTYPE_UINT32: 1302 return SimpleItoa(default_value_uint32()); 1303 break; 1304 case CPPTYPE_UINT64: 1305 return SimpleItoa(default_value_uint64()); 1306 break; 1307 case CPPTYPE_FLOAT: 1308 return SimpleFtoa(default_value_float()); 1309 break; 1310 case CPPTYPE_DOUBLE: 1311 return SimpleDtoa(default_value_double()); 1312 break; 1313 case CPPTYPE_BOOL: 1314 return default_value_bool() ? "true" : "false"; 1315 break; 1316 case CPPTYPE_STRING: 1317 if (quote_string_type) { 1318 return "\"" + CEscape(default_value_string()) + "\""; 1319 } else { 1320 if (type() == TYPE_BYTES) { 1321 return CEscape(default_value_string()); 1322 } else { 1323 return default_value_string(); 1324 } 1325 } 1326 break; 1327 case CPPTYPE_ENUM: 1328 return default_value_enum()->name(); 1329 break; 1330 case CPPTYPE_MESSAGE: 1331 GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; 1332 break; 1333 } 1334 GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string"; 1335 return ""; 1336} 1337 1338// CopyTo methods ==================================================== 1339 1340void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { 1341 proto->set_name(name()); 1342 if (!package().empty()) proto->set_package(package()); 1343 1344 for (int i = 0; i < dependency_count(); i++) { 1345 proto->add_dependency(dependency(i)->name()); 1346 } 1347 1348 for (int i = 0; i < message_type_count(); i++) { 1349 message_type(i)->CopyTo(proto->add_message_type()); 1350 } 1351 for (int i = 0; i < enum_type_count(); i++) { 1352 enum_type(i)->CopyTo(proto->add_enum_type()); 1353 } 1354 for (int i = 0; i < service_count(); i++) { 1355 service(i)->CopyTo(proto->add_service()); 1356 } 1357 for (int i = 0; i < extension_count(); i++) { 1358 extension(i)->CopyTo(proto->add_extension()); 1359 } 1360 1361 if (&options() != &FileOptions::default_instance()) { 1362 proto->mutable_options()->CopyFrom(options()); 1363 } 1364} 1365 1366void Descriptor::CopyTo(DescriptorProto* proto) const { 1367 proto->set_name(name()); 1368 1369 for (int i = 0; i < field_count(); i++) { 1370 field(i)->CopyTo(proto->add_field()); 1371 } 1372 for (int i = 0; i < nested_type_count(); i++) { 1373 nested_type(i)->CopyTo(proto->add_nested_type()); 1374 } 1375 for (int i = 0; i < enum_type_count(); i++) { 1376 enum_type(i)->CopyTo(proto->add_enum_type()); 1377 } 1378 for (int i = 0; i < extension_range_count(); i++) { 1379 DescriptorProto::ExtensionRange* range = proto->add_extension_range(); 1380 range->set_start(extension_range(i)->start); 1381 range->set_end(extension_range(i)->end); 1382 } 1383 for (int i = 0; i < extension_count(); i++) { 1384 extension(i)->CopyTo(proto->add_extension()); 1385 } 1386 1387 if (&options() != &MessageOptions::default_instance()) { 1388 proto->mutable_options()->CopyFrom(options()); 1389 } 1390} 1391 1392void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { 1393 proto->set_name(name()); 1394 proto->set_number(number()); 1395 1396 // Some compilers do not allow static_cast directly between two enum types, 1397 // so we must cast to int first. 1398 proto->set_label(static_cast<FieldDescriptorProto::Label>( 1399 implicit_cast<int>(label()))); 1400 proto->set_type(static_cast<FieldDescriptorProto::Type>( 1401 implicit_cast<int>(type()))); 1402 1403 if (is_extension()) { 1404 if (!containing_type()->is_unqualified_placeholder_) { 1405 proto->set_extendee("."); 1406 } 1407 proto->mutable_extendee()->append(containing_type()->full_name()); 1408 } 1409 1410 if (cpp_type() == CPPTYPE_MESSAGE) { 1411 if (message_type()->is_placeholder_) { 1412 // We don't actually know if the type is a message type. It could be 1413 // an enum. 1414 proto->clear_type(); 1415 } 1416 1417 if (!message_type()->is_unqualified_placeholder_) { 1418 proto->set_type_name("."); 1419 } 1420 proto->mutable_type_name()->append(message_type()->full_name()); 1421 } else if (cpp_type() == CPPTYPE_ENUM) { 1422 if (!enum_type()->is_unqualified_placeholder_) { 1423 proto->set_type_name("."); 1424 } 1425 proto->mutable_type_name()->append(enum_type()->full_name()); 1426 } 1427 1428 if (has_default_value()) { 1429 proto->set_default_value(DefaultValueAsString(false)); 1430 } 1431 1432 if (&options() != &FieldOptions::default_instance()) { 1433 proto->mutable_options()->CopyFrom(options()); 1434 } 1435} 1436 1437void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { 1438 proto->set_name(name()); 1439 1440 for (int i = 0; i < value_count(); i++) { 1441 value(i)->CopyTo(proto->add_value()); 1442 } 1443 1444 if (&options() != &EnumOptions::default_instance()) { 1445 proto->mutable_options()->CopyFrom(options()); 1446 } 1447} 1448 1449void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const { 1450 proto->set_name(name()); 1451 proto->set_number(number()); 1452 1453 if (&options() != &EnumValueOptions::default_instance()) { 1454 proto->mutable_options()->CopyFrom(options()); 1455 } 1456} 1457 1458void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const { 1459 proto->set_name(name()); 1460 1461 for (int i = 0; i < method_count(); i++) { 1462 method(i)->CopyTo(proto->add_method()); 1463 } 1464 1465 if (&options() != &ServiceOptions::default_instance()) { 1466 proto->mutable_options()->CopyFrom(options()); 1467 } 1468} 1469 1470void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const { 1471 proto->set_name(name()); 1472 1473 if (!input_type()->is_unqualified_placeholder_) { 1474 proto->set_input_type("."); 1475 } 1476 proto->mutable_input_type()->append(input_type()->full_name()); 1477 1478 if (!output_type()->is_unqualified_placeholder_) { 1479 proto->set_output_type("."); 1480 } 1481 proto->mutable_output_type()->append(output_type()->full_name()); 1482 1483 if (&options() != &MethodOptions::default_instance()) { 1484 proto->mutable_options()->CopyFrom(options()); 1485 } 1486} 1487 1488// DebugString methods =============================================== 1489 1490namespace { 1491 1492// Used by each of the option formatters. 1493bool RetrieveOptions(const Message &options, vector<string> *option_entries) { 1494 option_entries->clear(); 1495 const Reflection* reflection = options.GetReflection(); 1496 vector<const FieldDescriptor*> fields; 1497 reflection->ListFields(options, &fields); 1498 for (int i = 0; i < fields.size(); i++) { 1499 // Doesn't make sense to have message type fields here 1500 if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 1501 continue; 1502 } 1503 int count = 1; 1504 bool repeated = false; 1505 if (fields[i]->is_repeated()) { 1506 count = reflection->FieldSize(options, fields[i]); 1507 repeated = true; 1508 } 1509 for (int j = 0; j < count; j++) { 1510 string fieldval; 1511 TextFormat::PrintFieldValueToString(options, fields[i], 1512 repeated ? count : -1, &fieldval); 1513 option_entries->push_back(fields[i]->name() + " = " + fieldval); 1514 } 1515 } 1516 return !option_entries->empty(); 1517} 1518 1519// Formats options that all appear together in brackets. Does not include 1520// brackets. 1521bool FormatBracketedOptions(const Message &options, string *output) { 1522 vector<string> all_options; 1523 if (RetrieveOptions(options, &all_options)) { 1524 output->append(JoinStrings(all_options, ", ")); 1525 } 1526 return !all_options.empty(); 1527} 1528 1529// Formats options one per line 1530bool FormatLineOptions(int depth, const Message &options, string *output) { 1531 string prefix(depth * 2, ' '); 1532 vector<string> all_options; 1533 if (RetrieveOptions(options, &all_options)) { 1534 for (int i = 0; i < all_options.size(); i++) { 1535 strings::SubstituteAndAppend(output, "$0option $1;\n", 1536 prefix, all_options[i]); 1537 } 1538 } 1539 return !all_options.empty(); 1540} 1541 1542} // anonymous namespace 1543 1544string FileDescriptor::DebugString() const { 1545 string contents = "syntax = \"proto2\";\n\n"; 1546 1547 for (int i = 0; i < dependency_count(); i++) { 1548 strings::SubstituteAndAppend(&contents, "import \"$0\";\n", 1549 dependency(i)->name()); 1550 } 1551 1552 if (!package().empty()) { 1553 strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); 1554 } 1555 1556 if (FormatLineOptions(0, options(), &contents)) { 1557 contents.append("\n"); // add some space if we had options 1558 } 1559 1560 for (int i = 0; i < enum_type_count(); i++) { 1561 enum_type(i)->DebugString(0, &contents); 1562 contents.append("\n"); 1563 } 1564 1565 // Find all the 'group' type extensions; we will not output their nested 1566 // definitions (those will be done with their group field descriptor). 1567 set<const Descriptor*> groups; 1568 for (int i = 0; i < extension_count(); i++) { 1569 if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { 1570 groups.insert(extension(i)->message_type()); 1571 } 1572 } 1573 1574 for (int i = 0; i < message_type_count(); i++) { 1575 if (groups.count(message_type(i)) == 0) { 1576 strings::SubstituteAndAppend(&contents, "message $0", 1577 message_type(i)->name()); 1578 message_type(i)->DebugString(0, &contents); 1579 contents.append("\n"); 1580 } 1581 } 1582 1583 for (int i = 0; i < service_count(); i++) { 1584 service(i)->DebugString(&contents); 1585 contents.append("\n"); 1586 } 1587 1588 const Descriptor* containing_type = NULL; 1589 for (int i = 0; i < extension_count(); i++) { 1590 if (extension(i)->containing_type() != containing_type) { 1591 if (i > 0) contents.append("}\n\n"); 1592 containing_type = extension(i)->containing_type(); 1593 strings::SubstituteAndAppend(&contents, "extend .$0 {\n", 1594 containing_type->full_name()); 1595 } 1596 extension(i)->DebugString(1, &contents); 1597 } 1598 if (extension_count() > 0) contents.append("}\n\n"); 1599 1600 return contents; 1601} 1602 1603string Descriptor::DebugString() const { 1604 string contents; 1605 strings::SubstituteAndAppend(&contents, "message $0", name()); 1606 DebugString(0, &contents); 1607 return contents; 1608} 1609 1610void Descriptor::DebugString(int depth, string *contents) const { 1611 string prefix(depth * 2, ' '); 1612 ++depth; 1613 contents->append(" {\n"); 1614 1615 FormatLineOptions(depth, options(), contents); 1616 1617 // Find all the 'group' types for fields and extensions; we will not output 1618 // their nested definitions (those will be done with their group field 1619 // descriptor). 1620 set<const Descriptor*> groups; 1621 for (int i = 0; i < field_count(); i++) { 1622 if (field(i)->type() == FieldDescriptor::TYPE_GROUP) { 1623 groups.insert(field(i)->message_type()); 1624 } 1625 } 1626 for (int i = 0; i < extension_count(); i++) { 1627 if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { 1628 groups.insert(extension(i)->message_type()); 1629 } 1630 } 1631 1632 for (int i = 0; i < nested_type_count(); i++) { 1633 if (groups.count(nested_type(i)) == 0) { 1634 strings::SubstituteAndAppend(contents, "$0 message $1", 1635 prefix, nested_type(i)->name()); 1636 nested_type(i)->DebugString(depth, contents); 1637 } 1638 } 1639 for (int i = 0; i < enum_type_count(); i++) { 1640 enum_type(i)->DebugString(depth, contents); 1641 } 1642 for (int i = 0; i < field_count(); i++) { 1643 field(i)->DebugString(depth, contents); 1644 } 1645 1646 for (int i = 0; i < extension_range_count(); i++) { 1647 strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", 1648 prefix, 1649 extension_range(i)->start, 1650 extension_range(i)->end - 1); 1651 } 1652 1653 // Group extensions by what they extend, so they can be printed out together. 1654 const Descriptor* containing_type = NULL; 1655 for (int i = 0; i < extension_count(); i++) { 1656 if (extension(i)->containing_type() != containing_type) { 1657 if (i > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); 1658 containing_type = extension(i)->containing_type(); 1659 strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", 1660 prefix, containing_type->full_name()); 1661 } 1662 extension(i)->DebugString(depth + 1, contents); 1663 } 1664 if (extension_count() > 0) 1665 strings::SubstituteAndAppend(contents, "$0 }\n", prefix); 1666 1667 strings::SubstituteAndAppend(contents, "$0}\n", prefix); 1668} 1669 1670string FieldDescriptor::DebugString() const { 1671 string contents; 1672 int depth = 0; 1673 if (is_extension()) { 1674 strings::SubstituteAndAppend(&contents, "extend .$0 {\n", 1675 containing_type()->full_name()); 1676 depth = 1; 1677 } 1678 DebugString(depth, &contents); 1679 if (is_extension()) { 1680 contents.append("}\n"); 1681 } 1682 return contents; 1683} 1684 1685void FieldDescriptor::DebugString(int depth, string *contents) const { 1686 string prefix(depth * 2, ' '); 1687 string field_type; 1688 switch (type()) { 1689 case TYPE_MESSAGE: 1690 field_type = "." + message_type()->full_name(); 1691 break; 1692 case TYPE_ENUM: 1693 field_type = "." + enum_type()->full_name(); 1694 break; 1695 default: 1696 field_type = kTypeToName[type()]; 1697 } 1698 1699 strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4", 1700 prefix, 1701 kLabelToName[label()], 1702 field_type, 1703 type() == TYPE_GROUP ? message_type()->name() : 1704 name(), 1705 number()); 1706 1707 bool bracketed = false; 1708 if (has_default_value()) { 1709 bracketed = true; 1710 strings::SubstituteAndAppend(contents, " [default = $0", 1711 DefaultValueAsString(true)); 1712 } 1713 1714 string formatted_options; 1715 if (FormatBracketedOptions(options(), &formatted_options)) { 1716 contents->append(bracketed ? ", " : " ["); 1717 bracketed = true; 1718 contents->append(formatted_options); 1719 } 1720 1721 if (bracketed) { 1722 contents->append("]"); 1723 } 1724 1725 if (type() == TYPE_GROUP) { 1726 message_type()->DebugString(depth, contents); 1727 } else { 1728 contents->append(";\n"); 1729 } 1730} 1731 1732string EnumDescriptor::DebugString() const { 1733 string contents; 1734 DebugString(0, &contents); 1735 return contents; 1736} 1737 1738void EnumDescriptor::DebugString(int depth, string *contents) const { 1739 string prefix(depth * 2, ' '); 1740 ++depth; 1741 strings::SubstituteAndAppend(contents, "$0enum $1 {\n", 1742 prefix, name()); 1743 1744 FormatLineOptions(depth, options(), contents); 1745 1746 for (int i = 0; i < value_count(); i++) { 1747 value(i)->DebugString(depth, contents); 1748 } 1749 strings::SubstituteAndAppend(contents, "$0}\n", prefix); 1750} 1751 1752string EnumValueDescriptor::DebugString() const { 1753 string contents; 1754 DebugString(0, &contents); 1755 return contents; 1756} 1757 1758void EnumValueDescriptor::DebugString(int depth, string *contents) const { 1759 string prefix(depth * 2, ' '); 1760 strings::SubstituteAndAppend(contents, "$0$1 = $2", 1761 prefix, name(), number()); 1762 1763 string formatted_options; 1764 if (FormatBracketedOptions(options(), &formatted_options)) { 1765 strings::SubstituteAndAppend(contents, " [$0]", formatted_options); 1766 } 1767 contents->append(";\n"); 1768} 1769 1770string ServiceDescriptor::DebugString() const { 1771 string contents; 1772 DebugString(&contents); 1773 return contents; 1774} 1775 1776void ServiceDescriptor::DebugString(string *contents) const { 1777 strings::SubstituteAndAppend(contents, "service $0 {\n", name()); 1778 1779 FormatLineOptions(1, options(), contents); 1780 1781 for (int i = 0; i < method_count(); i++) { 1782 method(i)->DebugString(1, contents); 1783 } 1784 1785 contents->append("}\n"); 1786} 1787 1788string MethodDescriptor::DebugString() const { 1789 string contents; 1790 DebugString(0, &contents); 1791 return contents; 1792} 1793 1794void MethodDescriptor::DebugString(int depth, string *contents) const { 1795 string prefix(depth * 2, ' '); 1796 ++depth; 1797 strings::SubstituteAndAppend(contents, "$0rpc $1(.$2) returns (.$3)", 1798 prefix, name(), 1799 input_type()->full_name(), 1800 output_type()->full_name()); 1801 1802 string formatted_options; 1803 if (FormatLineOptions(depth, options(), &formatted_options)) { 1804 strings::SubstituteAndAppend(contents, " {\n$0$1}\n", 1805 formatted_options, prefix); 1806 } else { 1807 contents->append(";\n"); 1808 } 1809} 1810// =================================================================== 1811 1812namespace { 1813 1814// Represents an options message to interpret. Extension names in the option 1815// name are respolved relative to name_scope. element_name and orig_opt are 1816// used only for error reporting (since the parser records locations against 1817// pointers in the original options, not the mutable copy). The Message must be 1818// one of the Options messages in descriptor.proto. 1819struct OptionsToInterpret { 1820 OptionsToInterpret(const string& ns, 1821 const string& el, 1822 const Message* orig_opt, 1823 Message* opt) 1824 : name_scope(ns), 1825 element_name(el), 1826 original_options(orig_opt), 1827 options(opt) { 1828 } 1829 string name_scope; 1830 string element_name; 1831 const Message* original_options; 1832 Message* options; 1833}; 1834 1835} // namespace 1836 1837class DescriptorBuilder { 1838 public: 1839 DescriptorBuilder(const DescriptorPool* pool, 1840 DescriptorPool::Tables* tables, 1841 DescriptorPool::ErrorCollector* error_collector); 1842 ~DescriptorBuilder(); 1843 1844 const FileDescriptor* BuildFile(const FileDescriptorProto& proto); 1845 1846 private: 1847 friend class OptionInterpreter; 1848 1849 const DescriptorPool* pool_; 1850 DescriptorPool::Tables* tables_; // for convenience 1851 DescriptorPool::ErrorCollector* error_collector_; 1852 1853 // As we build descriptors we store copies of the options messages in 1854 // them. We put pointers to those copies in this vector, as we build, so we 1855 // can later (after cross-linking) interpret those options. 1856 vector<OptionsToInterpret> options_to_interpret_; 1857 1858 bool had_errors_; 1859 string filename_; 1860 FileDescriptor* file_; 1861 FileDescriptorTables* file_tables_; 1862 1863 // If LookupSymbol() finds a symbol that is in a file which is not a declared 1864 // dependency of this file, it will fail, but will set 1865 // possible_undeclared_dependency_ to point at that file. This is only used 1866 // by AddNotDefinedError() to report a more useful error message. 1867 // possible_undeclared_dependency_name_ is the name of the symbol that was 1868 // actually found in possible_undeclared_dependency_, which may be a parent 1869 // of the symbol actually looked for. 1870 const FileDescriptor* possible_undeclared_dependency_; 1871 string possible_undeclared_dependency_name_; 1872 1873 void AddError(const string& element_name, 1874 const Message& descriptor, 1875 DescriptorPool::ErrorCollector::ErrorLocation location, 1876 const string& error); 1877 1878 // Adds an error indicating that undefined_symbol was not defined. Must 1879 // only be called after LookupSymbol() fails. 1880 void AddNotDefinedError( 1881 const string& element_name, 1882 const Message& descriptor, 1883 DescriptorPool::ErrorCollector::ErrorLocation location, 1884 const string& undefined_symbol); 1885 1886 // Silly helper which determines if the given file is in the given package. 1887 // I.e., either file->package() == package_name or file->package() is a 1888 // nested package within package_name. 1889 bool IsInPackage(const FileDescriptor* file, const string& package_name); 1890 1891 // Like tables_->FindSymbol(), but additionally: 1892 // - Search the pool's underlay if not found in tables_. 1893 // - Insure that the resulting Symbol is from one of the file's declared 1894 // dependencies. 1895 Symbol FindSymbol(const string& name); 1896 1897 // Like FindSymbol() but does not require that the symbol is in one of the 1898 // file's declared dependencies. 1899 Symbol FindSymbolNotEnforcingDeps(const string& name); 1900 1901 // Like FindSymbol(), but looks up the name relative to some other symbol 1902 // name. This first searches siblings of relative_to, then siblings of its 1903 // parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes 1904 // the following calls, returning the first non-null result: 1905 // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"), 1906 // FindSymbol("foo.bar"). If AllowUnknownDependencies() has been called 1907 // on the DescriptorPool, this will generate a placeholder type if 1908 // the name is not found (unless the name itself is malformed). The 1909 // placeholder_type parameter indicates what kind of placeholder should be 1910 // constructed in this case. The resolve_mode parameter determines whether 1911 // any symbol is returned, or only symbols that are types. Note, however, 1912 // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode, 1913 // if it believes that's all it could refer to. The caller should always 1914 // check that it receives the type of symbol it was expecting. 1915 enum PlaceholderType { 1916 PLACEHOLDER_MESSAGE, 1917 PLACEHOLDER_ENUM, 1918 PLACEHOLDER_EXTENDABLE_MESSAGE 1919 }; 1920 enum ResolveMode { 1921 LOOKUP_ALL, LOOKUP_TYPES 1922 }; 1923 Symbol LookupSymbol(const string& name, const string& relative_to, 1924 PlaceholderType placeholder_type = PLACEHOLDER_MESSAGE, 1925 ResolveMode resolve_mode = LOOKUP_ALL); 1926 1927 // Like LookupSymbol() but will not return a placeholder even if 1928 // AllowUnknownDependencies() has been used. 1929 Symbol LookupSymbolNoPlaceholder(const string& name, 1930 const string& relative_to, 1931 ResolveMode resolve_mode = LOOKUP_ALL); 1932 1933 // Creates a placeholder type suitable for return from LookupSymbol(). May 1934 // return kNullSymbol if the name is not a valid type name. 1935 Symbol NewPlaceholder(const string& name, PlaceholderType placeholder_type); 1936 1937 // Creates a placeholder file. Never returns NULL. This is used when an 1938 // import is not found and AllowUnknownDependencies() is enabled. 1939 const FileDescriptor* NewPlaceholderFile(const string& name); 1940 1941 // Calls tables_->AddSymbol() and records an error if it fails. Returns 1942 // true if successful or false if failed, though most callers can ignore 1943 // the return value since