PageRenderTime 133ms CodeModel.GetById 3ms app.highlight 118ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/descriptor.cc

http://github.com/tomahawk-player/tomahawk
C++ | 1943 lines | 1412 code | 279 blank | 252 comment | 292 complexity | 169581e021afaf1ffcb5e8223a3b3ca5 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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

Large files files are truncated, but you can click here to view the full file