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