15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/hash.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor_database.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/dynamic_message.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/text_format.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/unknown_field_set.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/wire_format.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/coded_stream.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/tokenizer.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream_impl.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/common.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/once.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/substitute.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/map-util.h>
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/stl_util.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef PACKAGE  // autoheader #defines this.  :(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor::CppType
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<CppType>(0),  // 0 is reserved for errors
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_DOUBLE,   // TYPE_DOUBLE
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_FLOAT,    // TYPE_FLOAT
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT64,    // TYPE_INT64
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_UINT64,   // TYPE_UINT64
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT32,    // TYPE_INT32
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_UINT64,   // TYPE_FIXED64
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_UINT32,   // TYPE_FIXED32
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_BOOL,     // TYPE_BOOL
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_STRING,   // TYPE_STRING
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_MESSAGE,  // TYPE_GROUP
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_MESSAGE,  // TYPE_MESSAGE
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_STRING,   // TYPE_BYTES
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_UINT32,   // TYPE_UINT32
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_ENUM,     // TYPE_ENUM
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT32,    // TYPE_SFIXED32
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT64,    // TYPE_SFIXED64
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT32,    // TYPE_SINT32
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CPPTYPE_INT64,    // TYPE_SINT64
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "ERROR",     // 0 is reserved for errors
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "double",    // TYPE_DOUBLE
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "float",     // TYPE_FLOAT
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "int64",     // TYPE_INT64
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "uint64",    // TYPE_UINT64
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "int32",     // TYPE_INT32
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "fixed64",   // TYPE_FIXED64
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "fixed32",   // TYPE_FIXED32
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "bool",      // TYPE_BOOL
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "string",    // TYPE_STRING
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "group",     // TYPE_GROUP
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "message",   // TYPE_MESSAGE
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "bytes",     // TYPE_BYTES
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "uint32",    // TYPE_UINT32
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "enum",      // TYPE_ENUM
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "sfixed32",  // TYPE_SFIXED32
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "sfixed64",  // TYPE_SFIXED64
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "sint32",    // TYPE_SINT32
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "sint64",    // TYPE_SINT64
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "ERROR",     // 0 is reserved for errors
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "int32",     // CPPTYPE_INT32
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "int64",     // CPPTYPE_INT64
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "uint32",    // CPPTYPE_UINT32
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "uint64",    // CPPTYPE_UINT64
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "double",    // CPPTYPE_DOUBLE
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "float",     // CPPTYPE_FLOAT
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "bool",      // CPPTYPE_BOOL
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "enum",      // CPPTYPE_ENUM
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "string",    // CPPTYPE_STRING
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  "message",   // CPPTYPE_MESSAGE
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "ERROR",     // 0 is reserved for errors
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "optional",  // LABEL_OPTIONAL
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "required",  // LABEL_REQUIRED
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "repeated",  // LABEL_REPEATED
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _MSC_VER  // MSVC doesn't need these and won't even accept them.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int FieldDescriptor::kMaxNumber;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int FieldDescriptor::kFirstReservedNumber;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int FieldDescriptor::kLastReservedNumber;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ToCamelCase(const string& input) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool capitalize_next = false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string result;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.reserve(input.size());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < input.size(); i++) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (input[i] == '_') {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capitalize_next = true;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (capitalize_next) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note:  I distrust ctype.h due to locales.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ('a' <= input[i] && input[i] <= 'z') {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.push_back(input[i] - 'a' + 'A');
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.push_back(input[i]);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capitalize_next = false;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.push_back(input[i]);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lower-case the first letter.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result[0] = result[0] - 'A' + 'a';
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A DescriptorPool contains a bunch of hash_maps to implement the
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various Find*By*() methods.  Since hashtable lookups are O(1), it's
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// most efficient to construct a fixed set of large hash_maps used by
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all objects in the pool rather than construct one or more small
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hash_maps for each object.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The keys to these hash_maps are (parent, name) or (parent, number)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pairs.  Unfortunately STL doesn't provide hash functions for pair<>,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so we must invent our own.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kenton):  Use StringPiece rather than const char* in keys?  It would
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   be a lot cleaner but we'd just have to convert it back to const char*
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   for the open source release.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef pair<const void*, const char*> PointerStringPair;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PointerStringPairEqual {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator()(const PointerStringPair& a,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const PointerStringPair& b) const {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a.first == b.first && strcmp(a.second, b.second) == 0;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename PairType>
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PointerIntegerPairHash {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t operator()(const PairType& p) const {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FIXME(kenton):  What is the best way to compute this hash?  I have
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no idea!  This seems a bit better than an XOR.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used only by MSVC and platforms where hash_map is not available.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t bucket_size = 4;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t min_buckets = 8;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator()(const PairType& a, const PairType& b) const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a.first < b.first ||
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (a.first == b.first && a.second < b.second);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef pair<const Descriptor*, int> DescriptorIntPair;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef pair<const EnumDescriptor*, int> EnumIntPair;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PointerStringPairHash {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t operator()(const PointerStringPair& p) const {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FIXME(kenton):  What is the best way to compute this hash?  I have
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no idea!  This seems a bit better than an XOR.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash<const char*> cstring_hash;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) +
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cstring_hash(p.second);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used only by MSVC and platforms where hash_map is not available.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t bucket_size = 4;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t min_buckets = 8;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator()(const PointerStringPair& a,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const PointerStringPair& b) const {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (a.first < b.first) return true;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (a.first > b.first) return false;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return strcmp(a.second, b.second) < 0;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Symbol {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Type {
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PACKAGE
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type type;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* descriptor;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field_descriptor;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumDescriptor* enum_descriptor;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumValueDescriptor* enum_value_descriptor;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceDescriptor* service_descriptor;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MethodDescriptor* method_descriptor;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptor* package_file_descriptor;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool IsNull() const { return type == NULL_SYMBOL; }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool IsType() const {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type == MESSAGE || type == ENUM;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool IsAggregate() const {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type == MESSAGE || type == PACKAGE
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        || type == ENUM || type == SERVICE;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD)  \
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline explicit Symbol(const TYPE* value) {    \
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type = TYPE_CONSTANT;                        \
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->FIELD = value;                         \
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(Descriptor         , MESSAGE   , descriptor             )
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(FieldDescriptor    , FIELD     , field_descriptor       )
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(EnumDescriptor     , ENUM      , enum_descriptor        )
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor  )
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(ServiceDescriptor  , SERVICE   , service_descriptor     )
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(MethodDescriptor   , METHOD    , method_descriptor      )
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONSTRUCTOR(FileDescriptor     , PACKAGE   , package_file_descriptor)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef CONSTRUCTOR
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* GetFile() const {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NULL_SYMBOL: return NULL;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case MESSAGE    : return descriptor           ->file();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FIELD      : return field_descriptor     ->file();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ENUM       : return enum_descriptor      ->file();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ENUM_VALUE : return enum_value_descriptor->type()->file();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SERVICE    : return service_descriptor   ->file();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case METHOD     : return method_descriptor    ->service()->file();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PACKAGE    : return package_file_descriptor;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Symbol kNullSymbol;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<const char*, Symbol,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 hash<const char*>, streq>
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SymbolsByNameMap;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<PointerStringPair, Symbol,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PointerStringPairHash, PointerStringPairEqual>
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SymbolsByParentMap;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<const char*, const FileDescriptor*,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 hash<const char*>, streq>
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilesByNameMap;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<PointerStringPair, const FieldDescriptor*,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PointerStringPairHash, PointerStringPairEqual>
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldsByNameMap;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PointerIntegerPairHash<DescriptorIntPair> >
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldsByNumberMap;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PointerIntegerPairHash<EnumIntPair> >
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumValuesByNumberMap;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a map rather than a hash_map, since we use it to iterate
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through all the extensions that extend a given Descriptor, and an
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ordered data structure that implements lower_bound is convenient
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for that.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef map<DescriptorIntPair, const FieldDescriptor*>
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionsGroupedByDescriptorMap;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool::Tables
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DescriptorPool::Tables {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tables();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Tables();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Record the current state of the tables to the stack of checkpoints.
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Each call to AddCheckpoint() must be paired with exactly one call to either
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // This is used when building files, since some kinds of validation errors
333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // cannot be detected until the file's descriptors have already been added to
334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the tables.
335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // This supports recursive checkpoints, since building a file may trigger
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // recursive building of other files. Note that recursive checkpoints are not
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // normally necessary; explicit dependencies are built prior to checkpointing.
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // So although we recursively build transitive imports, there is at most one
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // checkpoint in the stack during dependency building.
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Recursive checkpoints only arise during cross-linking of the descriptors.
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // friends. If the pending file references an unknown symbol
345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // (e.g., it is not defined in the pending file's explicit dependencies), and
346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the pool is using a fallback database, and that database contains a file
347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // defining that symbol, and that file has not yet been built by the pool,
348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the pool builds the file during cross-linking, leading to another
349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // checkpoint.
350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void AddCheckpoint();
351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Mark the last checkpoint as having cleared successfully, removing it from
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the stack. If the stack is empty, all pending symbols will be committed.
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Note that this does not guarantee that the symbols added since the last
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // everything past that point gets rolled back, including symbols added after
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // checkpoints that were pushed onto the stack after it and marked as cleared.
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void ClearLastCheckpoint();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Roll back the Tables to the state of the checkpoint at the top of the
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // stack, removing everything that was added after that point.
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void RollbackToLastCheckpoint();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The stack of files which are currently being built.  Used to detect
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cyclic dependencies when loading files from a DescriptorDatabase.  Not
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used when fallback_database_ == NULL.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<string> pending_files_;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A set of files which we have tried to load from the fallback database
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and encountered errors.  We will not attempt to load them again.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not used when fallback_database_ == NULL.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hash_set<string> known_bad_files_;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of descriptors for which we've already loaded the full
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set of extensions numbers from fallback_database_.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hash_set<const Descriptor*> extensions_loaded_from_db_;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finding items.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if not found.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Symbol FindSymbol(const string& key) const;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This implements the body of DescriptorPool::Find*ByName().  It should
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // really be a private method of DescriptorPool, but that would require
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // declaring Symbol in descriptor.h, which would drag all kinds of other
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stuff into the header.  Yay C++.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol FindByNameHelper(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorPool* pool, const string& name) const;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These return NULL if not found.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const FileDescriptor* FindFile(const string& key) const;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int number);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void FindAllExtensions(const Descriptor* extendee,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                vector<const FieldDescriptor*>* out) const;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adding items.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These add items to the corresponding tables.  They return false if
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the key already exists in the table.  For AddSymbol(), the string passed
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in must be one that was constructed using AllocateString(), as it will
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be used as a key in the symbols_by_name_ map without copying.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddSymbol(const string& full_name, Symbol symbol);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddFile(const FileDescriptor* file);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddExtension(const FieldDescriptor* field);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocating memory.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate an object which will be reclaimed when the pool is
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destroyed.  Note that the object's destructor will never be called,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so its fields must be plain old data (primitive data types and
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pointers).  All of the descriptor types are such objects.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename Type> Type* Allocate();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate an array of objects which will be reclaimed when the
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pool in destroyed.  Again, destructors are never called.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename Type> Type* AllocateArray(int count);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a string which will be destroyed when the pool is destroyed.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The string is initialized to the given value for convenience.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* AllocateString(const string& value);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a protocol message object.  Some older versions of GCC have
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // trouble understanding explicit template instantiations in some cases, so
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in those cases we have to pass a dummy pointer of the right type as the
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parameter instead of specifying the type explicitly.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename Type> Type* AllocateMessage(Type* dummy = NULL);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a FileDescriptorTables object.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorTables* AllocateFileTables();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<string*> strings_;    // All strings in the pool.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<Message*> messages_;  // All messages in the pool.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<FileDescriptorTables*> file_tables_;  // All file tables in the pool.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<void*> allocations_;  // All other memory allocated in the pool.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SymbolsByNameMap      symbols_by_name_;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilesByNameMap        files_by_name_;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionsGroupedByDescriptorMap extensions_;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  struct CheckPoint {
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    explicit CheckPoint(const Tables* tables)
449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : strings_before_checkpoint(tables->strings_.size()),
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        messages_before_checkpoint(tables->messages_.size()),
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        file_tables_before_checkpoint(tables->file_tables_.size()),
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        allocations_before_checkpoint(tables->allocations_.size()),
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        pending_symbols_before_checkpoint(
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            tables->symbols_after_checkpoint_.size()),
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        pending_files_before_checkpoint(
456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            tables->files_after_checkpoint_.size()),
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        pending_extensions_before_checkpoint(
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            tables->extensions_after_checkpoint_.size()) {
459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int strings_before_checkpoint;
461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int messages_before_checkpoint;
462ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int file_tables_before_checkpoint;
463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int allocations_before_checkpoint;
464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int pending_symbols_before_checkpoint;
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int pending_files_before_checkpoint;
466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int pending_extensions_before_checkpoint;
467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<CheckPoint> checkpoints_;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const char*      > symbols_after_checkpoint_;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const char*      > files_after_checkpoint_;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<DescriptorIntPair> extensions_after_checkpoint_;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate some bytes which will be reclaimed when the pool is
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destroyed.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* AllocateBytes(int size);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains tables specific to a particular file.  These tables are not
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modified once the file has been constructed, so they need not be
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// protected by a mutex.  This makes operations that depend only on the
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contents of a single file -- e.g. Descriptor::FindFieldByName() --
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lock-free.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For historical reasons, the definitions of the methods of
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These used to be a single class.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FileDescriptorTables {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorTables();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~FileDescriptorTables();
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Empty table, used with placeholder files.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const FileDescriptorTables kEmpty;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finding items.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find symbols.  These return a null Symbol (symbol.IsNull() is true)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if not found.
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Symbol FindNestedSymbol(const void* parent,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const string& name) const;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Symbol FindNestedSymbolOfType(const void* parent,
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const string& name,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const Symbol::Type type) const;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These return NULL if not found.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const FieldDescriptor* FindFieldByNumber(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* parent, int number) const;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const FieldDescriptor* FindFieldByLowercaseName(
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& lowercase_name) const;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const FieldDescriptor* FindFieldByCamelcaseName(
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& camelcase_name) const;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const EnumValueDescriptor* FindEnumValueByNumber(
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumDescriptor* parent, int number) const;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adding items.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These add items to the corresponding tables.  They return false if
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the key already exists in the table.  For AddAliasUnderParent(), the
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string passed in must be one that was constructed using AllocateString(),
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as it will be used as a key in the symbols_by_parent_ map without copying.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddAliasUnderParent(const void* parent, const string& name,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Symbol symbol);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddFieldByNumber(const FieldDescriptor* field);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddEnumValueByNumber(const EnumValueDescriptor* value);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds the field to the lowercase_name and camelcase_name maps.  Never
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fails because we allow duplicates; the first field by the name wins.
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddFieldByStylizedNames(const FieldDescriptor* field);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SymbolsByParentMap    symbols_by_parent_;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldsByNameMap       fields_by_lowercase_name_;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldsByNameMap       fields_by_camelcase_name_;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldsByNumberMap     fields_by_number_;       // Not including extensions.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumValuesByNumberMap enum_values_by_number_;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::Tables::Tables()
541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Start some hash_map and hash_set objects with a small # of buckets
542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : known_bad_files_(3),
543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      extensions_loaded_from_db_(3),
544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      symbols_by_name_(3),
545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      files_by_name_(3) {}
546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::Tables::~Tables() {
549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GOOGLE_DCHECK(checkpoints_.empty());
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the deletion order is important, since the destructors of some
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // messages may refer to objects in allocations_.
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&messages_);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < allocations_.size(); i++) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(allocations_[i]);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&strings_);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&file_tables_);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileDescriptorTables::FileDescriptorTables()
561ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Initialize all the hash tables to start out with a small # of buckets
562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : symbols_by_parent_(3),
563ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      fields_by_lowercase_name_(3),
564ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      fields_by_camelcase_name_(3),
565ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      fields_by_number_(3),
566ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      enum_values_by_number_(3) {
567ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
568ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptorTables::~FileDescriptorTables() {}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptorTables FileDescriptorTables::kEmpty;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DescriptorPool::Tables::AddCheckpoint() {
574ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  checkpoints_.push_back(CheckPoint(this));
575ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
577ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DescriptorPool::Tables::ClearLastCheckpoint() {
578ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GOOGLE_DCHECK(!checkpoints_.empty());
579ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  checkpoints_.pop_back();
580ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (checkpoints_.empty()) {
581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // All checkpoints have been cleared: we can now commit all of the pending
582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // data.
583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    symbols_after_checkpoint_.clear();
584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    files_after_checkpoint_.clear();
585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    extensions_after_checkpoint_.clear();
586ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
589ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DescriptorPool::Tables::RollbackToLastCheckpoint() {
590ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GOOGLE_DCHECK(!checkpoints_.empty());
591ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const CheckPoint& checkpoint = checkpoints_.back();
592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = checkpoint.pending_symbols_before_checkpoint;
594ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i < symbols_after_checkpoint_.size();
595ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i++) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    symbols_by_name_.erase(symbols_after_checkpoint_[i]);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
598ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = checkpoint.pending_files_before_checkpoint;
599ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i < files_after_checkpoint_.size();
600ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i++) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    files_by_name_.erase(files_after_checkpoint_[i]);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
603ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = checkpoint.pending_extensions_before_checkpoint;
604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i < extensions_after_checkpoint_.size();
605ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i++) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions_.erase(extensions_after_checkpoint_[i]);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
609ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  symbols_after_checkpoint_.resize(
610ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      checkpoint.pending_symbols_before_checkpoint);
611ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
612ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  extensions_after_checkpoint_.resize(
613ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      checkpoint.pending_extensions_before_checkpoint);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(
616ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(
618ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      messages_.begin() + checkpoint.messages_before_checkpoint,
619ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      messages_.end());
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(
621ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
622ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      file_tables_.end());
623ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = checkpoint.allocations_before_checkpoint;
624ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i < allocations_.size();
625ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       i++) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(allocations_[i]);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
629ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  strings_.resize(checkpoint.strings_before_checkpoint);
630ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  messages_.resize(checkpoint.messages_before_checkpoint);
631ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  file_tables_.resize(checkpoint.file_tables_before_checkpoint);
632ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  allocations_.resize(checkpoint.allocations_before_checkpoint);
633ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  checkpoints_.pop_back();
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kNullSymbol;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *result;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Symbol FileDescriptorTables::FindNestedSymbol(
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& name) const {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Symbol* result =
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str()));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kNullSymbol;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *result;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& name, const Symbol::Type type) const {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = FindNestedSymbol(parent, name);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.type != type) return kNullSymbol;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol DescriptorPool::Tables::FindByNameHelper(
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorPool* pool, const string& name) const {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(pool->mutex_);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = FindSymbol(name);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.IsNull() && pool->underlay_ != NULL) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Symbol not found; check the underlay.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result =
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.IsNull()) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Symbol still not found, so check fallback database.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pool->TryFindSymbolInFallbackDatabase(name)) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = FindSymbol(name);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const FileDescriptor* DescriptorPool::Tables::FindFile(
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& key) const {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(files_by_name_, key.c_str());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* parent, int number) const {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& lowercase_name) const {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(fields_by_lowercase_name_,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       PointerStringPair(parent, lowercase_name.c_str()));
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& camelcase_name) const {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(fields_by_camelcase_name_,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       PointerStringPair(parent, camelcase_name.c_str()));
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumDescriptor* parent, int number) const {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* extendee, int number) {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindPtrOrNull(extensions_, make_pair(extendee, number));
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void DescriptorPool::Tables::FindAllExtensions(
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionsGroupedByDescriptorMap::const_iterator it =
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions_.lower_bound(make_pair(extendee, 0));
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; it != extensions_.end() && it->first.first == extendee; ++it) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->push_back(it->second);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::Tables::AddSymbol(
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& full_name, Symbol symbol) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    symbols_after_checkpoint_.push_back(full_name.c_str());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileDescriptorTables::AddAliasUnderParent(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* parent, const string& name, Symbol symbol) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointerStringPair by_parent_key(parent, name.c_str());
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    files_after_checkpoint_.push_back(file->name().c_str());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FileDescriptorTables::AddFieldByStylizedNames(
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* parent;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->is_extension()) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->extension_scope() == NULL) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent = field->file();
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent = field->extension_scope();
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = field->containing_type();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorIntPair key(field->containing_type(), field->number());
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InsertIfNotPresent(&fields_by_number_, key, field);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileDescriptorTables::AddEnumValueByNumber(
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumValueDescriptor* value) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumIntPair key(value->type(), value->number());
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InsertIfNotPresent(&enum_values_by_number_, key, value);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorIntPair key(field->containing_type(), field->number());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (InsertIfNotPresent(&extensions_, key, field)) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions_after_checkpoint_.push_back(key);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Type* DescriptorPool::Tables::Allocate() {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type)));
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Type* DescriptorPool::Tables::AllocateArray(int count) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string* DescriptorPool::Tables::AllocateString(const string& value) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* result = new string(value);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings_.push_back(result);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type* result = new Type;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  messages_.push_back(result);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorTables* result = new FileDescriptorTables;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_tables_.push_back(result);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* DescriptorPool::Tables::AllocateBytes(int size) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  Would it be worthwhile to implement this in some more
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sophisticated way?  Probably not for the open source release, but for
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // internal use we could easily plug in one of our existing memory pool
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allocators...
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0) return NULL;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result = operator new(size);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allocations_.push_back(result);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::ErrorCollector::~ErrorCollector() {}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::DescriptorPool()
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : mutex_(NULL),
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fallback_database_(NULL),
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_error_collector_(NULL),
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_(NULL),
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_(new Tables),
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enforce_dependencies_(true),
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_unknown_(false) {}
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ErrorCollector* error_collector)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : mutex_(new Mutex),
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fallback_database_(fallback_database),
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_error_collector_(error_collector),
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_(NULL),
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_(new Tables),
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enforce_dependencies_(true),
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_unknown_(false) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : mutex_(NULL),
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fallback_database_(NULL),
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_error_collector_(NULL),
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_(underlay),
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_(new Tables),
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enforce_dependencies_(true),
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_unknown_(false) {}
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool::~DescriptorPool() {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mutex_ != NULL) delete mutex_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool::BuildFile() defined later.
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool::BuildFileCollectingErrors() defined later.
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorPool::InternalDontEnforceDependencies() {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enforce_dependencies_ = false;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(mutex_);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tables_->FindFile(filename) != NULL;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generated_pool ====================================================
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EncodedDescriptorDatabase* generated_database_ = NULL;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool* generated_pool_ = NULL;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteGeneratedPool() {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete generated_database_;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generated_database_ = NULL;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete generated_pool_;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generated_pool_ = NULL;
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
904ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic void InitGeneratedPool() {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generated_database_ = new EncodedDescriptorDatabase;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generated_pool_ = new DescriptorPool(generated_database_);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::OnShutdown(&DeleteGeneratedPool);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void InitGeneratedPoolOnce() {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const DescriptorPool* DescriptorPool::generated_pool() {
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitGeneratedPoolOnce();
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generated_pool_;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorPool* DescriptorPool::internal_generated_pool() {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitGeneratedPoolOnce();
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generated_pool_;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorPool::InternalAddGeneratedFile(
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* encoded_file_descriptor, int size) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // So, this function is called in the process of initializing the
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptors for generated proto classes.  Each generated .pb.cc file
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has an internal procedure called AddDescriptors() which is called at
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process startup, and that function calls this one in order to register
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the raw bytes of the FileDescriptorProto representing the file.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not actually construct the descriptor objects right away.  We just
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hang on to the bytes until they are actually needed.  We actually construct
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the descriptor the first time one of the following things happens:
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // * Someone calls a method like descriptor(), GetDescriptor(), or
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   GetReflection() on the generated types, which requires returning the
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   descriptor or an object based on it.
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // * Someone looks up the descriptor in DescriptorPool::generated_pool().
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once one of these happens, the DescriptorPool actually parses the
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FileDescriptorProto and generates a FileDescriptor (and all its children)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // based on it.
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that FileDescriptorProto is itself a generated protocol message.
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Therefore, when we parse one, we have to be very careful to avoid using
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any descriptor-based operations, since this might cause infinite recursion
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or deadlock.
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitGeneratedPoolOnce();
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Find*By* methods ==================================================
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   there's any good way to factor it out.  Think about this some time when
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   there's nothing more important to do (read: never).
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(mutex_);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* result = tables_->FindFile(name);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) return result;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (underlay_ != NULL) {
967ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = underlay_->FindFileByName(name);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != NULL) return result;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (TryFindFileInFallbackDatabase(name)) {
971ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = tables_->FindFile(name);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != NULL) return result;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& symbol_name) const {
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(mutex_);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindSymbol(symbol_name);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) return result.GetFile();
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (underlay_ != NULL) {
983ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FileDescriptor* file_result =
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      underlay_->FindFileContainingSymbol(symbol_name);
985ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (file_result != NULL) return file_result;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (TryFindSymbolInFallbackDatabase(symbol_name)) {
988ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = tables_->FindSymbol(symbol_name);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.IsNull()) return result.GetFile();
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Descriptor* DescriptorPool::FindMessageTypeByName(
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor* DescriptorPool::FindFieldByName(
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.type == Symbol::FIELD &&
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !result.field_descriptor->is_extension()) {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.field_descriptor;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor* DescriptorPool::FindExtensionByName(
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.type == Symbol::FIELD &&
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.field_descriptor->is_extension()) {
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.field_descriptor;
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.type == Symbol::ENUM_VALUE) ?
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.enum_value_descriptor : NULL;
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ServiceDescriptor* DescriptorPool::FindServiceByName(
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MethodDescriptor* DescriptorPool::FindMethodByName(
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) const {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindByNameHelper(this, name);
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* extendee, int number) const {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(mutex_);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (underlay_ != NULL) {
1055ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = underlay_->FindExtensionByNumber(extendee, number);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != NULL) return result;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (TryFindExtensionInFallbackDatabase(extendee, number)) {
1059ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = tables_->FindExtension(extendee, number);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != NULL) {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorPool::FindAllExtensions(
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLockMaybe lock(mutex_);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize tables_->extensions_ from the fallback database first
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (but do this only once per descriptor).
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fallback_database_ != NULL &&
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tables_->extensions_loaded_from_db_.count(extendee) == 0) {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vector<int> numbers;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    &numbers)) {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < numbers.size(); ++i) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int number = numbers[i];
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tables_->FindExtension(extendee, number) == NULL) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TryFindExtensionInFallbackDatabase(extendee, number);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tables_->extensions_loaded_from_db_.insert(extendee);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tables_->FindAllExtensions(extendee, out);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (underlay_ != NULL) {
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underlay_->FindAllExtensions(extendee, out);
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindFieldByNumber(int key) const {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result =
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindFieldByNumber(this, key);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || result->is_extension()) {
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindFieldByLowercaseName(const string& key) const {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result =
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindFieldByLowercaseName(this, key);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || result->is_extension()) {
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindFieldByCamelcaseName(const string& key) const {
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result =
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindFieldByCamelcaseName(this, key);
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || result->is_extension()) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindFieldByName(const string& key) const {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull() && !result.field_descriptor->is_extension()) {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.field_descriptor;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindExtensionByName(const string& key) const {
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull() && result.field_descriptor->is_extension()) {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.field_descriptor;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindExtensionByLowercaseName(const string& key) const {
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result =
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindFieldByLowercaseName(this, key);
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || !result->is_extension()) {
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindExtensionByCamelcaseName(const string& key) const {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result =
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindFieldByCamelcaseName(this, key);
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || !result->is_extension()) {
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Descriptor*
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindNestedTypeByName(const string& key) const {
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.descriptor;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumDescriptor*
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindEnumTypeByName(const string& key) const {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.enum_descriptor;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumValueDescriptor*
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor::FindEnumValueByName(const string& key) const {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.enum_value_descriptor;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumValueDescriptor*
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumDescriptor::FindValueByName(const string& key) const {
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.enum_value_descriptor;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumValueDescriptor*
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumDescriptor::FindValueByNumber(int key) const {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file()->tables_->FindEnumValueByNumber(this, key);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MethodDescriptor*
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceDescriptor::FindMethodByName(const string& key) const {
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.method_descriptor;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Descriptor*
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindMessageTypeByName(const string& key) const {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.descriptor;
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumDescriptor*
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindEnumTypeByName(const string& key) const {
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.enum_descriptor;
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const EnumValueDescriptor*
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindEnumValueByName(const string& key) const {
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result =
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.enum_value_descriptor;
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ServiceDescriptor*
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindServiceByName(const string& key) const {
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull()) {
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.service_descriptor;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindExtensionByName(const string& key) const {
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.IsNull() && result.field_descriptor->is_extension()) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result.field_descriptor;
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || !result->is_extension()) {
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor*
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileDescriptor::FindExtensionByCamelcaseName(const string& key) const {
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL || !result->is_extension()) {
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Descriptor::IsExtensionNumber(int number) const {
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Linear search should be fine because we don't expect a message to have
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // more than a couple extension ranges.
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_range_count(); i++) {
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (number >= extension_range(i)->start &&
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        number <  extension_range(i)->end) {
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fallback_database_ == NULL) return false;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tables_->known_bad_files_.count(name) > 0) return false;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorProto file_proto;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fallback_database_->FindFileByName(name, &file_proto) ||
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BuildFileFromDatabase(file_proto) == NULL) {
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->known_bad_files_.insert(name);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
1334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string prefix = name;
1335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (;;) {
1336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string::size_type dot_pos = prefix.find_last_of('.');
1337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (dot_pos == string::npos) {
1338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      break;
1339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    prefix = prefix.substr(0, dot_pos);
1341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Symbol symbol = tables_->FindSymbol(prefix);
1342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If the symbol type is anything other than PACKAGE, then its complete
1343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // definition is already known.
1344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
1345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
1346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (underlay_ != NULL) {
1349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Check to see if any prefix of this symbol exists in the underlay.
1350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return underlay_->IsSubSymbolOfBuiltType(name);
1351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return false;
1353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fallback_database_ == NULL) return false;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We skip looking in the fallback database if the name is a sub-symbol of
1359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // any descriptor that already exists in the descriptor pool (except for
1360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // package descriptors).  This is valid because all symbols except for
1361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // packages are defined in a single file, so if the symbol exists then we
1362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // should already have its definition.
1363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
1364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The other reason to do this is to support "overriding" type definitions
1365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // by merging two databases that define the same type.  (Yes, people do
1366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // this.)  The main difficulty with making this work is that
1367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // FindFileContainingSymbol() is allowed to return both false positives
1368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
1369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).  When two
1370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // such databases are merged, looking up a non-existent sub-symbol of a type
1371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // that already exists in the descriptor pool can result in an attempt to
1372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // load multiple definitions of the same type.  The check below avoids this.
1373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (IsSubSymbolOfBuiltType(name)) return false;
1374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorProto file_proto;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) {
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tables_->FindFile(file_proto.name()) != NULL) {
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've already loaded this file, and it apparently doesn't contain the
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // symbol we're looking for.  Some DescriptorDatabases return false
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // positives.
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BuildFileFromDatabase(file_proto) == NULL) {
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorPool::TryFindExtensionInFallbackDatabase(
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* containing_type, int field_number) const {
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fallback_database_ == NULL) return false;
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorProto file_proto;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fallback_database_->FindFileContainingExtension(
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        containing_type->full_name(), field_number, &file_proto)) {
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tables_->FindFile(file_proto.name()) != NULL) {
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've already loaded this file, and it apparently doesn't contain the
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension we're looking for.  Some DescriptorDatabases return false
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // positives.
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BuildFileFromDatabase(file_proto) == NULL) {
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(has_default_value()) << "No default value";
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cpp_type()) {
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_INT32:
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(default_value_int32());
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_INT64:
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(default_value_int64());
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_UINT32:
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(default_value_uint32());
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_UINT64:
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleItoa(default_value_uint64());
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_FLOAT:
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleFtoa(default_value_float());
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_DOUBLE:
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SimpleDtoa(default_value_double());
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_BOOL:
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return default_value_bool() ? "true" : "false";
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_STRING:
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (quote_string_type) {
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "\"" + CEscape(default_value_string()) + "\"";
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (type() == TYPE_BYTES) {
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return CEscape(default_value_string());
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return default_value_string();
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_ENUM:
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return default_value_enum()->name();
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CPPTYPE_MESSAGE:
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string";
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CopyTo methods ====================================================
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!package().empty()) proto->set_package(package());
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < dependency_count(); i++) {
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->add_dependency(dependency(i)->name());
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < public_dependency_count(); i++) {
1477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    proto->add_public_dependency(public_dependencies_[i]);
1478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1480ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < weak_dependency_count(); i++) {
1481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    proto->add_weak_dependency(weak_dependencies_[i]);
1482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message_type_count(); i++) {
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_type(i)->CopyTo(proto->add_message_type());
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_type_count(); i++) {
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_type(i)->CopyTo(proto->add_enum_type());
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < service_count(); i++) {
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service(i)->CopyTo(proto->add_service());
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension(i)->CopyTo(proto->add_extension());
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &FileOptions::default_instance()) {
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
1503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (source_code_info_ != &SourceCodeInfo::default_instance()) {
1504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
1505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Descriptor::CopyTo(DescriptorProto* proto) const {
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < field_count(); i++) {
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field(i)->CopyTo(proto->add_field());
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < nested_type_count(); i++) {
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_type(i)->CopyTo(proto->add_nested_type());
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_type_count(); i++) {
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_type(i)->CopyTo(proto->add_enum_type());
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_range_count(); i++) {
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorProto::ExtensionRange* range = proto->add_extension_range();
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range->set_start(extension_range(i)->start);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range->set_end(extension_range(i)->end);
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension(i)->CopyTo(proto->add_extension());
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &MessageOptions::default_instance()) {
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_number(number());
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some compilers do not allow static_cast directly between two enum types,
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we must cast to int first.
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_label(static_cast<FieldDescriptorProto::Label>(
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     implicit_cast<int>(label())));
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_type(static_cast<FieldDescriptorProto::Type>(
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    implicit_cast<int>(type())));
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_extension()) {
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!containing_type()->is_unqualified_placeholder_) {
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proto->set_extendee(".");
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_extendee()->append(containing_type()->full_name());
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cpp_type() == CPPTYPE_MESSAGE) {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message_type()->is_placeholder_) {
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't actually know if the type is a message type.  It could be
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // an enum.
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proto->clear_type();
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!message_type()->is_unqualified_placeholder_) {
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proto->set_type_name(".");
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_type_name()->append(message_type()->full_name());
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (cpp_type() == CPPTYPE_ENUM) {
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!enum_type()->is_unqualified_placeholder_) {
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proto->set_type_name(".");
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_type_name()->append(enum_type()->full_name());
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_default_value()) {
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->set_default_value(DefaultValueAsString(false));
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &FieldOptions::default_instance()) {
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < value_count(); i++) {
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value(i)->CopyTo(proto->add_value());
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &EnumOptions::default_instance()) {
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_number(number());
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &EnumValueOptions::default_instance()) {
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < method_count(); i++) {
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method(i)->CopyTo(proto->add_method());
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &ServiceOptions::default_instance()) {
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->set_name(name());
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!input_type()->is_unqualified_placeholder_) {
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->set_input_type(".");
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->mutable_input_type()->append(input_type()->full_name());
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!output_type()->is_unqualified_placeholder_) {
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->set_output_type(".");
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proto->mutable_output_type()->append(output_type()->full_name());
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&options() != &MethodOptions::default_instance()) {
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proto->mutable_options()->CopyFrom(options());
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DebugString methods ===============================================
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used by each of the option formatters.
1635ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool RetrieveOptions(int depth,
1636ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const Message &options,
1637ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     vector<string> *option_entries) {
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  option_entries->clear();
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Reflection* reflection = options.GetReflection();
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> fields;
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reflection->ListFields(options, &fields);
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < fields.size(); i++) {
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int count = 1;
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool repeated = false;
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fields[i]->is_repeated()) {
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = reflection->FieldSize(options, fields[i]);
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      repeated = true;
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < count; j++) {
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string fieldval;
1651ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1652ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        string tmp;
1653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        TextFormat::Printer printer;
1654ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        printer.SetInitialIndentLevel(depth + 1);
1655ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        printer.PrintFieldValueToString(options, fields[i],
1656ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        repeated ? j : -1, &tmp);
1657ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        fieldval.append("{\n");
1658ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        fieldval.append(tmp);
1659ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        fieldval.append(depth * 2, ' ');
1660ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        fieldval.append("}");
1661ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
1662ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        TextFormat::PrintFieldValueToString(options, fields[i],
1663ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            repeated ? j : -1, &fieldval);
1664ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
1665ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      string name;
1666ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (fields[i]->is_extension()) {
1667ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        name = "(." + fields[i]->full_name() + ")";
1668ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
1669ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        name = fields[i]->name();
1670ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
1671ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      option_entries->push_back(name + " = " + fieldval);
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !option_entries->empty();
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Formats options that all appear together in brackets. Does not include
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// brackets.
1679ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool FormatBracketedOptions(int depth, const Message &options, string *output) {
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<string> all_options;
1681ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (RetrieveOptions(depth, options, &all_options)) {
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(JoinStrings(all_options, ", "));
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !all_options.empty();
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Formats options one per line
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FormatLineOptions(int depth, const Message &options, string *output) {
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<string> all_options;
1691ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (RetrieveOptions(depth, options, &all_options)) {
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < all_options.size(); i++) {
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings::SubstituteAndAppend(output, "$0option $1;\n",
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   prefix, all_options[i]);
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !all_options.empty();
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string FileDescriptor::DebugString() const {
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents = "syntax = \"proto2\";\n\n";
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  set<int> public_dependencies;
1706ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  set<int> weak_dependencies;
1707ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  public_dependencies.insert(public_dependencies_,
1708ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             public_dependencies_ + public_dependency_count_);
1709ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  weak_dependencies.insert(weak_dependencies_,
1710ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                           weak_dependencies_ + weak_dependency_count_);
1711ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < dependency_count(); i++) {
1713ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (public_dependencies.count(i) > 0) {
1714ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
1715ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   dependency(i)->name());
1716ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else if (weak_dependencies.count(i) > 0) {
1717ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
1718ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   dependency(i)->name());
1719ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
1720ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
1721ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   dependency(i)->name());
1722ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!package().empty()) {
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FormatLineOptions(0, options(), &contents)) {
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents.append("\n");  // add some space if we had options
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_type_count(); i++) {
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_type(i)->DebugString(0, &contents);
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents.append("\n");
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find all the 'group' type extensions; we will not output their nested
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // definitions (those will be done with their group field descriptor).
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set<const Descriptor*> groups;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      groups.insert(extension(i)->message_type());
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message_type_count(); i++) {
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (groups.count(message_type(i)) == 0) {
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings::SubstituteAndAppend(&contents, "message $0",
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   message_type(i)->name());
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_type(i)->DebugString(0, &contents);
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contents.append("\n");
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < service_count(); i++) {
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service(i)->DebugString(&contents);
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents.append("\n");
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* containing_type = NULL;
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension(i)->containing_type() != containing_type) {
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > 0) contents.append("}\n\n");
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      containing_type = extension(i)->containing_type();
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   containing_type->full_name());
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension(i)->DebugString(1, &contents);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_count() > 0) contents.append("}\n\n");
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Descriptor::DebugString() const {
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(&contents, "message $0", name());
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(0, &contents);
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Descriptor::DebugString(int depth, string *contents) const {
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++depth;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents->append(" {\n");
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormatLineOptions(depth, options(), contents);
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find all the 'group' types for fields and extensions; we will not output
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // their nested definitions (those will be done with their group field
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor).
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set<const Descriptor*> groups;
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < field_count(); i++) {
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      groups.insert(field(i)->message_type());
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      groups.insert(extension(i)->message_type());
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < nested_type_count(); i++) {
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (groups.count(nested_type(i)) == 0) {
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings::SubstituteAndAppend(contents, "$0  message $1",
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   prefix, nested_type(i)->name());
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nested_type(i)->DebugString(depth, contents);
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_type_count(); i++) {
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_type(i)->DebugString(depth, contents);
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < field_count(); i++) {
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field(i)->DebugString(depth, contents);
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_range_count(); i++) {
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n",
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 prefix,
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 extension_range(i)->start,
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 extension_range(i)->end - 1);
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Group extensions by what they extend, so they can be printed out together.
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* containing_type = NULL;
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extension_count(); i++) {
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension(i)->containing_type() != containing_type) {
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      containing_type = extension(i)->containing_type();
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings::SubstituteAndAppend(contents, "$0  extend .$1 {\n",
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   prefix, containing_type->full_name());
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension(i)->DebugString(depth + 1, contents);
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_count() > 0)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string FieldDescriptor::DebugString() const {
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int depth = 0;
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_extension()) {
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 containing_type()->full_name());
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    depth = 1;
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(depth, &contents);
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_extension()) {
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     contents.append("}\n");
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FieldDescriptor::DebugString(int depth, string *contents) const {
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string field_type;
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type()) {
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_MESSAGE:
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_type = "." + message_type()->full_name();
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_ENUM:
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_type = "." + enum_type()->full_name();
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_type = kTypeToName[type()];
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4",
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               prefix,
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               kLabelToName[label()],
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               field_type,
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               type() == TYPE_GROUP ? message_type()->name() :
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      name(),
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               number());
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool bracketed = false;
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_default_value()) {
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bracketed = true;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(contents, " [default = $0",
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 DefaultValueAsString(true));
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string formatted_options;
1888ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents->append(bracketed ? ", " : " [");
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bracketed = true;
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents->append(formatted_options);
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bracketed) {
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents->append("]");
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type() == TYPE_GROUP) {
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_type()->DebugString(depth, contents);
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents->append(";\n");
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string EnumDescriptor::DebugString() const {
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(0, &contents);
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumDescriptor::DebugString(int depth, string *contents) const {
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++depth;
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0enum $1 {\n",
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               prefix, name());
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormatLineOptions(depth, options(), contents);
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < value_count(); i++) {
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value(i)->DebugString(depth, contents);
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string EnumValueDescriptor::DebugString() const {
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(0, &contents);
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumValueDescriptor::DebugString(int depth, string *contents) const {
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0$1 = $2",
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               prefix, name(), number());
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string formatted_options;
1937ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents->append(";\n");
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ServiceDescriptor::DebugString() const {
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(&contents);
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceDescriptor::DebugString(string *contents) const {
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "service $0 {\n", name());
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormatLineOptions(1, options(), contents);
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < method_count(); i++) {
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method(i)->DebugString(1, contents);
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents->append("}\n");
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string MethodDescriptor::DebugString() const {
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string contents;
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugString(0, &contents);
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contents;
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MethodDescriptor::DebugString(int depth, string *contents) const {
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string prefix(depth * 2, ' ');
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++depth;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strings::SubstituteAndAppend(contents, "$0rpc $1(.$2) returns (.$3)",
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               prefix, name(),
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               input_type()->full_name(),
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               output_type()->full_name());
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string formatted_options;
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FormatLineOptions(depth, options(), &formatted_options)) {
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings::SubstituteAndAppend(contents, " {\n$0$1}\n",
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 formatted_options, prefix);
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contents->append(";\n");
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1983ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1984ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1985ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Location methods ===============================================
1986ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1987ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic bool PathsEqual(const vector<int>& x, const RepeatedField<int32>& y) {
1988ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (x.size() != y.size()) return false;
1989ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < x.size(); ++i) {
1990ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (x[i] != y.Get(i)) return false;
1991ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1992ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
1993ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
1994ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1995ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool FileDescriptor::GetSourceLocation(const vector<int>& path,
1996ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       SourceLocation* out_location) const {
1997ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GOOGLE_CHECK_NOTNULL(out_location);
1998ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const SourceCodeInfo* info = source_code_info_;
1999ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; info && i < info->location_size(); ++i) {
2000ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (PathsEqual(path, info->location(i).path())) {
2001ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const RepeatedField<int32>& span = info->location(i).span();
2002ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (span.size() == 3 || span.size() == 4) {
2003ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->start_line   = span.Get(0);
2004ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->start_column = span.Get(1);
2005ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->end_line     = span.Get(span.size() == 3 ? 0 : 2);
2006ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->end_column   = span.Get(span.size() - 1);
2007ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2008ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->leading_comments = info->location(i).leading_comments();
2009ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        out_location->trailing_comments = info->location(i).trailing_comments();
2010ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return true;
2011ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
2012ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
2013ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
2014ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return false;
2015ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2016ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2017ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool FieldDescriptor::is_packed() const {
2018ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return is_packable() && (options_ != NULL) && options_->packed();
2019ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2020ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2021ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
2022ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2023ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2024ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return file()->GetSourceLocation(path, out_location);
2025ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2026ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2027ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2028ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2029ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2030ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return file()->GetSourceLocation(path, out_location);
2031ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2032ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2033ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2034ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2035ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2036ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return file()->GetSourceLocation(path, out_location);
2037ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2038ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2039ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2040ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2041ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2042ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return service()->file()->GetSourceLocation(path, out_location);
2043ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2044ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2045ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2046ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2047ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2048ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return file()->GetSourceLocation(path, out_location);
2049ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2050ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2051ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool EnumValueDescriptor::GetSourceLocation(
2052ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    SourceLocation* out_location) const {
2053ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<int> path;
2054ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GetLocationPath(&path);
2055ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return type()->file()->GetSourceLocation(path, out_location);
2056ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2057ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2058ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid Descriptor::GetLocationPath(vector<int>* output) const {
2059ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (containing_type()) {
2060ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    containing_type()->GetLocationPath(output);
2061ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
2062ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(index());
2063ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
2064ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
2065ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(index());
2066ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
2067ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2068ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2069ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FieldDescriptor::GetLocationPath(vector<int>* output) const {
2070ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  containing_type()->GetLocationPath(output);
2071ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(DescriptorProto::kFieldFieldNumber);
2072ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(index());
2073ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2074ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2075ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid EnumDescriptor::GetLocationPath(vector<int>* output) const {
2076ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (containing_type()) {
2077ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    containing_type()->GetLocationPath(output);
2078ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
2079ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(index());
2080ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
2081ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
2082ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output->push_back(index());
2083ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
2084ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2085ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2086ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid EnumValueDescriptor::GetLocationPath(vector<int>* output) const {
2087ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  type()->GetLocationPath(output);
2088ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(EnumDescriptorProto::kValueFieldNumber);
2089ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(index());
2090ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2091ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2092ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ServiceDescriptor::GetLocationPath(vector<int>* output) const {
2093ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(FileDescriptorProto::kServiceFieldNumber);
2094ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(index());
2095ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2096ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2097ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid MethodDescriptor::GetLocationPath(vector<int>* output) const {
2098ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  service()->GetLocationPath(output);
2099ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
2100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  output->push_back(index());
2101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Represents an options message to interpret. Extension names in the option
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// name are respolved relative to name_scope. element_name and orig_opt are
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used only for error reporting (since the parser records locations against
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointers in the original options, not the mutable copy). The Message must be
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one of the Options messages in descriptor.proto.
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OptionsToInterpret {
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OptionsToInterpret(const string& ns,
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const string& el,
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const Message* orig_opt,
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     Message* opt)
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : name_scope(ns),
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        element_name(el),
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_options(orig_opt),
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        options(opt) {
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name_scope;
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string element_name;
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Message* original_options;
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Message* options;
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DescriptorBuilder {
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorBuilder(const DescriptorPool* pool,
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    DescriptorPool::Tables* tables,
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    DescriptorPool::ErrorCollector* error_collector);
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DescriptorBuilder();
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class OptionInterpreter;
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DescriptorPool* pool_;
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorPool::Tables* tables_;  // for convenience
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorPool::ErrorCollector* error_collector_;
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As we build descriptors we store copies of the options messages in
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them. We put pointers to those copies in this vector, as we build, so we
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later (after cross-linking) interpret those options.
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<OptionsToInterpret> options_to_interpret_;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_errors_;
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename_;
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor* file_;
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorTables* file_tables_;
2155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  set<const FileDescriptor*> dependencies_;
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If LookupSymbol() finds a symbol that is in a file which is not a declared
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dependency of this file, it will fail, but will set
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // possible_undeclared_dependency_ to point at that file.  This is only used
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by AddNotDefinedError() to report a more useful error message.
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // possible_undeclared_dependency_name_ is the name of the symbol that was
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actually found in possible_undeclared_dependency_, which may be a parent
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the symbol actually looked for.
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* possible_undeclared_dependency_;
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string possible_undeclared_dependency_name_;
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddError(const string& element_name,
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const Message& descriptor,
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                DescriptorPool::ErrorCollector::ErrorLocation location,
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const string& error);
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds an error indicating that undefined_symbol was not defined.  Must
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only be called after LookupSymbol() fails.
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddNotDefinedError(
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& element_name,
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& descriptor,
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorPool::ErrorCollector::ErrorLocation location,
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& undefined_symbol);
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Silly helper which determines if the given file is in the given package.
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // I.e., either file->package() == package_name or file->package() is a
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nested package within package_name.
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsInPackage(const FileDescriptor* file, const string& package_name);
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Helper function which finds all public dependencies of the given file, and
2186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // stores the them in the dependencies_ set in the builder.
2187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void RecordPublicDependencies(const FileDescriptor* file);
2188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like tables_->FindSymbol(), but additionally:
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - Search the pool's underlay if not found in tables_.
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - Insure that the resulting Symbol is from one of the file's declared
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   dependencies.
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol FindSymbol(const string& name);
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like FindSymbol() but does not require that the symbol is in one of the
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file's declared dependencies.
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol FindSymbolNotEnforcingDeps(const string& name);
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // This implements the body of FindSymbolNotEnforcingDeps().
2200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
2201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                          const string& name);
2202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like FindSymbol(), but looks up the name relative to some other symbol
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name.  This first searches siblings of relative_to, then siblings of its
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parents, etc.  For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the following calls, returning the first non-null result:
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the DescriptorPool, this will generate a placeholder type if
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the name is not found (unless the name itself is malformed).  The
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // placeholder_type parameter indicates what kind of placeholder should be
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // constructed in this case.  The resolve_mode parameter determines whether
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any symbol is returned, or only symbols that are types.  Note, however,
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if it believes that's all it could refer to.  The caller should always
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check that it receives the type of symbol it was expecting.
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum PlaceholderType {
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLACEHOLDER_MESSAGE,
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLACEHOLDER_ENUM,
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLACEHOLDER_EXTENDABLE_MESSAGE
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ResolveMode {
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOOKUP_ALL, LOOKUP_TYPES
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol LookupSymbol(const string& name, const string& relative_to,
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      PlaceholderType placeholder_type = PLACEHOLDER_MESSAGE,
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ResolveMode resolve_mode = LOOKUP_ALL);
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like LookupSymbol() but will not return a placeholder even if
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AllowUnknownDependencies() has been used.
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol LookupSymbolNoPlaceholder(const string& name,
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const string& relative_to,
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   ResolveMode resolve_mode = LOOKUP_ALL);
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a placeholder type suitable for return from LookupSymbol().  May
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return kNullSymbol if the name is not a valid type name.
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol NewPlaceholder(const string& name, PlaceholderType placeholder_type);
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a placeholder file.  Never returns NULL.  This is used when an
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // import is not found and AllowUnknownDependencies() is enabled.
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* NewPlaceholderFile(const string& name);
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calls tables_->AddSymbol() and records an error if it fails.  Returns
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true if successful or false if failed, though most callers can ignore
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the return value since an error has already been recorded.
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddSymbol(const string& full_name,
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const void* parent, const string& name,
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Message& proto, Symbol symbol);
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like AddSymbol(), but succeeds if the symbol is already defined as long
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the existing definition is also a package (because it's OK to define
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the same package in two different files).  Also adds all parents of the
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "foo.bar" and "foo" to the table).
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddPackage(const string& name, const Message& proto,
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const FileDescriptor* file);
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks that the symbol name contains only alphanumeric characters and
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underscores.  Records an error otherwise.
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateSymbolName(const string& name, const string& full_name,
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const Message& proto);
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like ValidateSymbolName(), but the name is allowed to contain periods and
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an error is indicated by returning false (not recording the error).
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ValidateQualifiedName(const string& name);
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by BUILD_ARRAY macro (below) to avoid having to have the type
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified as a macro parameter.
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void AllocateArray(int size, Type** output) {
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output = tables_->AllocateArray<Type>(size);
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocates a copy of orig_options in tables_ and stores it in the
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor. Remembers its uninterpreted options, to be interpreted
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // later. DescriptorT must be one of the Descriptor messages from
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor.proto.
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class DescriptorT> void AllocateOptions(
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const typename DescriptorT::OptionsType& orig_options,
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DescriptorT* descriptor);
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Specialization for FileOptions.
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AllocateOptions(const FileOptions& orig_options,
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       FileDescriptor* descriptor);
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation for AllocateOptions(). Don't call this directly.
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class DescriptorT> void AllocateOptionsImpl(
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string& name_scope,
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string& element_name,
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const typename DescriptorT::OptionsType& orig_options,
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DescriptorT* descriptor);
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These methods all have the same signature for the sake of the BUILD_ARRAY
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // macro, below.
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildMessage(const DescriptorProto& proto,
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const Descriptor* parent,
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    Descriptor* result);
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildFieldOrExtension(const FieldDescriptorProto& proto,
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const Descriptor* parent,
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             FieldDescriptor* result,
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             bool is_extension);
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildField(const FieldDescriptorProto& proto,
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const Descriptor* parent,
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  FieldDescriptor* result) {
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildFieldOrExtension(proto, parent, result, false);
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildExtension(const FieldDescriptorProto& proto,
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const Descriptor* parent,
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      FieldDescriptor* result) {
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildFieldOrExtension(proto, parent, result, true);
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const Descriptor* parent,
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Descriptor::ExtensionRange* result);
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildEnum(const EnumDescriptorProto& proto,
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Descriptor* parent,
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 EnumDescriptor* result);
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildEnumValue(const EnumValueDescriptorProto& proto,
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const EnumDescriptor* parent,
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      EnumValueDescriptor* result);
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildService(const ServiceDescriptorProto& proto,
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const void* dummy,
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ServiceDescriptor* result);
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildMethod(const MethodDescriptorProto& proto,
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const ServiceDescriptor* parent,
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   MethodDescriptor* result);
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be run only after building.
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Options will not be available during cross-linking, as they
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have not yet been interpreted. Defer any handling of options to the
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate*Options methods.
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkField(FieldDescriptor* field,
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const FieldDescriptorProto& proto);
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkEnum(EnumDescriptor* enum_type,
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const EnumDescriptorProto& proto);
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const EnumValueDescriptorProto& proto);
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkService(ServiceDescriptor* service,
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const ServiceDescriptorProto& proto);
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CrossLinkMethod(MethodDescriptor* method,
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const MethodDescriptorProto& proto);
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be run only after cross-linking.
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InterpretOptions();
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A helper class for interpreting options.
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class OptionInterpreter {
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates an interpreter that operates in the context of the pool of the
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // specified builder, which must not be NULL. We don't take ownership of the
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // builder.
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit OptionInterpreter(DescriptorBuilder* builder);
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~OptionInterpreter();
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Interprets the uninterpreted options in the specified Options message.
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On error, calls AddError() on the underlying builder and returns false.
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise returns true.
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool InterpretOptions(OptionsToInterpret* options_to_interpret);
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class AggregateOptionFinder;
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Interprets uninterpreted_option_ on the specified message, which
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // must be the mutable copy of the original options message to which
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // uninterpreted_option_ belongs.
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool InterpretSingleOption(Message* options);
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Adds the uninterpreted_option to the given options message verbatim.
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used when AllowUnknownDependencies() is in effect and we can't find
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the option's definition.
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Message* options);
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A recursive helper function that drills into the intermediate fields
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in unknown_fields to check if field innermost_field is set on the
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // innermost message. Returns false and sets an error if so.
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ExamineIfOptionIsSet(
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const FieldDescriptor* innermost_field, const string& debug_msg_name,
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const UnknownFieldSet& unknown_fields);
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Validates the value for the option field of the currently interpreted
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // option and then sets it on the unknown_field.
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool SetOptionValue(const FieldDescriptor* option_field,
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        UnknownFieldSet* unknown_fields);
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // saves it into *unknown_fields.
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool SetAggregateOption(const FieldDescriptor* option_field,
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            UnknownFieldSet* unknown_fields);
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Convenience functions to set an int field the right way, depending on
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // its wire type (a single int CppType can represent multiple wire types).
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetInt32(int number, int32 value, FieldDescriptor::Type type,
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  UnknownFieldSet* unknown_fields);
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetInt64(int number, int64 value, FieldDescriptor::Type type,
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  UnknownFieldSet* unknown_fields);
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   UnknownFieldSet* unknown_fields);
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   UnknownFieldSet* unknown_fields);
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A helper function that adds an error at the specified location of the
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // option we're currently interpreting, and returns false.
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const string& msg) {
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder_->AddError(options_to_interpret_->element_name,
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         *uninterpreted_option_, location, msg);
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A helper function that adds an error at the location of the option name
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and returns false.
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool AddNameError(const string& msg) {
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A helper function that adds an error at the location of the option name
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and returns false.
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool AddValueError(const string& msg) {
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We interpret against this builder's pool. Is never NULL. We don't own
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this pointer.
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorBuilder* builder_;
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The options we're currently interpreting, or NULL if we're not in a call
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to InterpretOptions.
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OptionsToInterpret* options_to_interpret_;
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The option we're currently interpreting within options_to_interpret_, or
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NULL if we're not in a call to InterpretOptions(). This points to a
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // submessage of the original option, not the mutable copy. Therefore we
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can use it to find locations recorded by the parser.
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UninterpretedOption* uninterpreted_option_;
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Factory used to create the dynamic messages we need to parse
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any aggregate option values we encounter.
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DynamicMessageFactory dynamic_factory_;
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Work-around for broken compilers:  According to the C++ standard,
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OptionInterpreter should have access to the private members of any class
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which has declared DescriptorBuilder as a friend.  Unfortunately some old
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // versions of GCC and other compilers do not implement this correctly.  So,
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we have to have these intermediate methods to provide access.  We also
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // redundantly declare OptionInterpreter a friend just to make things extra
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clear for these bad compilers.
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class OptionInterpreter;
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class OptionInterpreter::AggregateOptionFinder;
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static inline bool get_allow_unknown(const DescriptorPool* pool) {
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pool->allow_unknown_;
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static inline bool get_is_placeholder(const Descriptor* descriptor) {
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return descriptor->is_placeholder_;
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static inline void assert_mutex_held(const DescriptorPool* pool) {
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pool->mutex_ != NULL) {
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool->mutex_->AssertHeld();
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be run only after options have been interpreted.
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Validation code must only reference the options in the mutable
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptors, which are the ones that have been interpreted. The const
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // proto references are passed in only so they can be provided to calls to
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AddError(). Do not look at their options, which have not been interpreted.
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateFileOptions(FileDescriptor* file,
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const FileDescriptorProto& proto);
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateMessageOptions(Descriptor* message,
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const DescriptorProto& proto);
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateFieldOptions(FieldDescriptor* field,
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const FieldDescriptorProto& proto);
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateEnumOptions(EnumDescriptor* enm,
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const EnumDescriptorProto& proto);
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const EnumValueDescriptorProto& proto);
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateServiceOptions(ServiceDescriptor* service,
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const ServiceDescriptorProto& proto);
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateMethodOptions(MethodDescriptor* method,
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const MethodDescriptorProto& proto);
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateMapKey(FieldDescriptor* field,
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const FieldDescriptorProto& proto);
2494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorPool::BuildFile(
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptorProto& proto) {
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(fallback_database_ == NULL)
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << "Cannot call BuildFile on a DescriptorPool that uses a "
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "DescriptorDatabase.  You must instead find a way to get your file "
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "into the underlying database.";
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptorProto& proto,
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrorCollector* error_collector) {
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(fallback_database_ == NULL)
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << "Cannot call BuildFile on a DescriptorPool that uses a "
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "DescriptorDatabase.  You must instead find a way to get your file "
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "into the underlying database.";
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DescriptorBuilder(this, tables_.get(),
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           error_collector).BuildFile(proto);
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptorProto& proto) const {
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutex_->AssertHeld();
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DescriptorBuilder(this, tables_.get(),
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           default_error_collector_).BuildFile(proto);
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorBuilder::DescriptorBuilder(
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorPool* pool,
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorPool::Tables* tables,
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorPool::ErrorCollector* error_collector)
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : pool_(pool),
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_(tables),
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_collector_(error_collector),
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    had_errors_(false),
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    possible_undeclared_dependency_(NULL) {}
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorBuilder::~DescriptorBuilder() {}
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::AddError(
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& element_name,
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& descriptor,
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorPool::ErrorCollector::ErrorLocation location,
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& error) {
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_collector_ == NULL) {
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!had_errors_) {
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "\":";
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GOOGLE_LOG(ERROR) << "  " << element_name << ": " << error;
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_collector_->AddError(filename_, element_name,
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &descriptor, location, error);
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  had_errors_ = true;
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::AddNotDefinedError(
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& element_name,
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& descriptor,
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorPool::ErrorCollector::ErrorLocation location,
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& undefined_symbol) {
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (possible_undeclared_dependency_ == NULL) {
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(element_name, descriptor, location,
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "\"" + undefined_symbol + "\" is not defined.");
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(element_name, descriptor, location,
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "\"" + possible_undeclared_dependency_name_ +
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "\" seems to be defined in \"" +
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             possible_undeclared_dependency_->name() + "\", which is not "
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "imported by \"" + filename_ + "\".  To use it here, please "
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "add the necessary import.");
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const string& package_name) {
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasPrefixString(file->package(), package_name) &&
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (file->package().size() == package_name.size() ||
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file->package()[package_name.size()] == '.');
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
2582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (file == NULL || !dependencies_.insert(file).second) return;
2583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
2584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RecordPublicDependencies(file->public_dependency(i));
2585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
2586ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2588ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochSymbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
2589ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const DescriptorPool* pool, const string& name) {
2590ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If we are looking at an underlay, we must lock its mutex_, since we are
2591ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // accessing the underlay's tables_ directly.
2592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
2593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2594ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Symbol result = pool->tables_->FindSymbol(name);
2595ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result.IsNull() && pool->underlay_ != NULL) {
2596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Symbol not found; check the underlay.
2597ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
2598ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2600ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result.IsNull()) {
2601ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // In theory, we shouldn't need to check fallback_database_ because the
2602ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // symbol should be in one of its file's direct dependencies, and we have
2603ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // already loaded those by the time we get here.  But we check anyway so
2604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // that we can generate better error message when dependencies are missing
2605ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // (i.e., "missing dependency" rather than "type is not defined").
2606ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (pool->TryFindSymbolInFallbackDatabase(name)) {
2607ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      result = pool->tables_->FindSymbol(name);
2608ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2614ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochSymbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
2615ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return FindSymbolNotEnforcingDepsHelper(pool_, name);
2616ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
2617ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol DescriptorBuilder::FindSymbol(const string& name) {
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = FindSymbolNotEnforcingDeps(name);
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2621ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result.IsNull()) return result;
2622ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pool_->enforce_dependencies_) {
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hack for CompilerUpgrader.
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only find symbols which were defined in this file or one of its
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dependencies.
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* file = result.GetFile();
2631ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (file == file_ || dependencies_.count(file) > 0) return result;
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.type == Symbol::PACKAGE) {
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Arg, this is overcomplicated.  The symbol is a package name.  It could
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be that the package was defined in multiple files.  result.GetFile()
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // returns the first file we saw that used this package.  We've determined
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that that file is not a direct dependency of the file we are currently
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // building, but it could be that some other file which *is* a direct
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // dependency also defines the same package.  We can't really rule out this
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // symbol unless none of the dependencies define it.
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsInPackage(file_, name)) return result;
2642ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for (set<const FileDescriptor*>::const_iterator it = dependencies_.begin();
2643ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         it != dependencies_.end(); ++it) {
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note:  A dependency may be NULL if it was not found or had errors.
2645ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (*it != NULL && IsInPackage(*it, name)) return result;
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  possible_undeclared_dependency_ = file;
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  possible_undeclared_dependency_name_ = name;
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kNullSymbol;
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name, const string& relative_to, ResolveMode resolve_mode) {
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  possible_undeclared_dependency_ = NULL;
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name.size() > 0 && name[0] == '.') {
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fully-qualified name.
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FindSymbol(name.substr(1));
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // defined in multiple parent scopes, we only want to find "Bar.baz" in the
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // innermost one.  E.g., the following should produce an error:
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   message Bar { message Baz {} }
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   message Foo {
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     message Bar {
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     optional Bar.Baz baz = 1;
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   }
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // So, we look for just "Foo" first, then look for "Bar.baz" within it if
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // found.
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string::size_type name_dot_pos = name.find_first_of('.');
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string first_part_of_name;
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name_dot_pos == string::npos) {
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_part_of_name = name;
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_part_of_name = name.substr(0, name_dot_pos);
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string scope_to_try(relative_to);
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Chop off the last component of the scope.
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string::size_type dot_pos = scope_to_try.find_last_of('.');
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dot_pos == string::npos) {
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FindSymbol(name);
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scope_to_try.erase(dot_pos);
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Append ".first_part_of_name" and try to find.
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string::size_type old_size = scope_to_try.size();
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scope_to_try.append(1, '.');
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scope_to_try.append(first_part_of_name);
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol result = FindSymbol(scope_to_try);
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.IsNull()) {
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first_part_of_name.size() < name.size()) {
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // name is a compound symbol, of which we only found the first part.
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Now try to look up the rest of it.
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (result.IsAggregate()) {
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          scope_to_try.append(name, first_part_of_name.size(),
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              name.size() - first_part_of_name.size());
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return FindSymbol(scope_to_try);
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We found a symbol but it's not an aggregate.  Continue the loop.
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We found a symbol but it's not a type.  Continue the loop.
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return result;
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not found.  Remove the name so we can try again.
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scope_to_try.erase(old_size);
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol DescriptorBuilder::LookupSymbol(
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name, const string& relative_to,
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlaceholderType placeholder_type, ResolveMode resolve_mode) {
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol result = LookupSymbolNoPlaceholder(
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name, relative_to, resolve_mode);
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.IsNull() && pool_->allow_unknown_) {
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not found, but AllowUnknownDependencies() is enabled.  Return a
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // placeholder instead.
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = NewPlaceholder(name, placeholder_type);
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol DescriptorBuilder::NewPlaceholder(const string& name,
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         PlaceholderType placeholder_type) {
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compute names.
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string* placeholder_full_name;
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string* placeholder_name;
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string* placeholder_package;
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ValidateQualifiedName(name)) return kNullSymbol;
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name[0] == '.') {
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fully-qualified.
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_full_name = tables_->AllocateString(name.substr(1));
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_full_name = tables_->AllocateString(name);
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string::size_type dotpos = placeholder_full_name->find_last_of('.');
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dotpos != string::npos) {
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_package = tables_->AllocateString(
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_full_name->substr(0, dotpos));
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_name = tables_->AllocateString(
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_full_name->substr(dotpos + 1));
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
27585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    placeholder_package = &::google::protobuf::internal::GetEmptyString();
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_name = placeholder_full_name;
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the placeholders.
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor* placeholder_file = tables_->Allocate<FileDescriptor>();
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(placeholder_file, 0, sizeof(*placeholder_file));
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2766ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance();
2767ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder_file->name_ =
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->AllocateString(*placeholder_full_name + ".placeholder.proto");
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder_file->package_ = placeholder_package;
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder_file->pool_ = pool_;
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder_file->options_ = &FileOptions::default_instance();
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder_file->tables_ = &FileDescriptorTables::kEmpty;
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All other fields are zero or NULL.
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (placeholder_type == PLACEHOLDER_ENUM) {
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_file->enum_type_count_ = 1;
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_file->enum_types_ =
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tables_->AllocateArray<EnumDescriptor>(1);
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(placeholder_enum, 0, sizeof(*placeholder_enum));
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->full_name_ = placeholder_full_name;
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->name_ = placeholder_name;
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->file_ = placeholder_file;
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->options_ = &EnumOptions::default_instance();
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->is_placeholder_ = true;
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enums must have at least one value.
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->value_count_ = 1;
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(placeholder_value, 0, sizeof(*placeholder_value));
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that enum value names are siblings of their type, not children.
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_value->full_name_ =
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_package->empty() ? placeholder_value->name_ :
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE");
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_value->number_ = 0;
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_value->type_ = placeholder_enum;
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_value->options_ = &EnumValueOptions::default_instance();
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Symbol(placeholder_enum);
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_file->message_type_count_ = 1;
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_file->message_types_ =
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tables_->AllocateArray<Descriptor>(1);
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Descriptor* placeholder_message = &placeholder_file->message_types_[0];
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(placeholder_message, 0, sizeof(*placeholder_message));
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->full_name_ = placeholder_full_name;
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->name_ = placeholder_name;
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->file_ = placeholder_file;
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->options_ = &MessageOptions::default_instance();
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->is_placeholder_ = true;
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_message->extension_range_count_ = 1;
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_message->extension_ranges_ =
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tables_->AllocateArray<Descriptor::ExtensionRange>(1);
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_message->extension_ranges_->start = 1;
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // kMaxNumber + 1 because ExtensionRange::end is exclusive.
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      placeholder_message->extension_ranges_->end =
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FieldDescriptor::kMaxNumber + 1;
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Symbol(placeholder_message);
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name) {
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(placeholder, 0, sizeof(*placeholder));
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder->name_ = tables_->AllocateString(name);
28445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  placeholder->package_ = &::google::protobuf::internal::GetEmptyString();
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder->pool_ = pool_;
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder->options_ = &FileOptions::default_instance();
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  placeholder->tables_ = &FileDescriptorTables::kEmpty;
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All other fields are zero or NULL.
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return placeholder;
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::AddSymbol(
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& full_name, const void* parent, const string& name,
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& proto, Symbol symbol) {
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the caller passed NULL for the parent, the symbol is at file scope.
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use its file as the parent instead.
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parent == NULL) parent = file_;
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tables_->AddSymbol(full_name, symbol)) {
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in "
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "symbols_by_name_, but was defined in symbols_by_parent_; "
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "this shouldn't be possible.";
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (other_file == file_) {
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string::size_type dot_pos = full_name.find_last_of('.');
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (dot_pos == string::npos) {
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + full_name + "\" is already defined.");
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + full_name.substr(dot_pos + 1) +
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\" is already defined in \"" +
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 full_name.substr(0, dot_pos) + "\".");
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Symbol seems to have been defined in a different file.
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "\"" + full_name + "\" is already defined in file \"" +
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               other_file->name() + "\".");
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::AddPackage(
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name, const Message& proto, const FileDescriptor* file) {
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tables_->AddSymbol(name, Symbol(file))) {
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Success.  Also add parent package, if any.
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string::size_type dot_pos = name.find_last_of('.');
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dot_pos == string::npos) {
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // No parents.
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ValidateSymbolName(name, name, proto);
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Has parent.
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string* parent_name = tables_->AllocateString(name.substr(0, dot_pos));
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddPackage(*parent_name, proto, file);
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol existing_symbol = tables_->FindSymbol(name);
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's OK to redefine a package.
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing_symbol.type != Symbol::PACKAGE) {
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Symbol seems to have been defined in a different file.
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "\"" + name + "\" is already defined (as something other than "
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "a package) in file \"" + existing_symbol.GetFile()->name() +
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "\".");
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateSymbolName(
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name, const string& full_name, const Message& proto) {
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name.empty()) {
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Missing name.");
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < name.size(); i++) {
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // I don't trust isalnum() due to locales.  :(
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((name[i] < 'a' || 'z' < name[i]) &&
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (name[i] < 'A' || 'Z' < name[i]) &&
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (name[i] < '0' || '9' < name[i]) &&
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (name[i] != '_')) {
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + name + "\" is not a valid identifier.");
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::ValidateQualifiedName(const string& name) {
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool last_was_period = false;
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < name.size(); i++) {
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // I don't trust isalnum() due to locales.  :(
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (('a' <= name[i] && name[i] <= 'z') ||
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('A' <= name[i] && name[i] <= 'Z') ||
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('0' <= name[i] && name[i] <= '9') ||
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (name[i] == '_')) {
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_was_period = false;
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (name[i] == '.') {
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (last_was_period) return false;
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_was_period = true;
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !name.empty() && !last_was_period;
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This generic implementation is good for all descriptors except
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FileDescriptor.
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class DescriptorT> void DescriptorBuilder::AllocateOptions(
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const typename DescriptorT::OptionsType& orig_options,
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorT* descriptor) {
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      orig_options, descriptor);
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We specialize for FileDescriptor.
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        FileDescriptor* descriptor) {
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We add the dummy token so that LookupSymbol does the right thing.
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(),
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      orig_options, descriptor);
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class DescriptorT> void DescriptorBuilder::AllocateOptionsImpl(
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name_scope,
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& element_name,
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const typename DescriptorT::OptionsType& orig_options,
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorT* descriptor) {
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to use a dummy pointer to work around a bug in older versions of
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GCC.  Otherwise, the following two lines could be replaced with:
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   typename DescriptorT::OptionsType* options =
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       tables_->AllocateMessage<typename DescriptorT::OptionsType>();
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename DescriptorT::OptionsType* const dummy = NULL;
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
29883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
29893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
29903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // reflection based method, which requires the Descriptor. However, we are in
29913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the middle of building the descriptors, thus the deadlock.
29923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  options->ParseFromString(orig_options.SerializeAsString());
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor->options_ = options;
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't add to options_to_interpret_ unless there were uninterpreted
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // options.  This not only avoids unnecessary work, but prevents a
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bootstrapping problem when building descriptors for descriptor.proto.
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor.proto does not contain any uninterpreted options, but
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // attempting to interpret options anyway will cause
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OptionsType::GetDescriptor() to be called which may then deadlock since
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we're still trying to build it.
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options->uninterpreted_option_size() > 0) {
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options_to_interpret_.push_back(
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OptionsToInterpret(name_scope, element_name, &orig_options, options));
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A common pattern:  We want to convert a repeated field in the descriptor
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to an array of values, calling some method to build each value.
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)             \
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OUTPUT->NAME##_count_ = INPUT.NAME##_size();                       \
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_);             \
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < INPUT.NAME##_size(); i++) {                    \
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i);             \
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FileDescriptor* DescriptorBuilder::BuildFile(
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptorProto& proto) {
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filename_ = proto.name();
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the file already exists and is identical to the one being built.
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  This only works if the input is canonical -- that is, it
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fully-qualifies all type names, has no UninterpretedOptions, etc.
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   This is fine, because this idempotency "feature" really only exists to
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   accomodate one hack in the proto1->proto2 migration layer.
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileDescriptor* existing_file = tables_->FindFile(filename_);
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (existing_file != NULL) {
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // File already in pool.  Compare the existing one to the input.
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileDescriptorProto existing_proto;
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    existing_file->CopyTo(&existing_proto);
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing_proto.SerializeAsString() == proto.SerializeAsString()) {
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // They're identical.  Return the existing descriptor.
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return existing_file;
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a match.  The error will be detected and handled later.
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if this file is already on the pending files list.
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  Allow recursive imports?  It may not work with some
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   (most?) programming languages.  E.g., in C++, a forward declaration
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   of a type is not sufficient to allow it to be used even in a
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   generated header file due to inlining.  This could perhaps be
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   worked around using tricks involving inserting #include statements
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   mid-file, but that's pretty ugly, and I'm pretty sure there are
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   some languages out there that do not allow recursive dependencies
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   at all.
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < tables_->pending_files_.size(); i++) {
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tables_->pending_files_[i] == proto.name()) {
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string error_message("File recursively imports itself: ");
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (; i < tables_->pending_files_.size(); i++) {
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error_message.append(tables_->pending_files_[i]);
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error_message.append(" -> ");
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_message.append(proto.name());
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               error_message);
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have a fallback_database_, attempt to load all dependencies now,
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before checkpointing tables_.  This avoids confusion with recursive
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // checkpoints.
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pool_->fallback_database_ != NULL) {
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->pending_files_.push_back(proto.name());
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < proto.dependency_size(); i++) {
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tables_->FindFile(proto.dependency(i)) == NULL &&
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (pool_->underlay_ == NULL ||
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) {
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We don't care what this returns since we'll find out below anyway.
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->pending_files_.pop_back();
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checkpoint the tables so that we can roll back if something goes wrong.
3081ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  tables_->AddCheckpoint();
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor* result = tables_->Allocate<FileDescriptor>();
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_ = result;
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3086ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (proto.has_source_code_info()) {
3087ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
3088ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    info->CopyFrom(proto.source_code_info());
3089ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result->source_code_info_ = info;
3090ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
3091ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result->source_code_info_ = &SourceCodeInfo::default_instance();
3092ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
3093ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_tables_ = tables_->AllocateFileTables();
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_->tables_ = file_tables_;
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_name()) {
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Missing field: FileDescriptorProto.name.");
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_ = tables_->AllocateString(proto.name());
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.has_package()) {
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->package_ = tables_->AllocateString(proto.package());
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We cannot rely on proto.package() returning a valid string if
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // proto.has_package() is false, because we might be running at static
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // initialization time, in which case default values have not yet been
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // initialized.
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->package_ = tables_->AllocateString("");
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->pool_ = pool_;
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add to tables.
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tables_->AddFile(result)) {
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "A file with this name is already in the pool.");
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Bail out early so that if this is actually the exact same file, we
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // don't end up reporting that every single symbol is already defined.
3120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    tables_->RollbackToLastCheckpoint();
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result->package().empty()) {
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPackage(result->package(), proto, result);
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure all dependencies are loaded.
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set<string> seen_dependencies;
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->dependency_count_ = proto.dependency_size();
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->dependencies_ =
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < proto.dependency_size(); i++) {
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!seen_dependencies.insert(proto.dependency(i)).second) {
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(proto.name(), proto,
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::OTHER,
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Import \"" + proto.dependency(i) + "\" was listed twice.");
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dependency == NULL && pool_->underlay_ != NULL) {
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dependency == NULL) {
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pool_->allow_unknown_) {
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dependency = NewPlaceholderFile(proto.dependency(i));
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string message;
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (pool_->fallback_database_ == NULL) {
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          message = "Import \"" + proto.dependency(i) +
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "\" has not been loaded.";
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          message = "Import \"" + proto.dependency(i) +
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "\" was not found or had errors.";
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(proto.name(), proto,
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::OTHER,
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 message);
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->dependencies_[i] = dependency;
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Check public dependencies.
3166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int public_dependency_count = 0;
3167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  result->public_dependencies_ = tables_->AllocateArray<int>(
3168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      proto.public_dependency_size());
3169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < proto.public_dependency_size(); i++) {
3170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Only put valid public dependency indexes.
3171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int index = proto.public_dependency(i);
3172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (index >= 0 && index < proto.dependency_size()) {
3173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      result->public_dependencies_[public_dependency_count++] = index;
3174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
3175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      AddError(proto.name(), proto,
3176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               DescriptorPool::ErrorCollector::OTHER,
3177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               "Invalid public dependency index.");
3178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
3179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
3180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  result->public_dependency_count_ = public_dependency_count;
3181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Build dependency set
3183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  dependencies_.clear();
3184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < result->dependency_count(); i++) {
3185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RecordPublicDependencies(result->dependency(i));
3186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
3187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Check weak dependencies.
3189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int weak_dependency_count = 0;
3190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  result->weak_dependencies_ = tables_->AllocateArray<int>(
3191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      proto.weak_dependency_size());
3192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < proto.weak_dependency_size(); i++) {
3193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int index = proto.weak_dependency(i);
3194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (index >= 0 && index < proto.dependency_size()) {
3195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      result->weak_dependencies_[weak_dependency_count++] = index;
3196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
3197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      AddError(proto.name(), proto,
3198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               DescriptorPool::ErrorCollector::OTHER,
3199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               "Invalid weak dependency index.");
3200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
3201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
3202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  result->weak_dependency_count_ = weak_dependency_count;
3203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert children.
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, message_type, BuildMessage  , NULL);
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, enum_type   , BuildEnum     , NULL);
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, service     , BuildService  , NULL);
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, extension   , BuildExtension, NULL);
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the following steps must occur in exactly the specified order.
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cross-link.
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrossLinkFile(result, proto);
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Interpret any remaining uninterpreted options gathered into
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // options_to_interpret_ during descriptor building.  Cross-linking has made
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension options known, so all interpretations should now succeed.
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!had_errors_) {
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OptionInterpreter option_interpreter(this);
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (vector<OptionsToInterpret>::iterator iter =
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             options_to_interpret_.begin();
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         iter != options_to_interpret_.end(); ++iter) {
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      option_interpreter.InterpretOptions(&(*iter));
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options_to_interpret_.clear();
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate options.
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!had_errors_) {
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ValidateFileOptions(result, proto);
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (had_errors_) {
3241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    tables_->RollbackToLastCheckpoint();
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    tables_->ClearLastCheckpoint();
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const Descriptor* parent,
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     Descriptor* result) {
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string& scope = (parent == NULL) ?
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_->package() : parent->full_name();
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(scope);
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!full_name->empty()) full_name->append(1, '.');
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(proto.name());
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_            = tables_->AllocateString(proto.name());
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_       = full_name;
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->file_            = file_;
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->containing_type_ = parent;
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->is_placeholder_  = false;
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->is_unqualified_placeholder_ = false;
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, field          , BuildField         , result);
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, nested_type    , BuildMessage       , result);
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, enum_type      , BuildEnum          , result);
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, extension      , BuildExtension     , result);
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSymbol(result->full_name(), parent, result->name(),
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proto, Symbol(result));
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that no fields have numbers in extension ranges.
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < result->field_count(); i++) {
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = result->field(i);
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < result->extension_range_count(); j++) {
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Descriptor::ExtensionRange* range = result->extension_range(j);
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (range->start <= field->number() && field->number() < range->end) {
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto.extension_range(j),
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::NUMBER,
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 strings::Substitute(
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "Extension range $0 to $1 includes field \"$2\" ($3).",
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   range->start, range->end - 1,
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   field->name(), field->number()));
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that extension ranges don't overlap.
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < result->extension_range_count(); i++) {
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor::ExtensionRange* range1 = result->extension_range(i);
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = i + 1; j < result->extension_range_count(); j++) {
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Descriptor::ExtensionRange* range2 = result->extension_range(j);
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (range1->end > range2->start && range2->end > range1->start) {
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(result->full_name(), proto.extension_range(j),
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::NUMBER,
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 strings::Substitute("Extension range $0 to $1 overlaps with "
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     "already-defined range $2 to $3.",
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     range2->start, range2->end - 1,
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     range1->start, range1->end - 1));
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const Descriptor* parent,
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              FieldDescriptor* result,
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bool is_extension) {
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string& scope = (parent == NULL) ?
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_->package() : parent->full_name();
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(scope);
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!full_name->empty()) full_name->append(1, '.');
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(proto.name());
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_         = tables_->AllocateString(proto.name());
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_    = full_name;
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->file_         = file_;
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->number_       = proto.number();
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->is_extension_ = is_extension;
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If .proto files follow the style guide then the name should already be
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lower-cased.  If that's the case we can just reuse the string we already
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allocated rather than allocate a new one.
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string lowercase_name(proto.name());
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LowerString(&lowercase_name);
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lowercase_name == proto.name()) {
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->lowercase_name_ = result->name_;
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->lowercase_name_ = tables_->AllocateString(lowercase_name);
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't bother with the above optimization for camel-case names since
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // .proto files that follow the guide shouldn't be using names in this
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // format, so the optimization wouldn't help much.
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->camelcase_name_ = tables_->AllocateString(ToCamelCase(proto.name()));
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some compilers do not allow static_cast directly between two enum types,
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we must cast to int first.
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->type_  = static_cast<FieldDescriptor::Type>(
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     implicit_cast<int>(proto.type()));
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->label_ = static_cast<FieldDescriptor::Label>(
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     implicit_cast<int>(proto.label()));
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some of these may be filled in when cross-linking.
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->containing_type_ = NULL;
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->extension_scope_ = NULL;
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->experimental_map_key_ = NULL;
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->message_type_ = NULL;
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->enum_type_ = NULL;
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->has_default_value_ = proto.has_default_value();
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.has_default_value() && result->is_repeated()) {
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto,
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Repeated fields can't have default values.");
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.has_type()) {
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (proto.has_default_value()) {
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char* end_pos = NULL;
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (result->cpp_type()) {
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_INT32:
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_int32_ =
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            strtol(proto.default_value().c_str(), &end_pos, 0);
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_INT64:
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_int64_ =
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            strto64(proto.default_value().c_str(), &end_pos, 0);
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_UINT32:
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_uint32_ =
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            strtoul(proto.default_value().c_str(), &end_pos, 0);
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_UINT64:
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_uint64_ =
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            strtou64(proto.default_value().c_str(), &end_pos, 0);
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_FLOAT:
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (proto.default_value() == "inf") {
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_float_ = numeric_limits<float>::infinity();
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (proto.default_value() == "-inf") {
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_float_ = -numeric_limits<float>::infinity();
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (proto.default_value() == "nan") {
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_float_ = numeric_limits<float>::quiet_NaN();
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else  {
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_float_ =
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_DOUBLE:
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (proto.default_value() == "inf") {
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_double_ = numeric_limits<double>::infinity();
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (proto.default_value() == "-inf") {
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_double_ = -numeric_limits<double>::infinity();
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (proto.default_value() == "nan") {
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_double_ = numeric_limits<double>::quiet_NaN();
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else  {
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_double_ =
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_BOOL:
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (proto.default_value() == "true") {
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_bool_ = true;
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (proto.default_value() == "false") {
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_bool_ = false;
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AddError(result->full_name(), proto,
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "Boolean default must be true or false.");
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_ENUM:
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // This will be filled in when cross-linking.
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_enum_ = NULL;
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_STRING:
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (result->type() == FieldDescriptor::TYPE_BYTES) {
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_string_ = tables_->AllocateString(
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              UnescapeCEscapeString(proto.default_value()));
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result->default_value_string_ =
3436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                tables_->AllocateString(proto.default_value());
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_MESSAGE:
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddError(result->full_name(), proto,
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "Messages can't have default values.");
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->has_default_value_ = false;
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (end_pos != NULL) {
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // end_pos is only set non-NULL by the parsers for numeric types, above.
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This checks that the default was non-empty and had no extra junk
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // after the end of the number.
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (proto.default_value().empty() || *end_pos != '\0') {
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddError(result->full_name(), proto,
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "Couldn't parse default value.");
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // No explicit default value
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (result->cpp_type()) {
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_INT32:
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_int32_ = 0;
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_INT64:
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_int64_ = 0;
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_UINT32:
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_uint32_ = 0;
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_UINT64:
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_uint64_ = 0;
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_FLOAT:
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_float_ = 0.0f;
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_DOUBLE:
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_double_ = 0.0;
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_BOOL:
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_bool_ = false;
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_ENUM:
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // This will be filled in when cross-linking.
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->default_value_enum_ = NULL;
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_STRING:
34865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          result->default_value_string_ = &::google::protobuf::internal::GetEmptyString();
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::CPPTYPE_MESSAGE:
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result->number() <= 0) {
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Field numbers must be positive integers.");
3497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
3498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Only validate that the number is within the valid field range if it is
3499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // not an extension. Since extension numbers are validated with the
3500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // extendee's valid set of extension numbers, and those are in turn
3501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // validated against the max allowed number, the check is unnecessary for
3502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // extension fields.
3503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // This avoids cross-linking issues that arise when attempting to check if
3504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // the extendee is a message_set_wire_format message, which has a higher max
3505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // on extension numbers.
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             strings::Substitute("Field numbers cannot be greater than $0.",
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 FieldDescriptor::kMaxNumber));
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             result->number() <= FieldDescriptor::kLastReservedNumber) {
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             strings::Substitute(
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Field numbers $0 through $1 are reserved for the protocol "
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "buffer library implementation.",
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               FieldDescriptor::kFirstReservedNumber,
35165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               FieldDescriptor::kLastReservedNumber));
35175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_extension) {
35205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!proto.has_extendee()) {
35215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(result->full_name(), proto,
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::EXTENDEE,
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "FieldDescriptorProto.extendee not set for extension field.");
35245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->extension_scope_ = parent;
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (proto.has_extendee()) {
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(result->full_name(), proto,
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::EXTENDEE,
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "FieldDescriptorProto.extendee set for non-extension field.");
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->containing_type_ = parent;
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSymbol(result->full_name(), parent, result->name(),
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proto, Symbol(result));
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildExtensionRange(
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DescriptorProto::ExtensionRange& proto,
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* parent,
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Descriptor::ExtensionRange* result) {
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->start = proto.start();
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->end = proto.end();
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result->start <= 0) {
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(parent->full_name(), proto,
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::NUMBER,
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Extension numbers must be positive integers.");
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Checking of the upper bound of the extension range is deferred until after
3561ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // options interpreting. This allows messages with message_set_wire_format to
3562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
3563ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // numbers are actually used as int32s in the message_set_wire_format.
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result->start >= result->end) {
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(parent->full_name(), proto,
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::NUMBER,
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Extension range end number must be greater than start number.");
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const Descriptor* parent,
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  EnumDescriptor* result) {
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string& scope = (parent == NULL) ?
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_->package() : parent->full_name();
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(scope);
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!full_name->empty()) full_name->append(1, '.');
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(proto.name());
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_            = tables_->AllocateString(proto.name());
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_       = full_name;
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->file_            = file_;
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->containing_type_ = parent;
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->is_placeholder_  = false;
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->is_unqualified_placeholder_ = false;
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.value_size() == 0) {
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We cannot allow enums with no values because this would mean there
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // would be no valid default value for fields of this type.
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto,
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::NAME,
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Enums must contain at least one value.");
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSymbol(result->full_name(), parent, result->name(),
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proto, Symbol(result));
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
36125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const EnumDescriptor* parent,
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       EnumValueDescriptor* result) {
36145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_   = tables_->AllocateString(proto.name());
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->number_ = proto.number();
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->type_   = parent;
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  full_name for enum values is a sibling to the parent's name, not a
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   child of it.
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(*parent->full_name_);
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->resize(full_name->size() - parent->name_->size());
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(*result->name_);
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_ = full_name;
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
36285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
36295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
36305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Again, enum values are weird because we makes them appear as siblings
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the enum type instead of children of it.  So, we use
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parent->containing_type() as the value's parent.
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool added_to_outer_scope =
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddSymbol(result->full_name(), parent->containing_type(), result->name(),
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              proto, Symbol(result));
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, we also want to be able to search for values within a single
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // enum type, so we add it as a child of the enum type itself, too.
36435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  This could fail, but if it does, the error has already been
36445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   reported by the above AddSymbol() call, so we ignore the return code.
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool added_to_inner_scope =
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
36475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (added_to_inner_scope && !added_to_outer_scope) {
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This value did not conflict with any values defined in the same enum,
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but it did conflict with some other symbol defined in the enum type's
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scope.  Let's print an additional error to explain this.
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string outer_scope;
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parent->containing_type() == NULL) {
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      outer_scope = file_->package();
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      outer_scope = parent->containing_type()->full_name();
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (outer_scope.empty()) {
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      outer_scope = "the global scope";
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      outer_scope = "\"" + outer_scope + "\"";
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(result->full_name(), proto,
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::NAME,
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Note that enum values use C++ scoping rules, meaning that "
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "enum values are siblings of their type, not children of it.  "
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Therefore, \"" + result->name() + "\" must be unique within "
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             + outer_scope + ", not just within \"" + parent->name() + "\".");
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An enum is allowed to define two numbers that refer to the same value.
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindValueByNumber() should return the first such value, so we simply
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ignore AddEnumValueByNumber()'s return code.
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_tables_->AddEnumValueByNumber(result);
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const void* dummy,
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ServiceDescriptor* result) {
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(file_->package());
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!full_name->empty()) full_name->append(1, '.');
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(proto.name());
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_      = tables_->AllocateString(proto.name());
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_ = full_name;
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->file_      = file_;
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BUILD_ARRAY(proto, result, method, BuildMethod, result);
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSymbol(result->full_name(), NULL, result->name(),
37025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proto, Symbol(result));
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const ServiceDescriptor* parent,
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    MethodDescriptor* result) {
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->name_    = tables_->AllocateString(proto.name());
37095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->service_ = parent;
37105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string* full_name = tables_->AllocateString(parent->full_name());
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(1, '.');
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  full_name->append(*result->name_);
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->full_name_ = full_name;
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateSymbolName(proto.name(), *full_name, proto);
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These will be filled in when cross-linking.
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->input_type_ = NULL;
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->output_type_ = NULL;
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy options.
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto.has_options()) {
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->options_ = NULL;  // Will set to default_instance later.
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateOptions(proto.options(), result);
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSymbol(result->full_name(), parent, result->name(),
37305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            proto, Symbol(result));
37315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef BUILD_ARRAY
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkFile(
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileDescriptor* file, const FileDescriptorProto& proto) {
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file->options_ == NULL) {
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file->options_ = &FileOptions::default_instance();
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file->message_type_count(); i++) {
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file->extension_count(); i++) {
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkField(&file->extensions_[i], proto.extension(i));
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file->enum_type_count(); i++) {
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file->service_count(); i++) {
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkService(&file->services_[i], proto.service(i));
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkMessage(
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Descriptor* message, const DescriptorProto& proto) {
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message->options_ == NULL) {
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message->options_ = &MessageOptions::default_instance();
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message->nested_type_count(); i++) {
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message->enum_type_count(); i++) {
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message->field_count(); i++) {
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkField(&message->fields_[i], proto.field(i));
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < message->extension_count(); i++) {
37795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkField(&message->extensions_[i], proto.extension(i));
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkField(
37845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldDescriptor* field, const FieldDescriptorProto& proto) {
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->options_ == NULL) {
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field->options_ = &FieldOptions::default_instance();
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.has_extendee()) {
37905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol extendee = LookupSymbol(proto.extendee(), field->full_name(),
37915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PLACEHOLDER_EXTENDABLE_MESSAGE);
37925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extendee.IsNull()) {
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddNotDefinedError(field->full_name(), proto,
37945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         DescriptorPool::ErrorCollector::EXTENDEE,
37955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         proto.extendee());
37965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
37975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (extendee.type != Symbol::MESSAGE) {
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto,
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::EXTENDEE,
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "\"" + proto.extendee() + "\" is not a message type.");
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field->containing_type_ = extendee.descriptor;
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->containing_type()->IsExtensionNumber(field->number())) {
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto,
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::NUMBER,
38085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               strings::Substitute("\"$0\" does not declare $1 as an "
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "extension number.",
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->containing_type()->full_name(),
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->number()));
38125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto.has_type_name()) {
38165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume we are expecting a message type unless the proto contains some
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // evidence that it expects an enum type.  This only makes a difference if
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we end up creating a placeholder.
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          proto.has_default_value();
38215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol type =
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LookupSymbol(proto.type_name(), field->full_name(),
38245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE,
38255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   LOOKUP_TYPES);
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type.IsNull()) {
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddNotDefinedError(field->full_name(), proto,
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         DescriptorPool::ErrorCollector::TYPE,
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         proto.type_name());
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!proto.has_type()) {
38355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Choose field type based on symbol.
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type.type == Symbol::MESSAGE) {
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->type_ = FieldDescriptor::TYPE_MESSAGE;
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (type.type == Symbol::ENUM) {
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->type_ = FieldDescriptor::TYPE_ENUM;
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto,
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::TYPE,
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + proto.type_name() + "\" is not a type.");
38445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type.type != Symbol::MESSAGE) {
38505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto,
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::TYPE,
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + proto.type_name() + "\" is not a message type.");
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->message_type_ = type.descriptor;
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->has_default_value()) {
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto,
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Messages can't have default values.");
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type.type != Symbol::ENUM) {
38645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto,
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::TYPE,
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "\"" + proto.type_name() + "\" is not an enum type.");
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->enum_type_ = type.enum_descriptor;
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->enum_type()->is_placeholder_) {
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We can't look up default values for placeholder types.  We'll have
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // to just drop them.
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->has_default_value_ = false;
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->has_default_value()) {
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We can't just use field->enum_type()->FindValueByName() here
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // because that locks the pool's mutex, which we have already locked
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // at this point.
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Symbol default_value =
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LookupSymbolNoPlaceholder(proto.default_value(),
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    field->enum_type()->full_name());
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (default_value.type == Symbol::ENUM_VALUE &&
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            default_value.enum_value_descriptor->type() == field->enum_type()) {
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field->default_value_enum_ = default_value.enum_value_descriptor;
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddError(field->full_name(), proto,
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "Enum type \"" + field->enum_type()->full_name() +
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "\" has no value named \"" + proto.default_value() + "\".");
38935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (field->enum_type()->value_count() > 0) {
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // All enums must have at least one value, or we would have reported
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // an error elsewhere.  We use the first defined value as the default
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // if a default is not explicitly defined.
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->default_value_enum_ = field->enum_type()->value(0);
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Field with primitive type has type_name.");
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
39055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
39065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
39075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Field with message or enum type missing type_name.");
39095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the field to the fields-by-number table.
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  We have to do this *after* cross-linking because extensions do not
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   know their containing type until now.
39155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_tables_->AddFieldByNumber(field)) {
39165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* conflicting_field =
39175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_tables_->FindFieldByNumber(field->containing_type(),
39185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      field->number());
39195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_extension()) {
39205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto,
39215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::NUMBER,
39225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               strings::Substitute("Extension number $0 has already been used "
39235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "in \"$1\" by extension \"$2\".",
39245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->number(),
39255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->containing_type()->full_name(),
39265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   conflicting_field->full_name()));
39275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
39285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto,
39295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::NUMBER,
39305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               strings::Substitute("Field number $0 has already been used in "
39315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "\"$1\" by field \"$2\".",
39325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->number(),
39335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   field->containing_type()->full_name(),
39345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   conflicting_field->name()));
39355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->is_extension()) {
39395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need for error checking: if the extension number collided,
39405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we've already been informed of it by the if() above.
39415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tables_->AddExtension(field);
39425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the field to the lowercase-name and camelcase-name tables.
39455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_tables_->AddFieldByStylizedNames(field);
39465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkEnum(
39495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumDescriptor* enum_type, const EnumDescriptorProto& proto) {
39505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enum_type->options_ == NULL) {
39515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_type->options_ = &EnumOptions::default_instance();
39525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < enum_type->value_count(); i++) {
39555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
39565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkEnumValue(
39605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) {
39615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enum_value->options_ == NULL) {
39625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_value->options_ = &EnumValueOptions::default_instance();
39635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkService(
39675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
39685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service->options_ == NULL) {
39695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service->options_ = &ServiceOptions::default_instance();
39705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < service->method_count(); i++) {
39735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossLinkMethod(&service->methods_[i], proto.method(i));
39745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::CrossLinkMethod(
39785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MethodDescriptor* method, const MethodDescriptorProto& proto) {
39795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (method->options_ == NULL) {
39805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method->options_ = &MethodOptions::default_instance();
39815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol input_type = LookupSymbol(proto.input_type(), method->full_name());
39845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (input_type.IsNull()) {
39855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddNotDefinedError(method->full_name(), proto,
39865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       DescriptorPool::ErrorCollector::INPUT_TYPE,
39875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       proto.input_type());
39885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (input_type.type != Symbol::MESSAGE) {
39895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(method->full_name(), proto,
39905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::INPUT_TYPE,
39915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "\"" + proto.input_type() + "\" is not a message type.");
39925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
39935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method->input_type_ = input_type.descriptor;
39945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol output_type = LookupSymbol(proto.output_type(), method->full_name());
39975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (output_type.IsNull()) {
39985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddNotDefinedError(method->full_name(), proto,
39995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       DescriptorPool::ErrorCollector::OUTPUT_TYPE,
40005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       proto.output_type());
40015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (output_type.type != Symbol::MESSAGE) {
40025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(method->full_name(), proto,
40035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::OUTPUT_TYPE,
40045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "\"" + proto.output_type() + "\" is not a message type.");
40055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
40065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method->output_type_ = output_type.descriptor;
40075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
40115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type)  \
40135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor->array_name##_count(); ++i) {     \
40145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Validate##type##Options(descriptor->array_name##s_ + i,        \
40155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            proto.array_name(i));                  \
40165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
40195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// avoid problems that exist at init time.
40205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsLite(const FileDescriptor* file) {
40215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  I don't even remember how many of these conditions are
40225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   actually possible.  I'm just being super-safe.
40235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file != NULL &&
40245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         &file->options() != &FileOptions::default_instance() &&
40255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
40265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
40295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const FileDescriptorProto& proto) {
40305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
40315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
40325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
40335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
40345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lite files can only be imported by other Lite files.
40365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsLite(file)) {
40375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file->dependency_count(); i++) {
40385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsLite(file->dependency(i))) {
40395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(
40405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file->name(), proto,
40415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DescriptorPool::ErrorCollector::OTHER,
40425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Files that do not use optimize_for = LITE_RUNTIME cannot import "
40435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "files which do use this option.  This file is not lite, but it "
40445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "imports \"" + file->dependency(i)->name() + "\" which is.");
40455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
40465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
40525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const DescriptorProto& proto) {
40535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
40545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
40555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
40565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
4057ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4058ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const int64 max_extension_range =
4059ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      static_cast<int64>(message->options().message_set_wire_format() ?
4060ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         kint32max :
4061ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         FieldDescriptor::kMaxNumber);
4062ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < message->extension_range_count(); ++i) {
4063ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (message->extension_range(i)->end > max_extension_range + 1) {
4064ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      AddError(
4065ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          message->full_name(), proto.extension_range(i),
4066ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          DescriptorPool::ErrorCollector::NUMBER,
4067ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          strings::Substitute("Extension numbers cannot be greater than $0.",
4068ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              max_extension_range));
4069ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
4070ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
40715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
40745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptorProto& proto) {
40755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->options().has_experimental_map_key()) {
40765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ValidateMapKey(field, proto);
40775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4079ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Only message type fields may be lazy.
4080ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (field->options().lazy()) {
4081ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
4082ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      AddError(field->full_name(), proto,
4083ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               DescriptorPool::ErrorCollector::TYPE,
4084ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               "[lazy = true] can only be specified for submessage fields.");
4085ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
4086ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
4087ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
40885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only repeated primitive fields may be packed.
40895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->options().packed() && !field->is_packable()) {
40905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(
40915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->full_name(), proto,
40925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DescriptorPool::ErrorCollector::TYPE,
40935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "[packed = true] can only be specified for repeated primitive fields.");
40945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  Default instance may not yet be initialized here, so we have to
40975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   avoid reading from it.
40985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->containing_type_ != NULL &&
40995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &field->containing_type()->options() !=
41005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &MessageOptions::default_instance() &&
41015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->containing_type()->options().message_set_wire_format()) {
41025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_extension()) {
41035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!field->is_optional() ||
41045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field->type() != FieldDescriptor::TYPE_MESSAGE) {
41055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddError(field->full_name(), proto,
41065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 DescriptorPool::ErrorCollector::TYPE,
41075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Extensions of MessageSets must be optional messages.");
41085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
41095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
41105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddError(field->full_name(), proto,
41115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               DescriptorPool::ErrorCollector::NAME,
41125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "MessageSets cannot have fields, only extensions.");
41135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
41145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
41155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lite extensions can only be of Lite types.
41175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsLite(field->file()) &&
41185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->containing_type_ != NULL &&
41195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !IsLite(field->containing_type()->file())) {
41205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto,
41215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::EXTENDEE,
41225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Extensions to non-lite types can only be declared in non-lite "
41235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "files.  Note that you cannot extend a non-lite type to contain "
41245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "a lite type, but the reverse is allowed.");
41255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
41275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
41305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const EnumDescriptorProto& proto) {
41315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
41323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
4133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    map<int, string> used_values;
4134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for (int i = 0; i < enm->value_count(); ++i) {
4135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const EnumValueDescriptor* enum_value = enm->value(i);
4136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (used_values.find(enum_value->number()) != used_values.end()) {
41373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        string error =
41383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            "\"" + enum_value->full_name() +
41393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            "\" uses the same enum value as \"" +
41403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            used_values[enum_value->number()] + "\". If this is intended, set "
41413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            "'option allow_alias = true;' to the enum definition.";
41423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        if (!enm->options().allow_alias()) {
41433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          // Generate error if duplicated enum values are explicitly disallowed.
41443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          AddError(enm->full_name(), proto,
41453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   DescriptorPool::ErrorCollector::NUMBER,
41463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   error);
41473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        } else {
41483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          // Generate warning if duplicated values are found but the option
41493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          // isn't set.
41503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          GOOGLE_LOG(ERROR) << error;
41513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        }
4152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
4153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        used_values[enum_value->number()] = enum_value->full_name();
4154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
4155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
4156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
41575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateEnumValueOptions(
41605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) {
41615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing to do so far.
41625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
41645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceDescriptorProto& proto) {
41655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsLite(service->file()) &&
41665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (service->file()->options().cc_generic_services() ||
41675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       service->file()->options().java_generic_services())) {
41685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(service->full_name(), proto,
41695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DescriptorPool::ErrorCollector::NAME,
41705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Files with optimize_for = LITE_RUNTIME cannot define services "
41715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "unless you set both options cc_generic_services and "
41725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "java_generic_sevices to false.");
41735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
41745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
41765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* method,
41795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MethodDescriptorProto& proto) {
41805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing to do so far.
41815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::ValidateMapKey(FieldDescriptor* field,
41845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const FieldDescriptorProto& proto) {
41855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!field->is_repeated()) {
41865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
41875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "map type is only allowed for repeated fields.");
41885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
41895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
41905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
41925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
41935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "map type is only allowed for fields with a message type.");
41945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
41955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
41965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* item_type = field->message_type();
41985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (item_type == NULL) {
41995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
42005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Could not find field type.");
42015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
42025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the field in item_type named by "experimental_map_key"
42055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string& key_name = field->options().experimental_map_key();
42065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Symbol key_symbol = LookupSymbol(
42075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_name,
42085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We append ".key_name" to the containing type's name since
42095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // LookupSymbol() searches for peers of the supplied name, not
42105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // children of the supplied name.
42115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_type->full_name() + "." + key_name);
42125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key_symbol.IsNull() || key_symbol.field_descriptor->is_extension()) {
42145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
42155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "Could not find field named \"" + key_name + "\" in type \"" +
42165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             item_type->full_name() + "\".");
42175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
42185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* key_field = key_symbol.field_descriptor;
42205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key_field->is_repeated()) {
42225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
42235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "map_key must not name a repeated field.");
42245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
42255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
42285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
42295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "map key must name a scalar or string field.");
42305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
42315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  field->experimental_map_key_ = key_field;
42345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
42355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
42375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef VALIDATE_OPTIONS_FROM_ARRAY
42385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
42405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorBuilder::OptionInterpreter::OptionInterpreter(
42425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DescriptorBuilder* builder) : builder_(builder) {
42435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(builder_);
42445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
42455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {
42475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
42485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
42505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OptionsToInterpret* options_to_interpret) {
42515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that these may be in different pools, so we can't use the same
42525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor and reflection objects on both.
42535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Message* options = options_to_interpret->options;
42545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Message* original_options = options_to_interpret->original_options;
42555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool failed = false;
42575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options_to_interpret_ = options_to_interpret;
42585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the uninterpreted_option field in the mutable copy of the options
42605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and clear them, since we're about to interpret them.
42615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* uninterpreted_options_field =
42625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
42635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(uninterpreted_options_field != NULL)
42645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "No field named \"uninterpreted_option\" in the Options proto.";
42655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options->GetReflection()->ClearField(options, uninterpreted_options_field);
42665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the uninterpreted_option field in the original options.
42685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* original_uninterpreted_options_field =
42695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      original_options->GetDescriptor()->
42705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FindFieldByName("uninterpreted_option");
42715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(original_uninterpreted_options_field != NULL)
42725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "No field named \"uninterpreted_option\" in the Options proto.";
42735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_uninterpreted_options = original_options->GetReflection()->
42755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FieldSize(*original_options, original_uninterpreted_options_field);
42765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_uninterpreted_options; ++i) {
42775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uninterpreted_option_ = down_cast<const UninterpretedOption*>(
42785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &original_options->GetReflection()->GetRepeatedMessage(
42795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *original_options, original_uninterpreted_options_field, i));
42805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!InterpretSingleOption(options)) {
42815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Error already added by InterpretSingleOption().
42825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failed = true;
42835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
42845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
42855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset these, so we don't have any dangling pointers.
42875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uninterpreted_option_ = NULL;
42885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options_to_interpret_ = NULL;
42895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!failed) {
42915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // InterpretSingleOption() added the interpreted options in the
42925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // UnknownFieldSet, in case the option isn't yet known to us.  Now we
42935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // serialize the options message and deserialize it back.  That way, any
42945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // option fields that we do happen to know about will get moved from the
42955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // UnknownFieldSet into the real fields, and thus be available right away.
42965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If they are not known, that's OK too. They will get reparsed into the
42975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // UnknownFieldSet and wait there until the message is parsed by something
42985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that does know about the options.
42995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string buf;
43005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options->AppendToString(&buf);
43015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GOOGLE_CHECK(options->ParseFromString(buf))
43025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Protocol message serialized itself in invalid fashion.";
43035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !failed;
43065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
43075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
43095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* options) {
43105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First do some basic validation.
43115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uninterpreted_option_->name_size() == 0) {
43125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This should never happen unless the parser has gone seriously awry or
43135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // someone has manually created the uninterpreted option badly.
43145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AddNameError("Option must have a name.");
43155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
43175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AddNameError("Option must not use reserved name "
43185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "\"uninterpreted_option\".");
43195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* options_descriptor = NULL;
43225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the options message's descriptor from the builder's pool, so that we
43235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // get the version that knows about any extension options declared in the
43245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file we're currently building. The descriptor should be there as long as
43255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the file we're building imported "google/protobuf/descriptors.proto".
43265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
43285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DescriptorPool::FindMessageTypeByName() because we're already holding the
4329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // pool's mutex, and the latter method locks it again.  We don't use
4330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // FindSymbol() because files that use custom options only need to depend on
4331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the file that defines the option, not descriptor.proto itself.
43325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
43335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options->GetDescriptor()->full_name());
43345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
43355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options_descriptor = symbol.descriptor;
43365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
43375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The options message's descriptor was not in the builder's pool, so use
43385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the standard version from the generated pool. We're not holding the
43395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // generated pool's mutex, so we can search it the straightforward way.
43405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options_descriptor = options->GetDescriptor();
43415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(options_descriptor);
43435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We iterate over the name parts to drill into the submessages until we find
43455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the leaf field for the option. As we drill down we remember the current
43465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // submessage's descriptor in |descriptor| and the next field in that
43475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // submessage in |field|. We also track the fields we're drilling down
43485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // through in |intermediate_fields|. As we go, we reconstruct the full option
43495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name in |debug_msg_name|, for use in error messages.
43505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* descriptor = options_descriptor;
43515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* field = NULL;
43525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> intermediate_fields;
43535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string debug_msg_name = "";
43545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
43565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& name_part = uninterpreted_option_->name(i).name_part();
43575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (debug_msg_name.size() > 0) {
43585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_msg_name += ".";
43595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
43605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uninterpreted_option_->name(i).is_extension()) {
43615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_msg_name += "(" + name_part + ")";
43625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the extension's descriptor as an extension in the builder's
43635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
43645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
43655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // relative lookups, and 2) because we're already holding the pool's
43665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // mutex, and the latter method locks it again.
4367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      symbol = builder_->LookupSymbol(name_part,
4368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                      options_to_interpret_->name_scope);
43695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
43705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field = symbol.field_descriptor;
43715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
43725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we don't find the field then the field's descriptor was not in the
43735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // builder's pool, but there's no point in looking in the generated
43745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pool. We require that you import the file that defines any extensions
43755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // you use, so they must be present in the builder's pool.
43765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
43775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_msg_name += name_part;
43785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the field's descriptor as a regular field.
43795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field = descriptor->FindFieldByName(name_part);
43805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
43815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field == NULL) {
43835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (get_allow_unknown(builder_->pool_)) {
43845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We can't find the option, but AllowUnknownDependencies() is enabled,
43855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // so we will just leave it as uninterpreted.
43865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddWithoutInterpreting(*uninterpreted_option_, options);
43875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
43885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
43895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
43905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
43915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (field->containing_type() != descriptor) {
43925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (get_is_placeholder(field->containing_type())) {
43935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The field is an extension of a placeholder type, so we can't
43945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // reliably verify whether it is a valid extension to use here (e.g.
43955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // we don't know if it is an extension of the correct *Options message,
43965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // or if it has a valid field number, etc.).  Just leave it as
43975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // uninterpreted instead.
43985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddWithoutInterpreting(*uninterpreted_option_, options);
43995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
44005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
44015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This can only happen if, due to some insane misconfiguration of the
44025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // pools, we find the options message in one pool but the field in
44035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // another. This would probably imply a hefty bug somewhere.
44045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddNameError("Option field \"" + debug_msg_name +
44055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "\" is not a field or extension of message \"" +
44065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            descriptor->name() + "\".");
44075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (field->is_repeated()) {
44095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddNameError("Option field \"" + debug_msg_name +
44105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "\" is repeated. Repeated options are not "
44115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "supported.");
44125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (i < uninterpreted_option_->name_size() - 1) {
44135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
44145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddNameError("Option \"" +  debug_msg_name +
44155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "\" is an atomic type, not a message.");
44165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
44175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Drill down into the submessage.
44185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        intermediate_fields.push_back(field);
44195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        descriptor = field->message_type();
44205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
44225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We've found the leaf field. Now we use UnknownFieldSets to set its value
44255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the options message. We do so because the message may not yet know
44265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // about its extension fields, so we may not be able to set the fields
44275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directly. But the UnknownFieldSets will serialize to the same wire-format
44285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message, so reading that message back in once the extension fields are
44295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // known will populate them correctly.
44305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First see if the option is already set.
44325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ExamineIfOptionIsSet(
44335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          intermediate_fields.begin(),
44345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          intermediate_fields.end(),
44355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field, debug_msg_name,
44365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          options->GetReflection()->GetUnknownFields(*options))) {
44375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // ExamineIfOptionIsSet() already added the error.
44385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First set the value on the UnknownFieldSet corresponding to the
44425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // innermost message.
44435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
44445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SetOptionValue(field, unknown_fields.get())) {
44455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // SetOptionValue() already added the error.
44465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
44495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the intermediate messages.
44505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (vector<const FieldDescriptor*>::reverse_iterator iter =
44515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           intermediate_fields.rbegin();
44525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != intermediate_fields.rend(); ++iter) {
44535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<UnknownFieldSet> parent_unknown_fields(new UnknownFieldSet());
44545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch ((*iter)->type()) {
44555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::TYPE_MESSAGE: {
44565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io::StringOutputStream outstr(
44575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parent_unknown_fields->AddLengthDelimited((*iter)->number()));
44585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io::CodedOutputStream out(&outstr);
44595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        internal::WireFormatLite::SerializeUnknownFields(*unknown_fields, &out);
44605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_CHECK(!out.HadError())
44615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "Unexpected failure while serializing option submessage "
44625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << debug_msg_name << "\".";
44635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
44645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::TYPE_GROUP: {
44675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         parent_unknown_fields->AddGroup((*iter)->number())
44685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              ->MergeFrom(*unknown_fields);
44695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
44705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
44715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
44735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
44745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << (*iter)->type();
44755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
44765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
44775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unknown_fields.reset(parent_unknown_fields.release());
44785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now merge the UnknownFieldSet corresponding to the top-level message into
44815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the options message.
44825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
44835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *unknown_fields);
44845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
44865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
44895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UninterpretedOption& uninterpreted_option, Message* options) {
44905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor* field =
44915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options->GetDescriptor()->FindFieldByName("uninterpreted_option");
44925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(field != NULL);
44935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options->GetReflection()->AddMessage(options, field)
44955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ->CopyFrom(uninterpreted_option);
44965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
44995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
45005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
45015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* innermost_field, const string& debug_msg_name,
45025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields) {
45035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do linear searches of the UnknownFieldSet and its sub-groups.  This
45045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be fine since it's unlikely that any one options structure will
45055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contain more than a handful of options.
45065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (intermediate_fields_iter == intermediate_fields_end) {
45085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're at the innermost submessage.
45095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < unknown_fields.field_count(); i++) {
45105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unknown_fields.field(i).number() == innermost_field->number()) {
45115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddNameError("Option \"" + debug_msg_name +
45125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "\" was already set.");
45135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
45145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
45155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
45165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < unknown_fields.field_count(); i++) {
45195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unknown_fields.field(i).number() ==
45205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*intermediate_fields_iter)->number()) {
45215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const UnknownField* unknown_field = &unknown_fields.field(i);
45225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
45235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Recurse into the next submessage.
45245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (type) {
45255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::TYPE_MESSAGE:
45265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
45275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            UnknownFieldSet intermediate_unknown_fields;
45285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (intermediate_unknown_fields.ParseFromString(
45295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    unknown_field->length_delimited()) &&
45305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
45315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      intermediate_fields_end,
45325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      innermost_field, debug_msg_name,
45335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      intermediate_unknown_fields)) {
45345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              return false;  // Error already added.
45355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
45365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
45375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
45385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case FieldDescriptor::TYPE_GROUP:
45405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (unknown_field->type() == UnknownField::TYPE_GROUP) {
45415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
45425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      intermediate_fields_end,
45435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      innermost_field, debug_msg_name,
45445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      unknown_field->group())) {
45455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              return false;  // Error already added.
45465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
45475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
45485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
45495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
45515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
45525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
45535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
45545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
45555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
45575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
45585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
45605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* option_field,
45615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnknownFieldSet* unknown_fields) {
45625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We switch on the CppType to validate.
45635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (option_field->cpp_type()) {
45645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT32:
45665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_positive_int_value()) {
45675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (uninterpreted_option_->positive_int_value() >
45685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<uint64>(kint32max)) {
45695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return AddValueError("Value out of range for int32 option \"" +
45705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               option_field->full_name() + "\".");
45715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
45725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SetInt32(option_field->number(),
45735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   uninterpreted_option_->positive_int_value(),
45745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   option_field->type(), unknown_fields);
45755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
45765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_negative_int_value()) {
45775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (uninterpreted_option_->negative_int_value() <
45785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int64>(kint32min)) {
45795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return AddValueError("Value out of range for int32 option \"" +
45805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               option_field->full_name() + "\".");
45815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
45825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SetInt32(option_field->number(),
45835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   uninterpreted_option_->negative_int_value(),
45845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   option_field->type(), unknown_fields);
45855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
45865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
45875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be integer for int32 option \"" +
45885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             option_field->full_name() + "\".");
45895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
45905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
45915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT64:
45935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_positive_int_value()) {
45945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (uninterpreted_option_->positive_int_value() >
45955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<uint64>(kint64max)) {
45965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return AddValueError("Value out of range for int64 option \"" +
45975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               option_field->full_name() + "\".");
45985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
45995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SetInt64(option_field->number(),
46005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   uninterpreted_option_->positive_int_value(),
46015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   option_field->type(), unknown_fields);
46025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
46035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_negative_int_value()) {
46045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetInt64(option_field->number(),
46055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 uninterpreted_option_->negative_int_value(),
46065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 option_field->type(), unknown_fields);
46075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be integer for int64 option \"" +
46095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             option_field->full_name() + "\".");
46105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT32:
46145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_positive_int_value()) {
46155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (uninterpreted_option_->positive_int_value() > kuint32max) {
46165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return AddValueError("Value out of range for uint32 option \"" +
46175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               option_field->name() + "\".");
46185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
46195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SetUInt32(option_field->number(),
46205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    uninterpreted_option_->positive_int_value(),
46215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    option_field->type(), unknown_fields);
46225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
46235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be non-negative integer for uint32 "
46255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "option \"" + option_field->full_name() + "\".");
46265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT64:
46305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_positive_int_value()) {
46315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetUInt64(option_field->number(),
46325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  uninterpreted_option_->positive_int_value(),
46335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  option_field->type(), unknown_fields);
46345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be non-negative integer for uint64 "
46365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "option \"" + option_field->full_name() + "\".");
46375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_FLOAT: {
46415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float value;
46425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_double_value()) {
46435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->double_value();
46445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_positive_int_value()) {
46455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->positive_int_value();
46465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_negative_int_value()) {
46475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->negative_int_value();
46485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be number for float option \"" +
46505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             option_field->full_name() + "\".");
46515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed32(option_field->number(),
46535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          google::protobuf::internal::WireFormatLite::EncodeFloat(value));
46545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
46565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_DOUBLE: {
46585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double value;
46595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->has_double_value()) {
46605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->double_value();
46615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_positive_int_value()) {
46625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->positive_int_value();
46635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->has_negative_int_value()) {
46645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = uninterpreted_option_->negative_int_value();
46655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be number for double option \"" +
46675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             option_field->full_name() + "\".");
46685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed64(option_field->number(),
46705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          google::protobuf::internal::WireFormatLite::EncodeDouble(value));
46715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
46735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_BOOL:
46755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint64 value;
46765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!uninterpreted_option_->has_identifier_value()) {
46775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be identifier for boolean option "
46785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "\"" + option_field->full_name() + "\".");
46795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (uninterpreted_option_->identifier_value() == "true") {
46815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = 1;
46825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (uninterpreted_option_->identifier_value() == "false") {
46835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = 0;
46845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
46855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be \"true\" or \"false\" for boolean "
46865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "option \"" + option_field->full_name() + "\".");
46875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(option_field->number(), value);
46895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
46905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_ENUM: {
46925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!uninterpreted_option_->has_identifier_value()) {
46935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be identifier for enum-valued option "
46945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "\"" + option_field->full_name() + "\".");
46955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const EnumDescriptor* enum_type = option_field->enum_type();
46975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string& value_name = uninterpreted_option_->identifier_value();
46985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const EnumValueDescriptor* enum_value = NULL;
46995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
47015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that the enum value's fully-qualified name is a sibling of the
47025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // enum's name, not a child of it.
47035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string fully_qualified_name = enum_type->full_name();
47045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fully_qualified_name.resize(fully_qualified_name.size() -
47055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    enum_type->name().size());
47065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fully_qualified_name += value_name;
47075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Search for the enum value's descriptor in the builder's pool. Note
47095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
47105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // DescriptorPool::FindEnumValueByName() because we're already holding
47115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the pool's mutex, and the latter method locks it again.
47125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Symbol symbol =
47135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
47145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) {
47155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (symbol.enum_value_descriptor->type() != enum_type) {
47165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return AddValueError("Enum type \"" + enum_type->full_name() +
47175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "\" has no value named \"" + value_name + "\" for option \"" +
47185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                option_field->full_name() +
47195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "\". This appears to be a value from a sibling type.");
47205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
47215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            enum_value = symbol.enum_value_descriptor;
47225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
47235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
47245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
47255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The enum type is in the generated pool, so we can search for the
47265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // value there.
47275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enum_value = enum_type->FindValueByName(value_name);
47285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
47295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (enum_value == NULL) {
47315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Enum type \"" +
47325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             option_field->enum_type()->full_name() +
47335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "\" has no value named \"" + value_name + "\" for "
47345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "option \"" + option_field->full_name() + "\".");
47355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
47365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Sign-extension is not a problem, since we cast directly from int32 to
47375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // uint64, without first going through uint32.
47385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unknown_fields->AddVarint(option_field->number(),
47395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<uint64>(static_cast<int64>(enum_value->number())));
47405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
47415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
47425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
47435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_STRING:
47455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!uninterpreted_option_->has_string_value()) {
47465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return AddValueError("Value must be quoted string for string option "
47475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "\"" + option_field->full_name() + "\".");
47485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
47495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The string has already been unquoted and unescaped by the parser.
47505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddLengthDelimited(option_field->number(),
47515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          uninterpreted_option_->string_value());
47525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
47535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_MESSAGE:
47555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!SetAggregateOption(option_field, unknown_fields)) {
47565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
47575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
47585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
47595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
47605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
47625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
47635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
47655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public TextFormat::Finder {
47665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
47675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DescriptorBuilder* builder_;
47685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual const FieldDescriptor* FindExtension(
47705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Message* message, const string& name) const {
47715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert_mutex_held(builder_->pool_);
4772ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Descriptor* descriptor = message->GetDescriptor();
47735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol result = builder_->LookupSymbolNoPlaceholder(
4774ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        name, descriptor->full_name());
47755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result.type == Symbol::FIELD &&
47765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.field_descriptor->is_extension()) {
47775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result.field_descriptor;
4778ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else if (result.type == Symbol::MESSAGE &&
4779ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               descriptor->options().message_set_wire_format()) {
4780ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const Descriptor* foreign_type = result.descriptor;
4781ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // The text format allows MessageSet items to be specified using
4782ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // the type name, rather than the extension identifier. If the symbol
4783ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // lookup returned a Message, and the enclosing Message has
4784ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // message_set_wire_format = true, then return the message set
4785ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // extension, if one exists.
4786ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      for (int i = 0; i < foreign_type->extension_count(); i++) {
4787ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        const FieldDescriptor* extension = foreign_type->extension(i);
4788ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        if (extension->containing_type() == descriptor &&
4789ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
4790ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            extension->is_optional() &&
4791ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            extension->message_type() == foreign_type) {
4792ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          // Found it.
4793ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          return extension;
4794ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        }
4795ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
47965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4797ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return NULL;
47985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
47995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
48005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A custom error collector to record any text-format parsing errors
48025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
48035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AggregateErrorCollector : public io::ErrorCollector {
48045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
48055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string error_;
48065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddError(int line, int column, const string& message) {
48085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!error_.empty()) {
48095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ += "; ";
48105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
48115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ += message;
48125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddWarning(int line, int column, const string& message) {
48155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ignore warnings
48165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
48185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We construct a dynamic message of the type corresponding to
48215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// option_field, parse the supplied text-format string into this
48225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message, and serialize the resulting message to produce the value.
48235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
48245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* option_field,
48255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnknownFieldSet* unknown_fields) {
48265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!uninterpreted_option_->has_aggregate_value()) {
48275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AddValueError("Option \"" + option_field->full_name() +
48285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "\" is a message. To set the entire message, use "
48295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "syntax like \"" + option_field->name() +
48305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         " = { <proto text format> }\". "
48315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "To set fields within it, use "
48325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "syntax like \"" + option_field->name() +
48335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ".foo = value\".");
48345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* type = option_field->message_type();
48375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
48385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(dynamic.get() != NULL)
48395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Could not create an instance of " << option_field->DebugString();
48405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AggregateErrorCollector collector;
48425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AggregateOptionFinder finder;
48435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  finder.builder_ = builder_;
48445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextFormat::Parser parser;
48455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.RecordErrorsTo(&collector);
48465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.SetFinder(&finder);
48475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
48485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              dynamic.get())) {
48495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddValueError("Error while parsing option value for \"" +
48505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  option_field->name() + "\": " + collector.error_);
48515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
48525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
48535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string serial;
48545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dynamic->SerializeToString(&serial);  // Never fails
4855ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
4856ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      unknown_fields->AddLengthDelimited(option_field->number(), serial);
4857ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
4858ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      GOOGLE_CHECK_EQ(option_field->type(),  FieldDescriptor::TYPE_GROUP);
4859ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
4860ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      group->ParseFromString(serial);
4861ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
48625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
48635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
48675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
48685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
48695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_INT32:
48705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number,
48715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<uint64>(static_cast<int64>(value)));
48725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_SFIXED32:
48755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed32(number, static_cast<uint32>(value));
48765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_SINT32:
48795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number,
48805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
48815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
48845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
48855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
48905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
48915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
48925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_INT64:
48935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number, static_cast<uint64>(value));
48945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_SFIXED64:
48975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed64(number, static_cast<uint64>(value));
48985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
48995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_SINT64:
49015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number,
49025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
49035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
49065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
49075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value,
49125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
49135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
49145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_UINT32:
49155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number, static_cast<uint64>(value));
49165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_FIXED32:
49195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed32(number, static_cast<uint32>(value));
49205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
49235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
49245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value,
49295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
49305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
49315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_UINT64:
49325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddVarint(number, value);
49335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::TYPE_FIXED64:
49365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unknown_fields->AddFixed64(number, value);
49375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
49405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
49415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
49425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
49465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
4947