1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/stubs/hash.h>
36 #include <map>
37 #include <memory>
38 #ifndef _SHARED_PTR_H
39 #include <google/protobuf/stubs/shared_ptr.h>
40 #endif
41 #include <set>
42 #include <string>
43 #include <vector>
44 #include <algorithm>
45 #include <limits>
46 
47 #include <google/protobuf/stubs/common.h>
48 #include <google/protobuf/stubs/logging.h>
49 #include <google/protobuf/stubs/mutex.h>
50 #include <google/protobuf/stubs/once.h>
51 #include <google/protobuf/stubs/stringprintf.h>
52 #include <google/protobuf/stubs/strutil.h>
53 #include <google/protobuf/io/strtod.h>
54 #include <google/protobuf/io/coded_stream.h>
55 #include <google/protobuf/io/tokenizer.h>
56 #include <google/protobuf/io/zero_copy_stream_impl.h>
57 #include <google/protobuf/descriptor.pb.h>
58 #include <google/protobuf/descriptor.h>
59 #include <google/protobuf/descriptor_database.h>
60 #include <google/protobuf/dynamic_message.h>
61 #include <google/protobuf/generated_message_util.h>
62 #include <google/protobuf/text_format.h>
63 #include <google/protobuf/unknown_field_set.h>
64 #include <google/protobuf/wire_format.h>
65 #include <google/protobuf/stubs/substitute.h>
66 
67 #include <google/protobuf/stubs/map_util.h>
68 #include <google/protobuf/stubs/stl_util.h>
69 
70 #undef PACKAGE  // autoheader #defines this.  :(
71 
72 namespace google {
73 
74 namespace protobuf {
75 
76 struct Symbol {
77   enum Type {
78     NULL_SYMBOL,
79     MESSAGE,
80     FIELD,
81     ONEOF,
82     ENUM,
83     ENUM_VALUE,
84     SERVICE,
85     METHOD,
86     PACKAGE
87   };
88   Type type;
89   union {
90     const Descriptor* descriptor;
91     const FieldDescriptor* field_descriptor;
92     const OneofDescriptor* oneof_descriptor;
93     const EnumDescriptor* enum_descriptor;
94     const EnumValueDescriptor* enum_value_descriptor;
95     const ServiceDescriptor* service_descriptor;
96     const MethodDescriptor* method_descriptor;
97     const FileDescriptor* package_file_descriptor;
98   };
99 
Symbolgoogle::protobuf::Symbol100   inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; }
IsNullgoogle::protobuf::Symbol101   inline bool IsNull() const { return type == NULL_SYMBOL; }
IsTypegoogle::protobuf::Symbol102   inline bool IsType() const { return type == MESSAGE || type == ENUM; }
IsAggregategoogle::protobuf::Symbol103   inline bool IsAggregate() const {
104     return type == MESSAGE || type == PACKAGE || type == ENUM ||
105            type == SERVICE;
106   }
107 
108 #define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \
109   inline explicit Symbol(const TYPE* value) {   \
110     type = TYPE_CONSTANT;                       \
111     this->FIELD = value;                        \
112   }
113 
CONSTRUCTORgoogle::protobuf::Symbol114   CONSTRUCTOR(Descriptor, MESSAGE, descriptor)
115   CONSTRUCTOR(FieldDescriptor, FIELD, field_descriptor)
116   CONSTRUCTOR(OneofDescriptor, ONEOF, oneof_descriptor)
117   CONSTRUCTOR(EnumDescriptor, ENUM, enum_descriptor)
118   CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor)
119   CONSTRUCTOR(ServiceDescriptor, SERVICE, service_descriptor)
120   CONSTRUCTOR(MethodDescriptor, METHOD, method_descriptor)
121   CONSTRUCTOR(FileDescriptor, PACKAGE, package_file_descriptor)
122 #undef CONSTRUCTOR
123 
124   const FileDescriptor* GetFile() const {
125     switch (type) {
126       case NULL_SYMBOL:
127         return NULL;
128       case MESSAGE:
129         return descriptor->file();
130       case FIELD:
131         return field_descriptor->file();
132       case ONEOF:
133         return oneof_descriptor->containing_type()->file();
134       case ENUM:
135         return enum_descriptor->file();
136       case ENUM_VALUE:
137         return enum_value_descriptor->type()->file();
138       case SERVICE:
139         return service_descriptor->file();
140       case METHOD:
141         return method_descriptor->service()->file();
142       case PACKAGE:
143         return package_file_descriptor;
144     }
145     return NULL;
146   }
147 };
148 
149 const FieldDescriptor::CppType
150 FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
151   static_cast<CppType>(0),  // 0 is reserved for errors
152 
153   CPPTYPE_DOUBLE,   // TYPE_DOUBLE
154   CPPTYPE_FLOAT,    // TYPE_FLOAT
155   CPPTYPE_INT64,    // TYPE_INT64
156   CPPTYPE_UINT64,   // TYPE_UINT64
157   CPPTYPE_INT32,    // TYPE_INT32
158   CPPTYPE_UINT64,   // TYPE_FIXED64
159   CPPTYPE_UINT32,   // TYPE_FIXED32
160   CPPTYPE_BOOL,     // TYPE_BOOL
161   CPPTYPE_STRING,   // TYPE_STRING
162   CPPTYPE_MESSAGE,  // TYPE_GROUP
163   CPPTYPE_MESSAGE,  // TYPE_MESSAGE
164   CPPTYPE_STRING,   // TYPE_BYTES
165   CPPTYPE_UINT32,   // TYPE_UINT32
166   CPPTYPE_ENUM,     // TYPE_ENUM
167   CPPTYPE_INT32,    // TYPE_SFIXED32
168   CPPTYPE_INT64,    // TYPE_SFIXED64
169   CPPTYPE_INT32,    // TYPE_SINT32
170   CPPTYPE_INT64,    // TYPE_SINT64
171 };
172 
173 const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
174   "ERROR",     // 0 is reserved for errors
175 
176   "double",    // TYPE_DOUBLE
177   "float",     // TYPE_FLOAT
178   "int64",     // TYPE_INT64
179   "uint64",    // TYPE_UINT64
180   "int32",     // TYPE_INT32
181   "fixed64",   // TYPE_FIXED64
182   "fixed32",   // TYPE_FIXED32
183   "bool",      // TYPE_BOOL
184   "string",    // TYPE_STRING
185   "group",     // TYPE_GROUP
186   "message",   // TYPE_MESSAGE
187   "bytes",     // TYPE_BYTES
188   "uint32",    // TYPE_UINT32
189   "enum",      // TYPE_ENUM
190   "sfixed32",  // TYPE_SFIXED32
191   "sfixed64",  // TYPE_SFIXED64
192   "sint32",    // TYPE_SINT32
193   "sint64",    // TYPE_SINT64
194 };
195 
196 const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
197   "ERROR",     // 0 is reserved for errors
198 
199   "int32",     // CPPTYPE_INT32
200   "int64",     // CPPTYPE_INT64
201   "uint32",    // CPPTYPE_UINT32
202   "uint64",    // CPPTYPE_UINT64
203   "double",    // CPPTYPE_DOUBLE
204   "float",     // CPPTYPE_FLOAT
205   "bool",      // CPPTYPE_BOOL
206   "enum",      // CPPTYPE_ENUM
207   "string",    // CPPTYPE_STRING
208   "message",   // CPPTYPE_MESSAGE
209 };
210 
211 const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
212   "ERROR",     // 0 is reserved for errors
213 
214   "optional",  // LABEL_OPTIONAL
215   "required",  // LABEL_REQUIRED
216   "repeated",  // LABEL_REPEATED
217 };
218 
SyntaxName(FileDescriptor::Syntax syntax)219 const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
220   switch (syntax) {
221     case SYNTAX_PROTO2:
222       return "proto2";
223     case SYNTAX_PROTO3:
224       return "proto3";
225     case SYNTAX_UNKNOWN:
226       return "unknown";
227   }
228   GOOGLE_LOG(FATAL) << "can't reach here.";
229   return NULL;
230 }
231 
232 static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
233 
234 #if !defined(_MSC_VER) || _MSC_VER >= 1900
235 const int FieldDescriptor::kMaxNumber;
236 const int FieldDescriptor::kFirstReservedNumber;
237 const int FieldDescriptor::kLastReservedNumber;
238 #endif
239 
240 namespace {
241 
242 // Note:  I distrust ctype.h due to locales.
ToUpper(char ch)243 char ToUpper(char ch) {
244   return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
245 }
246 
ToLower(char ch)247 char ToLower(char ch) {
248   return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
249 }
250 
ToCamelCase(const string & input,bool lower_first)251 string ToCamelCase(const string& input, bool lower_first) {
252   bool capitalize_next = !lower_first;
253   string result;
254   result.reserve(input.size());
255 
256   for (int i = 0; i < input.size(); i++) {
257     if (input[i] == '_') {
258       capitalize_next = true;
259     } else if (capitalize_next) {
260       result.push_back(ToUpper(input[i]));
261       capitalize_next = false;
262     } else {
263       result.push_back(input[i]);
264     }
265   }
266 
267   // Lower-case the first letter.
268   if (lower_first && !result.empty()) {
269     result[0] = ToLower(result[0]);
270   }
271 
272   return result;
273 }
274 
ToJsonName(const string & input)275 string ToJsonName(const string& input) {
276   bool capitalize_next = false;
277   string result;
278   result.reserve(input.size());
279 
280   for (int i = 0; i < input.size(); i++) {
281     if (input[i] == '_') {
282       capitalize_next = true;
283     } else if (capitalize_next) {
284       result.push_back(ToUpper(input[i]));
285       capitalize_next = false;
286     } else {
287       result.push_back(input[i]);
288     }
289   }
290 
291   return result;
292 }
293 
EnumValueToPascalCase(const string & input)294 string EnumValueToPascalCase(const string& input) {
295   bool next_upper = true;
296   string result;
297   result.reserve(input.size());
298 
299   for (int i = 0; i < input.size(); i++) {
300     if (input[i] == '_') {
301       next_upper = true;
302     } else {
303       if (next_upper) {
304         result.push_back(ToUpper(input[i]));
305       } else {
306         result.push_back(ToLower(input[i]));
307       }
308       next_upper = false;
309     }
310   }
311 
312   return result;
313 }
314 
315 // Class to remove an enum prefix from enum values.
316 class PrefixRemover {
317  public:
PrefixRemover(StringPiece prefix)318   PrefixRemover(StringPiece prefix) {
319     // Strip underscores and lower-case the prefix.
320     for (int i = 0; i < prefix.size(); i++) {
321       if (prefix[i] != '_') {
322         prefix_ += ascii_tolower(prefix[i]);
323       }
324     }
325   }
326 
327   // Tries to remove the enum prefix from this enum value.
328   // If this is not possible, returns the input verbatim.
MaybeRemove(StringPiece str)329   string MaybeRemove(StringPiece str) {
330     // We can't just lowercase and strip str and look for a prefix.
331     // We need to properly recognize the difference between:
332     //
333     //   enum Foo {
334     //     FOO_BAR_BAZ = 0;
335     //     FOO_BARBAZ = 1;
336     //   }
337     //
338     // This is acceptable (though perhaps not advisable) because even when
339     // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
340     size_t i, j;
341 
342     // Skip past prefix_ in str if we can.
343     for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
344       if (str[i] == '_') {
345         continue;
346       }
347 
348       if (ascii_tolower(str[i]) != prefix_[j++]) {
349         return str.as_string();
350       }
351     }
352 
353     // If we didn't make it through the prefix, we've failed to strip the
354     // prefix.
355     if (j < prefix_.size()) {
356       return str.as_string();
357     }
358 
359     // Skip underscores between prefix and further characters.
360     while (i < str.size() && str[i] == '_') {
361       i++;
362     }
363 
364     // Enum label can't be the empty string.
365     if (i == str.size()) {
366       return str.as_string();
367     }
368 
369     // We successfully stripped the prefix.
370     str.remove_prefix(i);
371     return str.as_string();
372   }
373 
374  private:
375   string prefix_;
376 };
377 
378 // A DescriptorPool contains a bunch of hash_maps to implement the
379 // various Find*By*() methods.  Since hashtable lookups are O(1), it's
380 // most efficient to construct a fixed set of large hash_maps used by
381 // all objects in the pool rather than construct one or more small
382 // hash_maps for each object.
383 //
384 // The keys to these hash_maps are (parent, name) or (parent, number)
385 // pairs.  Unfortunately STL doesn't provide hash functions for pair<>,
386 // so we must invent our own.
387 //
388 // TODO(kenton):  Use StringPiece rather than const char* in keys?  It would
389 //   be a lot cleaner but we'd just have to convert it back to const char*
390 //   for the open source release.
391 
392 typedef std::pair<const void*, const char*> PointerStringPair;
393 
394 struct PointerStringPairEqual {
operator ()google::protobuf::__anon78c7d0840211::PointerStringPairEqual395   inline bool operator()(const PointerStringPair& a,
396                          const PointerStringPair& b) const {
397     return a.first == b.first && strcmp(a.second, b.second) == 0;
398   }
399 };
400 
401 template<typename PairType>
402 struct PointerIntegerPairHash {
operator ()google::protobuf::__anon78c7d0840211::PointerIntegerPairHash403   size_t operator()(const PairType& p) const {
404     // FIXME(kenton):  What is the best way to compute this hash?  I have
405     // no idea!  This seems a bit better than an XOR.
406     return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second;
407   }
408 
409 #ifdef _MSC_VER
410   // Used only by MSVC and platforms where hash_map is not available.
411   static const size_t bucket_size = 4;
412   static const size_t min_buckets = 8;
413 #endif
operator ()google::protobuf::__anon78c7d0840211::PointerIntegerPairHash414   inline bool operator()(const PairType& a, const PairType& b) const {
415     return a.first < b.first ||
416           (a.first == b.first && a.second < b.second);
417   }
418 };
419 
420 typedef std::pair<const Descriptor*, int> DescriptorIntPair;
421 typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
422 
423 struct PointerStringPairHash {
operator ()google::protobuf::__anon78c7d0840211::PointerStringPairHash424   size_t operator()(const PointerStringPair& p) const {
425     // FIXME(kenton):  What is the best way to compute this hash?  I have
426     // no idea!  This seems a bit better than an XOR.
427     hash<const char*> cstring_hash;
428     return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) +
429            cstring_hash(p.second);
430   }
431 
432 #ifdef _MSC_VER
433   // Used only by MSVC and platforms where hash_map is not available.
434   static const size_t bucket_size = 4;
435   static const size_t min_buckets = 8;
436 #endif
operator ()google::protobuf::__anon78c7d0840211::PointerStringPairHash437   inline bool operator()(const PointerStringPair& a,
438                          const PointerStringPair& b) const {
439     if (a.first < b.first) return true;
440     if (a.first > b.first) return false;
441     return strcmp(a.second, b.second) < 0;
442   }
443 };
444 
445 
446 const Symbol kNullSymbol;
447 
448 typedef hash_map<const char*, Symbol,
449                  hash<const char*>, streq>
450   SymbolsByNameMap;
451 typedef hash_map<PointerStringPair, Symbol,
452                  PointerStringPairHash, PointerStringPairEqual>
453   SymbolsByParentMap;
454 typedef hash_map<const char*, const FileDescriptor*,
455                  hash<const char*>, streq>
456   FilesByNameMap;
457 typedef hash_map<PointerStringPair, const FieldDescriptor*,
458                  PointerStringPairHash, PointerStringPairEqual>
459   FieldsByNameMap;
460 typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
461                  PointerIntegerPairHash<DescriptorIntPair> >
462   FieldsByNumberMap;
463 typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
464                  PointerIntegerPairHash<EnumIntPair> >
465   EnumValuesByNumberMap;
466 // This is a map rather than a hash_map, since we use it to iterate
467 // through all the extensions that extend a given Descriptor, and an
468 // ordered data structure that implements lower_bound is convenient
469 // for that.
470 typedef std::map<DescriptorIntPair, const FieldDescriptor*>
471   ExtensionsGroupedByDescriptorMap;
472 typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
473 
474 std::set<string>* allowed_proto3_extendees_ = NULL;
475 GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_);
476 
DeleteAllowedProto3Extendee()477 void DeleteAllowedProto3Extendee() {
478   delete allowed_proto3_extendees_;
479 }
480 
InitAllowedProto3Extendee()481 void InitAllowedProto3Extendee() {
482   allowed_proto3_extendees_ = new std::set<string>;
483   const char* kOptionNames[] = {
484       "FileOptions",      "MessageOptions", "FieldOptions", "EnumOptions",
485       "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
486   for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
487     // descriptor.proto has a different package name in opensource. We allow
488     // both so the opensource protocol compiler can also compile internal
489     // proto3 files with custom options. See: b/27567912
490     allowed_proto3_extendees_->insert(string("google.protobuf.") +
491                                       kOptionNames[i]);
492     // Split the word to trick the opensource processing scripts so they
493     // will keep the origial package name.
494     allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]);
495   }
496 
497   google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee);
498 }
499 
500 // Checks whether the extendee type is allowed in proto3.
501 // Only extensions to descriptor options are allowed. We use name comparison
502 // instead of comparing the descriptor directly because the extensions may be
503 // defined in a different pool.
AllowedExtendeeInProto3(const string & name)504 bool AllowedExtendeeInProto3(const string& name) {
505   ::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee);
506   return allowed_proto3_extendees_->find(name) !=
507          allowed_proto3_extendees_->end();
508 }
509 
510 }  // anonymous namespace
511 
512 // ===================================================================
513 // DescriptorPool::Tables
514 
515 class DescriptorPool::Tables {
516  public:
517   Tables();
518   ~Tables();
519 
520   // Record the current state of the tables to the stack of checkpoints.
521   // Each call to AddCheckpoint() must be paired with exactly one call to either
522   // ClearLastCheckpoint() or RollbackToLastCheckpoint().
523   //
524   // This is used when building files, since some kinds of validation errors
525   // cannot be detected until the file's descriptors have already been added to
526   // the tables.
527   //
528   // This supports recursive checkpoints, since building a file may trigger
529   // recursive building of other files. Note that recursive checkpoints are not
530   // normally necessary; explicit dependencies are built prior to checkpointing.
531   // So although we recursively build transitive imports, there is at most one
532   // checkpoint in the stack during dependency building.
533   //
534   // Recursive checkpoints only arise during cross-linking of the descriptors.
535   // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
536   // friends. If the pending file references an unknown symbol
537   // (e.g., it is not defined in the pending file's explicit dependencies), and
538   // the pool is using a fallback database, and that database contains a file
539   // defining that symbol, and that file has not yet been built by the pool,
540   // the pool builds the file during cross-linking, leading to another
541   // checkpoint.
542   void AddCheckpoint();
543 
544   // Mark the last checkpoint as having cleared successfully, removing it from
545   // the stack. If the stack is empty, all pending symbols will be committed.
546   //
547   // Note that this does not guarantee that the symbols added since the last
548   // checkpoint won't be rolled back: if a checkpoint gets rolled back,
549   // everything past that point gets rolled back, including symbols added after
550   // checkpoints that were pushed onto the stack after it and marked as cleared.
551   void ClearLastCheckpoint();
552 
553   // Roll back the Tables to the state of the checkpoint at the top of the
554   // stack, removing everything that was added after that point.
555   void RollbackToLastCheckpoint();
556 
557   // The stack of files which are currently being built.  Used to detect
558   // cyclic dependencies when loading files from a DescriptorDatabase.  Not
559   // used when fallback_database_ == NULL.
560   std::vector<string> pending_files_;
561 
562   // A set of files which we have tried to load from the fallback database
563   // and encountered errors.  We will not attempt to load them again during
564   // execution of the current public API call, but for compatibility with
565   // legacy clients, this is cleared at the beginning of each public API call.
566   // Not used when fallback_database_ == NULL.
567   hash_set<string> known_bad_files_;
568 
569   // A set of symbols which we have tried to load from the fallback database
570   // and encountered errors. We will not attempt to load them again during
571   // execution of the current public API call, but for compatibility with
572   // legacy clients, this is cleared at the beginning of each public API call.
573   hash_set<string> known_bad_symbols_;
574 
575   // The set of descriptors for which we've already loaded the full
576   // set of extensions numbers from fallback_database_.
577   hash_set<const Descriptor*> extensions_loaded_from_db_;
578 
579   // -----------------------------------------------------------------
580   // Finding items.
581 
582   // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
583   // if not found.
584   inline Symbol FindSymbol(const string& key) const;
585 
586   // This implements the body of DescriptorPool::Find*ByName().  It should
587   // really be a private method of DescriptorPool, but that would require
588   // declaring Symbol in descriptor.h, which would drag all kinds of other
589   // stuff into the header.  Yay C++.
590   Symbol FindByNameHelper(
591     const DescriptorPool* pool, const string& name);
592 
593   // These return NULL if not found.
594   inline const FileDescriptor* FindFile(const string& key) const;
595   inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
596                                               int number);
597   inline void FindAllExtensions(const Descriptor* extendee,
598                                 std::vector<const FieldDescriptor*>* out) const;
599 
600   // -----------------------------------------------------------------
601   // Adding items.
602 
603   // These add items to the corresponding tables.  They return false if
604   // the key already exists in the table.  For AddSymbol(), the string passed
605   // in must be one that was constructed using AllocateString(), as it will
606   // be used as a key in the symbols_by_name_ map without copying.
607   bool AddSymbol(const string& full_name, Symbol symbol);
608   bool AddFile(const FileDescriptor* file);
609   bool AddExtension(const FieldDescriptor* field);
610 
611   // -----------------------------------------------------------------
612   // Allocating memory.
613 
614   // Allocate an object which will be reclaimed when the pool is
615   // destroyed.  Note that the object's destructor will never be called,
616   // so its fields must be plain old data (primitive data types and
617   // pointers).  All of the descriptor types are such objects.
618   template<typename Type> Type* Allocate();
619 
620   // Allocate an array of objects which will be reclaimed when the
621   // pool in destroyed.  Again, destructors are never called.
622   template<typename Type> Type* AllocateArray(int count);
623 
624   // Allocate a string which will be destroyed when the pool is destroyed.
625   // The string is initialized to the given value for convenience.
626   string* AllocateString(const string& value);
627 
628   // Allocate a GoogleOnceDynamic which will be destroyed when the pool is
629   // destroyed.
630   GoogleOnceDynamic* AllocateOnceDynamic();
631 
632   // Allocate a protocol message object.  Some older versions of GCC have
633   // trouble understanding explicit template instantiations in some cases, so
634   // in those cases we have to pass a dummy pointer of the right type as the
635   // parameter instead of specifying the type explicitly.
636   template<typename Type> Type* AllocateMessage(Type* dummy = NULL);
637 
638   // Allocate a FileDescriptorTables object.
639   FileDescriptorTables* AllocateFileTables();
640 
641  private:
642   std::vector<string*> strings_;    // All strings in the pool.
643   std::vector<Message*> messages_;  // All messages in the pool.
644   std::vector<GoogleOnceDynamic*>
645       once_dynamics_;  // All GoogleOnceDynamics in the pool.
646   std::vector<FileDescriptorTables*>
647       file_tables_;                 // All file tables in the pool.
648   std::vector<void*> allocations_;  // All other memory allocated in the pool.
649 
650   SymbolsByNameMap      symbols_by_name_;
651   FilesByNameMap        files_by_name_;
652   ExtensionsGroupedByDescriptorMap extensions_;
653 
654   struct CheckPoint {
CheckPointgoogle::protobuf::DescriptorPool::Tables::CheckPoint655     explicit CheckPoint(const Tables* tables)
656         : strings_before_checkpoint(tables->strings_.size()),
657           messages_before_checkpoint(tables->messages_.size()),
658           once_dynamics_before_checkpoint(tables->once_dynamics_.size()),
659           file_tables_before_checkpoint(tables->file_tables_.size()),
660           allocations_before_checkpoint(tables->allocations_.size()),
661           pending_symbols_before_checkpoint(
662               tables->symbols_after_checkpoint_.size()),
663           pending_files_before_checkpoint(
664               tables->files_after_checkpoint_.size()),
665           pending_extensions_before_checkpoint(
666               tables->extensions_after_checkpoint_.size()) {}
667     int strings_before_checkpoint;
668     int messages_before_checkpoint;
669     int once_dynamics_before_checkpoint;
670     int file_tables_before_checkpoint;
671     int allocations_before_checkpoint;
672     int pending_symbols_before_checkpoint;
673     int pending_files_before_checkpoint;
674     int pending_extensions_before_checkpoint;
675   };
676   std::vector<CheckPoint> checkpoints_;
677   std::vector<const char*      > symbols_after_checkpoint_;
678   std::vector<const char*      > files_after_checkpoint_;
679   std::vector<DescriptorIntPair> extensions_after_checkpoint_;
680 
681   // Allocate some bytes which will be reclaimed when the pool is
682   // destroyed.
683   void* AllocateBytes(int size);
684 };
685 
686 // Contains tables specific to a particular file.  These tables are not
687 // modified once the file has been constructed, so they need not be
688 // protected by a mutex.  This makes operations that depend only on the
689 // contents of a single file -- e.g. Descriptor::FindFieldByName() --
690 // lock-free.
691 //
692 // For historical reasons, the definitions of the methods of
693 // FileDescriptorTables and DescriptorPool::Tables are interleaved below.
694 // These used to be a single class.
695 class FileDescriptorTables {
696  public:
697   FileDescriptorTables();
698   ~FileDescriptorTables();
699 
700   // Empty table, used with placeholder files.
701   inline static const FileDescriptorTables& GetEmptyInstance();
702 
703   // -----------------------------------------------------------------
704   // Finding items.
705 
706   // Find symbols.  These return a null Symbol (symbol.IsNull() is true)
707   // if not found.
708   inline Symbol FindNestedSymbol(const void* parent,
709                                  const string& name) const;
710   inline Symbol FindNestedSymbolOfType(const void* parent,
711                                        const string& name,
712                                        const Symbol::Type type) const;
713 
714   // These return NULL if not found.
715   inline const FieldDescriptor* FindFieldByNumber(
716     const Descriptor* parent, int number) const;
717   inline const FieldDescriptor* FindFieldByLowercaseName(
718     const void* parent, const string& lowercase_name) const;
719   inline const FieldDescriptor* FindFieldByCamelcaseName(
720     const void* parent, const string& camelcase_name) const;
721   inline const EnumValueDescriptor* FindEnumValueByNumber(
722     const EnumDescriptor* parent, int number) const;
723   // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
724   inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
725       const EnumDescriptor* parent, int number) const;
726 
727   // -----------------------------------------------------------------
728   // Adding items.
729 
730   // These add items to the corresponding tables.  They return false if
731   // the key already exists in the table.  For AddAliasUnderParent(), the
732   // string passed in must be one that was constructed using AllocateString(),
733   // as it will be used as a key in the symbols_by_parent_ map without copying.
734   bool AddAliasUnderParent(const void* parent, const string& name,
735                            Symbol symbol);
736   bool AddFieldByNumber(const FieldDescriptor* field);
737   bool AddEnumValueByNumber(const EnumValueDescriptor* value);
738 
739   // Adds the field to the lowercase_name and camelcase_name maps.  Never
740   // fails because we allow duplicates; the first field by the name wins.
741   void AddFieldByStylizedNames(const FieldDescriptor* field);
742 
743   // Populates p->first->locations_by_path_ from p->second.
744   // Unusual signature dictated by GoogleOnceDynamic.
745   static void BuildLocationsByPath(
746       std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
747 
748   // Returns the location denoted by the specified path through info,
749   // or NULL if not found.
750   // The value of info must be that of the corresponding FileDescriptor.
751   // (Conceptually a pure function, but stateful as an optimisation.)
752   const SourceCodeInfo_Location* GetSourceLocation(
753       const std::vector<int>& path, const SourceCodeInfo* info) const;
754 
755  private:
756   SymbolsByParentMap    symbols_by_parent_;
757   FieldsByNameMap       fields_by_lowercase_name_;
758   FieldsByNameMap       fields_by_camelcase_name_;
759   FieldsByNumberMap     fields_by_number_;       // Not including extensions.
760   EnumValuesByNumberMap enum_values_by_number_;
761   mutable EnumValuesByNumberMap unknown_enum_values_by_number_
762       GOOGLE_GUARDED_BY(unknown_enum_values_mu_);
763 
764   // Populated on first request to save space, hence constness games.
765   mutable GoogleOnceDynamic locations_by_path_once_;
766   mutable LocationsByPathMap locations_by_path_;
767 
768   // Mutex to protect the unknown-enum-value map due to dynamic
769   // EnumValueDescriptor creation on unknown values.
770   mutable Mutex unknown_enum_values_mu_;
771 };
772 
Tables()773 DescriptorPool::Tables::Tables()
774     // Start some hash_map and hash_set objects with a small # of buckets
775     : known_bad_files_(3),
776       known_bad_symbols_(3),
777       extensions_loaded_from_db_(3),
778       symbols_by_name_(3),
779       files_by_name_(3) {}
780 
781 
~Tables()782 DescriptorPool::Tables::~Tables() {
783   GOOGLE_DCHECK(checkpoints_.empty());
784   // Note that the deletion order is important, since the destructors of some
785   // messages may refer to objects in allocations_.
786   STLDeleteElements(&messages_);
787   for (int i = 0; i < allocations_.size(); i++) {
788     operator delete(allocations_[i]);
789   }
790   STLDeleteElements(&strings_);
791   STLDeleteElements(&file_tables_);
792   STLDeleteElements(&once_dynamics_);
793 }
794 
FileDescriptorTables()795 FileDescriptorTables::FileDescriptorTables()
796     // Initialize all the hash tables to start out with a small # of buckets
797     : symbols_by_parent_(3),
798       fields_by_lowercase_name_(3),
799       fields_by_camelcase_name_(3),
800       fields_by_number_(3),
801       enum_values_by_number_(3),
802       unknown_enum_values_by_number_(3) {
803 }
804 
~FileDescriptorTables()805 FileDescriptorTables::~FileDescriptorTables() {}
806 
807 namespace {
808 
809 FileDescriptorTables* file_descriptor_tables_ = NULL;
810 GOOGLE_PROTOBUF_DECLARE_ONCE(file_descriptor_tables_once_init_);
811 
DeleteFileDescriptorTables()812 void DeleteFileDescriptorTables() {
813   delete file_descriptor_tables_;
814   file_descriptor_tables_ = NULL;
815 }
816 
InitFileDescriptorTables()817 void InitFileDescriptorTables() {
818   file_descriptor_tables_ = new FileDescriptorTables();
819   internal::OnShutdown(&DeleteFileDescriptorTables);
820 }
821 
InitFileDescriptorTablesOnce()822 inline void InitFileDescriptorTablesOnce() {
823   ::google::protobuf::GoogleOnceInit(
824       &file_descriptor_tables_once_init_, &InitFileDescriptorTables);
825 }
826 
827 }  // anonymous namespace
828 
GetEmptyInstance()829 inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
830   InitFileDescriptorTablesOnce();
831   return *file_descriptor_tables_;
832 }
833 
AddCheckpoint()834 void DescriptorPool::Tables::AddCheckpoint() {
835   checkpoints_.push_back(CheckPoint(this));
836 }
837 
ClearLastCheckpoint()838 void DescriptorPool::Tables::ClearLastCheckpoint() {
839   GOOGLE_DCHECK(!checkpoints_.empty());
840   checkpoints_.pop_back();
841   if (checkpoints_.empty()) {
842     // All checkpoints have been cleared: we can now commit all of the pending
843     // data.
844     symbols_after_checkpoint_.clear();
845     files_after_checkpoint_.clear();
846     extensions_after_checkpoint_.clear();
847   }
848 }
849 
RollbackToLastCheckpoint()850 void DescriptorPool::Tables::RollbackToLastCheckpoint() {
851   GOOGLE_DCHECK(!checkpoints_.empty());
852   const CheckPoint& checkpoint = checkpoints_.back();
853 
854   for (int i = checkpoint.pending_symbols_before_checkpoint;
855        i < symbols_after_checkpoint_.size();
856        i++) {
857     symbols_by_name_.erase(symbols_after_checkpoint_[i]);
858   }
859   for (int i = checkpoint.pending_files_before_checkpoint;
860        i < files_after_checkpoint_.size();
861        i++) {
862     files_by_name_.erase(files_after_checkpoint_[i]);
863   }
864   for (int i = checkpoint.pending_extensions_before_checkpoint;
865        i < extensions_after_checkpoint_.size();
866        i++) {
867     extensions_.erase(extensions_after_checkpoint_[i]);
868   }
869 
870   symbols_after_checkpoint_.resize(
871       checkpoint.pending_symbols_before_checkpoint);
872   files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
873   extensions_after_checkpoint_.resize(
874       checkpoint.pending_extensions_before_checkpoint);
875 
876   STLDeleteContainerPointers(
877       strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
878   STLDeleteContainerPointers(
879       messages_.begin() + checkpoint.messages_before_checkpoint,
880       messages_.end());
881   STLDeleteContainerPointers(
882       once_dynamics_.begin() + checkpoint.once_dynamics_before_checkpoint,
883       once_dynamics_.end());
884   STLDeleteContainerPointers(
885       file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
886       file_tables_.end());
887   for (int i = checkpoint.allocations_before_checkpoint;
888        i < allocations_.size();
889        i++) {
890     operator delete(allocations_[i]);
891   }
892 
893   strings_.resize(checkpoint.strings_before_checkpoint);
894   messages_.resize(checkpoint.messages_before_checkpoint);
895   once_dynamics_.resize(checkpoint.once_dynamics_before_checkpoint);
896   file_tables_.resize(checkpoint.file_tables_before_checkpoint);
897   allocations_.resize(checkpoint.allocations_before_checkpoint);
898   checkpoints_.pop_back();
899 }
900 
901 // -------------------------------------------------------------------
902 
FindSymbol(const string & key) const903 inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const {
904   const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
905   if (result == NULL) {
906     return kNullSymbol;
907   } else {
908     return *result;
909   }
910 }
911 
FindNestedSymbol(const void * parent,const string & name) const912 inline Symbol FileDescriptorTables::FindNestedSymbol(
913     const void* parent, const string& name) const {
914   const Symbol* result =
915     FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str()));
916   if (result == NULL) {
917     return kNullSymbol;
918   } else {
919     return *result;
920   }
921 }
922 
FindNestedSymbolOfType(const void * parent,const string & name,const Symbol::Type type) const923 inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
924     const void* parent, const string& name, const Symbol::Type type) const {
925   Symbol result = FindNestedSymbol(parent, name);
926   if (result.type != type) return kNullSymbol;
927   return result;
928 }
929 
FindByNameHelper(const DescriptorPool * pool,const string & name)930 Symbol DescriptorPool::Tables::FindByNameHelper(
931     const DescriptorPool* pool, const string& name) {
932   MutexLockMaybe lock(pool->mutex_);
933   known_bad_symbols_.clear();
934   known_bad_files_.clear();
935   Symbol result = FindSymbol(name);
936 
937   if (result.IsNull() && pool->underlay_ != NULL) {
938     // Symbol not found; check the underlay.
939     result =
940       pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
941   }
942 
943   if (result.IsNull()) {
944     // Symbol still not found, so check fallback database.
945     if (pool->TryFindSymbolInFallbackDatabase(name)) {
946       result = FindSymbol(name);
947     }
948   }
949 
950   return result;
951 }
952 
FindFile(const string & key) const953 inline const FileDescriptor* DescriptorPool::Tables::FindFile(
954     const string& key) const {
955   return FindPtrOrNull(files_by_name_, key.c_str());
956 }
957 
FindFieldByNumber(const Descriptor * parent,int number) const958 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
959     const Descriptor* parent, int number) const {
960   return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
961 }
962 
FindFieldByLowercaseName(const void * parent,const string & lowercase_name) const963 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
964     const void* parent, const string& lowercase_name) const {
965   return FindPtrOrNull(fields_by_lowercase_name_,
966                        PointerStringPair(parent, lowercase_name.c_str()));
967 }
968 
FindFieldByCamelcaseName(const void * parent,const string & camelcase_name) const969 inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
970     const void* parent, const string& camelcase_name) const {
971   return FindPtrOrNull(fields_by_camelcase_name_,
972                        PointerStringPair(parent, camelcase_name.c_str()));
973 }
974 
FindEnumValueByNumber(const EnumDescriptor * parent,int number) const975 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
976     const EnumDescriptor* parent, int number) const {
977   return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
978 }
979 
980 inline const EnumValueDescriptor*
FindEnumValueByNumberCreatingIfUnknown(const EnumDescriptor * parent,int number) const981 FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
982     const EnumDescriptor* parent, int number) const {
983   // First try, with map of compiled-in values.
984   {
985     const EnumValueDescriptor* desc =
986         FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
987     if (desc != NULL) {
988       return desc;
989     }
990   }
991   // Second try, with reader lock held on unknown enum values: common case.
992   {
993     ReaderMutexLock l(&unknown_enum_values_mu_);
994     const EnumValueDescriptor* desc = FindPtrOrNull(
995         unknown_enum_values_by_number_, std::make_pair(parent, number));
996     if (desc != NULL) {
997       return desc;
998     }
999   }
1000   // If not found, try again with writer lock held, and create new descriptor if
1001   // necessary.
1002   {
1003     WriterMutexLock l(&unknown_enum_values_mu_);
1004     const EnumValueDescriptor* desc = FindPtrOrNull(
1005         unknown_enum_values_by_number_, std::make_pair(parent, number));
1006     if (desc != NULL) {
1007       return desc;
1008     }
1009 
1010     // Create an EnumValueDescriptor dynamically. We don't insert it into the
1011     // EnumDescriptor (it's not a part of the enum as originally defined), but
1012     // we do insert it into the table so that we can return the same pointer
1013     // later.
1014     string enum_value_name = StringPrintf(
1015         "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
1016     DescriptorPool::Tables* tables =
1017         const_cast<DescriptorPool::Tables*>(DescriptorPool::generated_pool()->
1018                                             tables_.get());
1019     EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
1020     result->name_ = tables->AllocateString(enum_value_name);
1021     result->full_name_ = tables->AllocateString(parent->full_name() +
1022                                                 "." + enum_value_name);
1023     result->number_ = number;
1024     result->type_ = parent;
1025     result->options_ = &EnumValueOptions::default_instance();
1026     InsertIfNotPresent(&unknown_enum_values_by_number_,
1027                        std::make_pair(parent, number), result);
1028     return result;
1029   }
1030 }
1031 
1032 
FindExtension(const Descriptor * extendee,int number)1033 inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1034     const Descriptor* extendee, int number) {
1035   return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
1036 }
1037 
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1038 inline void DescriptorPool::Tables::FindAllExtensions(
1039     const Descriptor* extendee,
1040     std::vector<const FieldDescriptor*>* out) const {
1041   ExtensionsGroupedByDescriptorMap::const_iterator it =
1042       extensions_.lower_bound(std::make_pair(extendee, 0));
1043   for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1044     out->push_back(it->second);
1045   }
1046 }
1047 
1048 // -------------------------------------------------------------------
1049 
AddSymbol(const string & full_name,Symbol symbol)1050 bool DescriptorPool::Tables::AddSymbol(
1051     const string& full_name, Symbol symbol) {
1052   if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
1053     symbols_after_checkpoint_.push_back(full_name.c_str());
1054     return true;
1055   } else {
1056     return false;
1057   }
1058 }
1059 
AddAliasUnderParent(const void * parent,const string & name,Symbol symbol)1060 bool FileDescriptorTables::AddAliasUnderParent(
1061     const void* parent, const string& name, Symbol symbol) {
1062   PointerStringPair by_parent_key(parent, name.c_str());
1063   return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
1064 }
1065 
AddFile(const FileDescriptor * file)1066 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1067   if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
1068     files_after_checkpoint_.push_back(file->name().c_str());
1069     return true;
1070   } else {
1071     return false;
1072   }
1073 }
1074 
AddFieldByStylizedNames(const FieldDescriptor * field)1075 void FileDescriptorTables::AddFieldByStylizedNames(
1076     const FieldDescriptor* field) {
1077   const void* parent;
1078   if (field->is_extension()) {
1079     if (field->extension_scope() == NULL) {
1080       parent = field->file();
1081     } else {
1082       parent = field->extension_scope();
1083     }
1084   } else {
1085     parent = field->containing_type();
1086   }
1087 
1088   PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
1089   InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field);
1090 
1091   PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
1092   InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field);
1093 }
1094 
AddFieldByNumber(const FieldDescriptor * field)1095 bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
1096   DescriptorIntPair key(field->containing_type(), field->number());
1097   return InsertIfNotPresent(&fields_by_number_, key, field);
1098 }
1099 
AddEnumValueByNumber(const EnumValueDescriptor * value)1100 bool FileDescriptorTables::AddEnumValueByNumber(
1101     const EnumValueDescriptor* value) {
1102   EnumIntPair key(value->type(), value->number());
1103   return InsertIfNotPresent(&enum_values_by_number_, key, value);
1104 }
1105 
AddExtension(const FieldDescriptor * field)1106 bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1107   DescriptorIntPair key(field->containing_type(), field->number());
1108   if (InsertIfNotPresent(&extensions_, key, field)) {
1109     extensions_after_checkpoint_.push_back(key);
1110     return true;
1111   } else {
1112     return false;
1113   }
1114 }
1115 
1116 // -------------------------------------------------------------------
1117 
1118 template<typename Type>
Allocate()1119 Type* DescriptorPool::Tables::Allocate() {
1120   return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type)));
1121 }
1122 
1123 template<typename Type>
AllocateArray(int count)1124 Type* DescriptorPool::Tables::AllocateArray(int count) {
1125   return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
1126 }
1127 
AllocateString(const string & value)1128 string* DescriptorPool::Tables::AllocateString(const string& value) {
1129   string* result = new string(value);
1130   strings_.push_back(result);
1131   return result;
1132 }
1133 
AllocateOnceDynamic()1134 GoogleOnceDynamic* DescriptorPool::Tables::AllocateOnceDynamic() {
1135   GoogleOnceDynamic* result = new GoogleOnceDynamic();
1136   once_dynamics_.push_back(result);
1137   return result;
1138 }
1139 
1140 template<typename Type>
AllocateMessage(Type *)1141 Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) {
1142   Type* result = new Type;
1143   messages_.push_back(result);
1144   return result;
1145 }
1146 
AllocateFileTables()1147 FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
1148   FileDescriptorTables* result = new FileDescriptorTables;
1149   file_tables_.push_back(result);
1150   return result;
1151 }
1152 
AllocateBytes(int size)1153 void* DescriptorPool::Tables::AllocateBytes(int size) {
1154   // TODO(kenton):  Would it be worthwhile to implement this in some more
1155   // sophisticated way?  Probably not for the open source release, but for
1156   // internal use we could easily plug in one of our existing memory pool
1157   // allocators...
1158   if (size == 0) return NULL;
1159 
1160   void* result = operator new(size);
1161   allocations_.push_back(result);
1162   return result;
1163 }
1164 
BuildLocationsByPath(std::pair<const FileDescriptorTables *,const SourceCodeInfo * > * p)1165 void FileDescriptorTables::BuildLocationsByPath(
1166     std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1167   for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1168     const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1169     p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
1170   }
1171 }
1172 
GetSourceLocation(const std::vector<int> & path,const SourceCodeInfo * info) const1173 const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1174     const std::vector<int>& path, const SourceCodeInfo* info) const {
1175   std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1176       std::make_pair(this, info));
1177   locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
1178   return FindPtrOrNull(locations_by_path_, Join(path, ","));
1179 }
1180 
1181 // ===================================================================
1182 // DescriptorPool
1183 
~ErrorCollector()1184 DescriptorPool::ErrorCollector::~ErrorCollector() {}
1185 
DescriptorPool()1186 DescriptorPool::DescriptorPool()
1187   : mutex_(NULL),
1188     fallback_database_(NULL),
1189     default_error_collector_(NULL),
1190     underlay_(NULL),
1191     tables_(new Tables),
1192     enforce_dependencies_(true),
1193     lazily_build_dependencies_(false),
1194     allow_unknown_(false),
1195     enforce_weak_(false),
1196     disallow_enforce_utf8_(false) {}
1197 
DescriptorPool(DescriptorDatabase * fallback_database,ErrorCollector * error_collector)1198 DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1199                                ErrorCollector* error_collector)
1200   : mutex_(new Mutex),
1201     fallback_database_(fallback_database),
1202     default_error_collector_(error_collector),
1203     underlay_(NULL),
1204     tables_(new Tables),
1205     enforce_dependencies_(true),
1206     lazily_build_dependencies_(false),
1207     allow_unknown_(false),
1208     enforce_weak_(false),
1209     disallow_enforce_utf8_(false) {
1210 }
1211 
DescriptorPool(const DescriptorPool * underlay)1212 DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1213   : mutex_(NULL),
1214     fallback_database_(NULL),
1215     default_error_collector_(NULL),
1216     underlay_(underlay),
1217     tables_(new Tables),
1218     enforce_dependencies_(true),
1219     lazily_build_dependencies_(false),
1220     allow_unknown_(false),
1221     enforce_weak_(false),
1222     disallow_enforce_utf8_(false) {}
1223 
~DescriptorPool()1224 DescriptorPool::~DescriptorPool() {
1225   if (mutex_ != NULL) delete mutex_;
1226 }
1227 
1228 // DescriptorPool::BuildFile() defined later.
1229 // DescriptorPool::BuildFileCollectingErrors() defined later.
1230 
InternalDontEnforceDependencies()1231 void DescriptorPool::InternalDontEnforceDependencies() {
1232   enforce_dependencies_ = false;
1233 }
1234 
AddUnusedImportTrackFile(const string & file_name)1235 void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) {
1236   unused_import_track_files_.insert(file_name);
1237 }
1238 
ClearUnusedImportTrackFiles()1239 void DescriptorPool::ClearUnusedImportTrackFiles() {
1240   unused_import_track_files_.clear();
1241 }
1242 
InternalIsFileLoaded(const string & filename) const1243 bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
1244   MutexLockMaybe lock(mutex_);
1245   return tables_->FindFile(filename) != NULL;
1246 }
1247 
1248 // generated_pool ====================================================
1249 
1250 namespace {
1251 
1252 
1253 EncodedDescriptorDatabase* generated_database_ = NULL;
1254 DescriptorPool* generated_pool_ = NULL;
1255 GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
1256 
DeleteGeneratedPool()1257 void DeleteGeneratedPool() {
1258   delete generated_database_;
1259   generated_database_ = NULL;
1260   delete generated_pool_;
1261   generated_pool_ = NULL;
1262 }
1263 
InitGeneratedPool()1264 static void InitGeneratedPool() {
1265   generated_database_ = new EncodedDescriptorDatabase;
1266   generated_pool_ = new DescriptorPool(generated_database_);
1267   generated_pool_->InternalSetLazilyBuildDependencies();
1268 
1269   internal::OnShutdown(&DeleteGeneratedPool);
1270 }
1271 
InitGeneratedPoolOnce()1272 inline void InitGeneratedPoolOnce() {
1273   ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
1274 }
1275 
1276 }  // anonymous namespace
1277 
generated_pool()1278 const DescriptorPool* DescriptorPool::generated_pool() {
1279   InitGeneratedPoolOnce();
1280   return generated_pool_;
1281 }
1282 
1283 
1284 
internal_generated_pool()1285 DescriptorPool* DescriptorPool::internal_generated_pool() {
1286   InitGeneratedPoolOnce();
1287   return generated_pool_;
1288 }
1289 
InternalAddGeneratedFile(const void * encoded_file_descriptor,int size)1290 void DescriptorPool::InternalAddGeneratedFile(
1291     const void* encoded_file_descriptor, int size) {
1292   // So, this function is called in the process of initializing the
1293   // descriptors for generated proto classes.  Each generated .pb.cc file
1294   // has an internal procedure called AddDescriptors() which is called at
1295   // process startup, and that function calls this one in order to register
1296   // the raw bytes of the FileDescriptorProto representing the file.
1297   //
1298   // We do not actually construct the descriptor objects right away.  We just
1299   // hang on to the bytes until they are actually needed.  We actually construct
1300   // the descriptor the first time one of the following things happens:
1301   // * Someone calls a method like descriptor(), GetDescriptor(), or
1302   //   GetReflection() on the generated types, which requires returning the
1303   //   descriptor or an object based on it.
1304   // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1305   //
1306   // Once one of these happens, the DescriptorPool actually parses the
1307   // FileDescriptorProto and generates a FileDescriptor (and all its children)
1308   // based on it.
1309   //
1310   // Note that FileDescriptorProto is itself a generated protocol message.
1311   // Therefore, when we parse one, we have to be very careful to avoid using
1312   // any descriptor-based operations, since this might cause infinite recursion
1313   // or deadlock.
1314   InitGeneratedPoolOnce();
1315   GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
1316 }
1317 
1318 
1319 // Find*By* methods ==================================================
1320 
1321 // TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
1322 //   there's any good way to factor it out.  Think about this some time when
1323 //   there's nothing more important to do (read: never).
1324 
FindFileByName(const string & name) const1325 const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
1326   MutexLockMaybe lock(mutex_);
1327   tables_->known_bad_symbols_.clear();
1328   tables_->known_bad_files_.clear();
1329   const FileDescriptor* result = tables_->FindFile(name);
1330   if (result != NULL) return result;
1331   if (underlay_ != NULL) {
1332     result = underlay_->FindFileByName(name);
1333     if (result != NULL) return result;
1334   }
1335   if (TryFindFileInFallbackDatabase(name)) {
1336     result = tables_->FindFile(name);
1337     if (result != NULL) return result;
1338   }
1339   return NULL;
1340 }
1341 
FindFileContainingSymbol(const string & symbol_name) const1342 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
1343     const string& symbol_name) const {
1344   MutexLockMaybe lock(mutex_);
1345   tables_->known_bad_symbols_.clear();
1346   tables_->known_bad_files_.clear();
1347   Symbol result = tables_->FindSymbol(symbol_name);
1348   if (!result.IsNull()) return result.GetFile();
1349   if (underlay_ != NULL) {
1350     const FileDescriptor* file_result =
1351       underlay_->FindFileContainingSymbol(symbol_name);
1352     if (file_result != NULL) return file_result;
1353   }
1354   if (TryFindSymbolInFallbackDatabase(symbol_name)) {
1355     result = tables_->FindSymbol(symbol_name);
1356     if (!result.IsNull()) return result.GetFile();
1357   }
1358   return NULL;
1359 }
1360 
FindMessageTypeByName(const string & name) const1361 const Descriptor* DescriptorPool::FindMessageTypeByName(
1362     const string& name) const {
1363   Symbol result = tables_->FindByNameHelper(this, name);
1364   return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL;
1365 }
1366 
FindFieldByName(const string & name) const1367 const FieldDescriptor* DescriptorPool::FindFieldByName(
1368     const string& name) const {
1369   Symbol result = tables_->FindByNameHelper(this, name);
1370   if (result.type == Symbol::FIELD &&
1371       !result.field_descriptor->is_extension()) {
1372     return result.field_descriptor;
1373   } else {
1374     return NULL;
1375   }
1376 }
1377 
FindExtensionByName(const string & name) const1378 const FieldDescriptor* DescriptorPool::FindExtensionByName(
1379     const string& name) const {
1380   Symbol result = tables_->FindByNameHelper(this, name);
1381   if (result.type == Symbol::FIELD &&
1382       result.field_descriptor->is_extension()) {
1383     return result.field_descriptor;
1384   } else {
1385     return NULL;
1386   }
1387 }
1388 
FindOneofByName(const string & name) const1389 const OneofDescriptor* DescriptorPool::FindOneofByName(
1390     const string& name) const {
1391   Symbol result = tables_->FindByNameHelper(this, name);
1392   return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL;
1393 }
1394 
FindEnumTypeByName(const string & name) const1395 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
1396     const string& name) const {
1397   Symbol result = tables_->FindByNameHelper(this, name);
1398   return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL;
1399 }
1400 
FindEnumValueByName(const string & name) const1401 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
1402     const string& name) const {
1403   Symbol result = tables_->FindByNameHelper(this, name);
1404   return (result.type == Symbol::ENUM_VALUE) ?
1405     result.enum_value_descriptor : NULL;
1406 }
1407 
FindServiceByName(const string & name) const1408 const ServiceDescriptor* DescriptorPool::FindServiceByName(
1409     const string& name) const {
1410   Symbol result = tables_->FindByNameHelper(this, name);
1411   return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL;
1412 }
1413 
FindMethodByName(const string & name) const1414 const MethodDescriptor* DescriptorPool::FindMethodByName(
1415     const string& name) const {
1416   Symbol result = tables_->FindByNameHelper(this, name);
1417   return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL;
1418 }
1419 
FindExtensionByNumber(const Descriptor * extendee,int number) const1420 const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
1421     const Descriptor* extendee, int number) const {
1422   MutexLockMaybe lock(mutex_);
1423   tables_->known_bad_symbols_.clear();
1424   tables_->known_bad_files_.clear();
1425   const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1426   if (result != NULL) {
1427     return result;
1428   }
1429   if (underlay_ != NULL) {
1430     result = underlay_->FindExtensionByNumber(extendee, number);
1431     if (result != NULL) return result;
1432   }
1433   if (TryFindExtensionInFallbackDatabase(extendee, number)) {
1434     result = tables_->FindExtension(extendee, number);
1435     if (result != NULL) {
1436       return result;
1437     }
1438   }
1439   return NULL;
1440 }
1441 
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1442 void DescriptorPool::FindAllExtensions(
1443     const Descriptor* extendee,
1444     std::vector<const FieldDescriptor*>* out) const {
1445   MutexLockMaybe lock(mutex_);
1446   tables_->known_bad_symbols_.clear();
1447   tables_->known_bad_files_.clear();
1448 
1449   // Initialize tables_->extensions_ from the fallback database first
1450   // (but do this only once per descriptor).
1451   if (fallback_database_ != NULL &&
1452       tables_->extensions_loaded_from_db_.count(extendee) == 0) {
1453     std::vector<int> numbers;
1454     if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
1455                                                     &numbers)) {
1456       for (int i = 0; i < numbers.size(); ++i) {
1457         int number = numbers[i];
1458         if (tables_->FindExtension(extendee, number) == NULL) {
1459           TryFindExtensionInFallbackDatabase(extendee, number);
1460         }
1461       }
1462       tables_->extensions_loaded_from_db_.insert(extendee);
1463     }
1464   }
1465 
1466   tables_->FindAllExtensions(extendee, out);
1467   if (underlay_ != NULL) {
1468     underlay_->FindAllExtensions(extendee, out);
1469   }
1470 }
1471 
1472 
1473 // -------------------------------------------------------------------
1474 
1475 const FieldDescriptor*
FindFieldByNumber(int key) const1476 Descriptor::FindFieldByNumber(int key) const {
1477   const FieldDescriptor* result =
1478     file()->tables_->FindFieldByNumber(this, key);
1479   if (result == NULL || result->is_extension()) {
1480     return NULL;
1481   } else {
1482     return result;
1483   }
1484 }
1485 
1486 const FieldDescriptor*
FindFieldByLowercaseName(const string & key) const1487 Descriptor::FindFieldByLowercaseName(const string& key) const {
1488   const FieldDescriptor* result =
1489     file()->tables_->FindFieldByLowercaseName(this, key);
1490   if (result == NULL || result->is_extension()) {
1491     return NULL;
1492   } else {
1493     return result;
1494   }
1495 }
1496 
1497 const FieldDescriptor*
FindFieldByCamelcaseName(const string & key) const1498 Descriptor::FindFieldByCamelcaseName(const string& key) const {
1499   const FieldDescriptor* result =
1500     file()->tables_->FindFieldByCamelcaseName(this, key);
1501   if (result == NULL || result->is_extension()) {
1502     return NULL;
1503   } else {
1504     return result;
1505   }
1506 }
1507 
1508 const FieldDescriptor*
FindFieldByName(const string & key) const1509 Descriptor::FindFieldByName(const string& key) const {
1510   Symbol result =
1511     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1512   if (!result.IsNull() && !result.field_descriptor->is_extension()) {
1513     return result.field_descriptor;
1514   } else {
1515     return NULL;
1516   }
1517 }
1518 
1519 const OneofDescriptor*
FindOneofByName(const string & key) const1520 Descriptor::FindOneofByName(const string& key) const {
1521   Symbol result =
1522     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
1523   if (!result.IsNull()) {
1524     return result.oneof_descriptor;
1525   } else {
1526     return NULL;
1527   }
1528 }
1529 
1530 const FieldDescriptor*
FindExtensionByName(const string & key) const1531 Descriptor::FindExtensionByName(const string& key) const {
1532   Symbol result =
1533     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1534   if (!result.IsNull() && result.field_descriptor->is_extension()) {
1535     return result.field_descriptor;
1536   } else {
1537     return NULL;
1538   }
1539 }
1540 
1541 const FieldDescriptor*
FindExtensionByLowercaseName(const string & key) const1542 Descriptor::FindExtensionByLowercaseName(const string& key) const {
1543   const FieldDescriptor* result =
1544     file()->tables_->FindFieldByLowercaseName(this, key);
1545   if (result == NULL || !result->is_extension()) {
1546     return NULL;
1547   } else {
1548     return result;
1549   }
1550 }
1551 
1552 const FieldDescriptor*
FindExtensionByCamelcaseName(const string & key) const1553 Descriptor::FindExtensionByCamelcaseName(const string& key) const {
1554   const FieldDescriptor* result =
1555     file()->tables_->FindFieldByCamelcaseName(this, key);
1556   if (result == NULL || !result->is_extension()) {
1557     return NULL;
1558   } else {
1559     return result;
1560   }
1561 }
1562 
1563 const Descriptor*
FindNestedTypeByName(const string & key) const1564 Descriptor::FindNestedTypeByName(const string& key) const {
1565   Symbol result =
1566     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1567   if (!result.IsNull()) {
1568     return result.descriptor;
1569   } else {
1570     return NULL;
1571   }
1572 }
1573 
1574 const EnumDescriptor*
FindEnumTypeByName(const string & key) const1575 Descriptor::FindEnumTypeByName(const string& key) const {
1576   Symbol result =
1577     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1578   if (!result.IsNull()) {
1579     return result.enum_descriptor;
1580   } else {
1581     return NULL;
1582   }
1583 }
1584 
1585 const EnumValueDescriptor*
FindEnumValueByName(const string & key) const1586 Descriptor::FindEnumValueByName(const string& key) const {
1587   Symbol result =
1588     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1589   if (!result.IsNull()) {
1590     return result.enum_value_descriptor;
1591   } else {
1592     return NULL;
1593   }
1594 }
1595 
1596 const EnumValueDescriptor*
FindValueByName(const string & key) const1597 EnumDescriptor::FindValueByName(const string& key) const {
1598   Symbol result =
1599     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1600   if (!result.IsNull()) {
1601     return result.enum_value_descriptor;
1602   } else {
1603     return NULL;
1604   }
1605 }
1606 
1607 const EnumValueDescriptor*
FindValueByNumber(int key) const1608 EnumDescriptor::FindValueByNumber(int key) const {
1609   return file()->tables_->FindEnumValueByNumber(this, key);
1610 }
1611 
1612 const EnumValueDescriptor*
FindValueByNumberCreatingIfUnknown(int key) const1613 EnumDescriptor::FindValueByNumberCreatingIfUnknown(int key) const {
1614   return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
1615 }
1616 
1617 const MethodDescriptor*
FindMethodByName(const string & key) const1618 ServiceDescriptor::FindMethodByName(const string& key) const {
1619   Symbol result =
1620     file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
1621   if (!result.IsNull()) {
1622     return result.method_descriptor;
1623   } else {
1624     return NULL;
1625   }
1626 }
1627 
1628 const Descriptor*
FindMessageTypeByName(const string & key) const1629 FileDescriptor::FindMessageTypeByName(const string& key) const {
1630   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1631   if (!result.IsNull()) {
1632     return result.descriptor;
1633   } else {
1634     return NULL;
1635   }
1636 }
1637 
1638 const EnumDescriptor*
FindEnumTypeByName(const string & key) const1639 FileDescriptor::FindEnumTypeByName(const string& key) const {
1640   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1641   if (!result.IsNull()) {
1642     return result.enum_descriptor;
1643   } else {
1644     return NULL;
1645   }
1646 }
1647 
1648 const EnumValueDescriptor*
FindEnumValueByName(const string & key) const1649 FileDescriptor::FindEnumValueByName(const string& key) const {
1650   Symbol result =
1651     tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1652   if (!result.IsNull()) {
1653     return result.enum_value_descriptor;
1654   } else {
1655     return NULL;
1656   }
1657 }
1658 
1659 const ServiceDescriptor*
FindServiceByName(const string & key) const1660 FileDescriptor::FindServiceByName(const string& key) const {
1661   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
1662   if (!result.IsNull()) {
1663     return result.service_descriptor;
1664   } else {
1665     return NULL;
1666   }
1667 }
1668 
1669 const FieldDescriptor*
FindExtensionByName(const string & key) const1670 FileDescriptor::FindExtensionByName(const string& key) const {
1671   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1672   if (!result.IsNull() && result.field_descriptor->is_extension()) {
1673     return result.field_descriptor;
1674   } else {
1675     return NULL;
1676   }
1677 }
1678 
1679 const FieldDescriptor*
FindExtensionByLowercaseName(const string & key) const1680 FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
1681   const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
1682   if (result == NULL || !result->is_extension()) {
1683     return NULL;
1684   } else {
1685     return result;
1686   }
1687 }
1688 
1689 const FieldDescriptor*
FindExtensionByCamelcaseName(const string & key) const1690 FileDescriptor::FindExtensionByCamelcaseName(const string& key) const {
1691   const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
1692   if (result == NULL || !result->is_extension()) {
1693     return NULL;
1694   } else {
1695     return result;
1696   }
1697 }
1698 
1699 const Descriptor::ExtensionRange*
FindExtensionRangeContainingNumber(int number) const1700 Descriptor::FindExtensionRangeContainingNumber(int number) const {
1701   // Linear search should be fine because we don't expect a message to have
1702   // more than a couple extension ranges.
1703   for (int i = 0; i < extension_range_count(); i++) {
1704     if (number >= extension_range(i)->start &&
1705         number <  extension_range(i)->end) {
1706       return extension_range(i);
1707     }
1708   }
1709   return NULL;
1710 }
1711 
1712 const Descriptor::ReservedRange*
FindReservedRangeContainingNumber(int number) const1713 Descriptor::FindReservedRangeContainingNumber(int number) const {
1714   // TODO(chrisn): Consider a non-linear search.
1715   for (int i = 0; i < reserved_range_count(); i++) {
1716     if (number >= reserved_range(i)->start &&
1717         number <  reserved_range(i)->end) {
1718       return reserved_range(i);
1719     }
1720   }
1721   return NULL;
1722 }
1723 
1724 // -------------------------------------------------------------------
1725 
TryFindFileInFallbackDatabase(const string & name) const1726 bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
1727   if (fallback_database_ == NULL) return false;
1728 
1729   if (tables_->known_bad_files_.count(name) > 0) return false;
1730 
1731   FileDescriptorProto file_proto;
1732   if (!fallback_database_->FindFileByName(name, &file_proto) ||
1733       BuildFileFromDatabase(file_proto) == NULL) {
1734     tables_->known_bad_files_.insert(name);
1735     return false;
1736   }
1737   return true;
1738 }
1739 
IsSubSymbolOfBuiltType(const string & name) const1740 bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
1741   string prefix = name;
1742   for (;;) {
1743     string::size_type dot_pos = prefix.find_last_of('.');
1744     if (dot_pos == string::npos) {
1745       break;
1746     }
1747     prefix = prefix.substr(0, dot_pos);
1748     Symbol symbol = tables_->FindSymbol(prefix);
1749     // If the symbol type is anything other than PACKAGE, then its complete
1750     // definition is already known.
1751     if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
1752       return true;
1753     }
1754   }
1755   if (underlay_ != NULL) {
1756     // Check to see if any prefix of this symbol exists in the underlay.
1757     return underlay_->IsSubSymbolOfBuiltType(name);
1758   }
1759   return false;
1760 }
1761 
TryFindSymbolInFallbackDatabase(const string & name) const1762 bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
1763   if (fallback_database_ == NULL) return false;
1764 
1765   if (tables_->known_bad_symbols_.count(name) > 0) return false;
1766 
1767   FileDescriptorProto file_proto;
1768   if (// We skip looking in the fallback database if the name is a sub-symbol
1769       // of any descriptor that already exists in the descriptor pool (except
1770       // for package descriptors).  This is valid because all symbols except
1771       // for packages are defined in a single file, so if the symbol exists
1772       // then we should already have its definition.
1773       //
1774       // The other reason to do this is to support "overriding" type
1775       // definitions by merging two databases that define the same type.  (Yes,
1776       // people do this.)  The main difficulty with making this work is that
1777       // FindFileContainingSymbol() is allowed to return both false positives
1778       // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
1779       // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
1780       // When two such databases are merged, looking up a non-existent
1781       // sub-symbol of a type that already exists in the descriptor pool can
1782       // result in an attempt to load multiple definitions of the same type.
1783       // The check below avoids this.
1784       IsSubSymbolOfBuiltType(name)
1785 
1786       // Look up file containing this symbol in fallback database.
1787       || !fallback_database_->FindFileContainingSymbol(name, &file_proto)
1788 
1789       // Check if we've already built this file. If so, it apparently doesn't
1790       // contain the symbol we're looking for.  Some DescriptorDatabases
1791       // return false positives.
1792       || tables_->FindFile(file_proto.name()) != NULL
1793 
1794       // Build the file.
1795       || BuildFileFromDatabase(file_proto) == NULL) {
1796     tables_->known_bad_symbols_.insert(name);
1797     return false;
1798   }
1799 
1800   return true;
1801 }
1802 
TryFindExtensionInFallbackDatabase(const Descriptor * containing_type,int field_number) const1803 bool DescriptorPool::TryFindExtensionInFallbackDatabase(
1804     const Descriptor* containing_type, int field_number) const {
1805   if (fallback_database_ == NULL) return false;
1806 
1807   FileDescriptorProto file_proto;
1808   if (!fallback_database_->FindFileContainingExtension(
1809         containing_type->full_name(), field_number, &file_proto)) {
1810     return false;
1811   }
1812 
1813   if (tables_->FindFile(file_proto.name()) != NULL) {
1814     // We've already loaded this file, and it apparently doesn't contain the
1815     // extension we're looking for.  Some DescriptorDatabases return false
1816     // positives.
1817     return false;
1818   }
1819 
1820   if (BuildFileFromDatabase(file_proto) == NULL) {
1821     return false;
1822   }
1823 
1824   return true;
1825 }
1826 
1827 // ===================================================================
1828 
is_map() const1829 bool FieldDescriptor::is_map() const {
1830   return type() == TYPE_MESSAGE && message_type()->options().map_entry();
1831 }
1832 
DefaultValueAsString(bool quote_string_type) const1833 string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
1834   GOOGLE_CHECK(has_default_value()) << "No default value";
1835   switch (cpp_type()) {
1836     case CPPTYPE_INT32:
1837       return SimpleItoa(default_value_int32());
1838       break;
1839     case CPPTYPE_INT64:
1840       return SimpleItoa(default_value_int64());
1841       break;
1842     case CPPTYPE_UINT32:
1843       return SimpleItoa(default_value_uint32());
1844       break;
1845     case CPPTYPE_UINT64:
1846       return SimpleItoa(default_value_uint64());
1847       break;
1848     case CPPTYPE_FLOAT:
1849       return SimpleFtoa(default_value_float());
1850       break;
1851     case CPPTYPE_DOUBLE:
1852       return SimpleDtoa(default_value_double());
1853       break;
1854     case CPPTYPE_BOOL:
1855       return default_value_bool() ? "true" : "false";
1856       break;
1857     case CPPTYPE_STRING:
1858       if (quote_string_type) {
1859         return "\"" + CEscape(default_value_string()) + "\"";
1860       } else {
1861         if (type() == TYPE_BYTES) {
1862           return CEscape(default_value_string());
1863         } else {
1864           return default_value_string();
1865         }
1866       }
1867       break;
1868     case CPPTYPE_ENUM:
1869       return default_value_enum()->name();
1870       break;
1871     case CPPTYPE_MESSAGE:
1872       GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
1873       break;
1874   }
1875   GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string";
1876   return "";
1877 }
1878 
1879 // CopyTo methods ====================================================
1880 
CopyTo(FileDescriptorProto * proto) const1881 void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
1882   proto->set_name(name());
1883   if (!package().empty()) proto->set_package(package());
1884   // TODO(liujisi): Also populate when syntax="proto2".
1885   if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
1886 
1887   for (int i = 0; i < dependency_count(); i++) {
1888     proto->add_dependency(dependency(i)->name());
1889   }
1890 
1891   for (int i = 0; i < public_dependency_count(); i++) {
1892     proto->add_public_dependency(public_dependencies_[i]);
1893   }
1894 
1895   for (int i = 0; i < weak_dependency_count(); i++) {
1896     proto->add_weak_dependency(weak_dependencies_[i]);
1897   }
1898 
1899   for (int i = 0; i < message_type_count(); i++) {
1900     message_type(i)->CopyTo(proto->add_message_type());
1901   }
1902   for (int i = 0; i < enum_type_count(); i++) {
1903     enum_type(i)->CopyTo(proto->add_enum_type());
1904   }
1905   for (int i = 0; i < service_count(); i++) {
1906     service(i)->CopyTo(proto->add_service());
1907   }
1908   for (int i = 0; i < extension_count(); i++) {
1909     extension(i)->CopyTo(proto->add_extension());
1910   }
1911 
1912   if (&options() != &FileOptions::default_instance()) {
1913     proto->mutable_options()->CopyFrom(options());
1914   }
1915 }
1916 
CopyJsonNameTo(FileDescriptorProto * proto) const1917 void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
1918   if (message_type_count() != proto->message_type_size() ||
1919       extension_count() != proto->extension_size()) {
1920     GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
1921     return;
1922   }
1923   for (int i = 0; i < message_type_count(); i++) {
1924     message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
1925   }
1926   for (int i = 0; i < extension_count(); i++) {
1927     extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
1928   }
1929 }
1930 
CopySourceCodeInfoTo(FileDescriptorProto * proto) const1931 void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
1932   if (source_code_info_ &&
1933       source_code_info_ != &SourceCodeInfo::default_instance()) {
1934     proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
1935   }
1936 }
1937 
CopyTo(DescriptorProto * proto) const1938 void Descriptor::CopyTo(DescriptorProto* proto) const {
1939   proto->set_name(name());
1940 
1941   for (int i = 0; i < field_count(); i++) {
1942     field(i)->CopyTo(proto->add_field());
1943   }
1944   for (int i = 0; i < oneof_decl_count(); i++) {
1945     oneof_decl(i)->CopyTo(proto->add_oneof_decl());
1946   }
1947   for (int i = 0; i < nested_type_count(); i++) {
1948     nested_type(i)->CopyTo(proto->add_nested_type());
1949   }
1950   for (int i = 0; i < enum_type_count(); i++) {
1951     enum_type(i)->CopyTo(proto->add_enum_type());
1952   }
1953   for (int i = 0; i < extension_range_count(); i++) {
1954     DescriptorProto::ExtensionRange* range = proto->add_extension_range();
1955     range->set_start(extension_range(i)->start);
1956     range->set_end(extension_range(i)->end);
1957     const ExtensionRangeOptions* options = extension_range(i)->options_;
1958     if (options != &ExtensionRangeOptions::default_instance()) {
1959       range->mutable_options()->CopyFrom(*options);
1960     }
1961   }
1962   for (int i = 0; i < extension_count(); i++) {
1963     extension(i)->CopyTo(proto->add_extension());
1964   }
1965   for (int i = 0; i < reserved_range_count(); i++) {
1966     DescriptorProto::ReservedRange* range = proto->add_reserved_range();
1967     range->set_start(reserved_range(i)->start);
1968     range->set_end(reserved_range(i)->end);
1969   }
1970   for (int i = 0; i < reserved_name_count(); i++) {
1971     proto->add_reserved_name(reserved_name(i));
1972   }
1973 
1974   if (&options() != &MessageOptions::default_instance()) {
1975     proto->mutable_options()->CopyFrom(options());
1976   }
1977 }
1978 
CopyJsonNameTo(DescriptorProto * proto) const1979 void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
1980   if (field_count() != proto->field_size() ||
1981       nested_type_count() != proto->nested_type_size() ||
1982       extension_count() != proto->extension_size()) {
1983     GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
1984     return;
1985   }
1986   for (int i = 0; i < field_count(); i++) {
1987     field(i)->CopyJsonNameTo(proto->mutable_field(i));
1988   }
1989   for (int i = 0; i < nested_type_count(); i++) {
1990     nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
1991   }
1992   for (int i = 0; i < extension_count(); i++) {
1993     extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
1994   }
1995 }
1996 
CopyTo(FieldDescriptorProto * proto) const1997 void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
1998   proto->set_name(name());
1999   proto->set_number(number());
2000   if (has_json_name_) {
2001     proto->set_json_name(json_name());
2002   }
2003 
2004   // Some compilers do not allow static_cast directly between two enum types,
2005   // so we must cast to int first.
2006   proto->set_label(static_cast<FieldDescriptorProto::Label>(
2007                      implicit_cast<int>(label())));
2008   proto->set_type(static_cast<FieldDescriptorProto::Type>(
2009                     implicit_cast<int>(type())));
2010 
2011   if (is_extension()) {
2012     if (!containing_type()->is_unqualified_placeholder_) {
2013       proto->set_extendee(".");
2014     }
2015     proto->mutable_extendee()->append(containing_type()->full_name());
2016   }
2017 
2018   if (cpp_type() == CPPTYPE_MESSAGE) {
2019     if (message_type()->is_placeholder_) {
2020       // We don't actually know if the type is a message type.  It could be
2021       // an enum.
2022       proto->clear_type();
2023     }
2024 
2025     if (!message_type()->is_unqualified_placeholder_) {
2026       proto->set_type_name(".");
2027     }
2028     proto->mutable_type_name()->append(message_type()->full_name());
2029   } else if (cpp_type() == CPPTYPE_ENUM) {
2030     if (!enum_type()->is_unqualified_placeholder_) {
2031       proto->set_type_name(".");
2032     }
2033     proto->mutable_type_name()->append(enum_type()->full_name());
2034   }
2035 
2036   if (has_default_value()) {
2037     proto->set_default_value(DefaultValueAsString(false));
2038   }
2039 
2040   if (containing_oneof() != NULL && !is_extension()) {
2041     proto->set_oneof_index(containing_oneof()->index());
2042   }
2043 
2044   if (&options() != &FieldOptions::default_instance()) {
2045     proto->mutable_options()->CopyFrom(options());
2046   }
2047 }
2048 
CopyJsonNameTo(FieldDescriptorProto * proto) const2049 void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2050   proto->set_json_name(json_name());
2051 }
2052 
CopyTo(OneofDescriptorProto * proto) const2053 void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2054   proto->set_name(name());
2055   if (&options() != &OneofOptions::default_instance()) {
2056     proto->mutable_options()->CopyFrom(options());
2057   }
2058 }
2059 
CopyTo(EnumDescriptorProto * proto) const2060 void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2061   proto->set_name(name());
2062 
2063   for (int i = 0; i < value_count(); i++) {
2064     value(i)->CopyTo(proto->add_value());
2065   }
2066 
2067   if (&options() != &EnumOptions::default_instance()) {
2068     proto->mutable_options()->CopyFrom(options());
2069   }
2070 }
2071 
CopyTo(EnumValueDescriptorProto * proto) const2072 void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2073   proto->set_name(name());
2074   proto->set_number(number());
2075 
2076   if (&options() != &EnumValueOptions::default_instance()) {
2077     proto->mutable_options()->CopyFrom(options());
2078   }
2079 }
2080 
CopyTo(ServiceDescriptorProto * proto) const2081 void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2082   proto->set_name(name());
2083 
2084   for (int i = 0; i < method_count(); i++) {
2085     method(i)->CopyTo(proto->add_method());
2086   }
2087 
2088   if (&options() != &ServiceOptions::default_instance()) {
2089     proto->mutable_options()->CopyFrom(options());
2090   }
2091 }
2092 
CopyTo(MethodDescriptorProto * proto) const2093 void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2094   proto->set_name(name());
2095 
2096   if (!input_type()->is_unqualified_placeholder_) {
2097     proto->set_input_type(".");
2098   }
2099   proto->mutable_input_type()->append(input_type()->full_name());
2100 
2101   if (!output_type()->is_unqualified_placeholder_) {
2102     proto->set_output_type(".");
2103   }
2104   proto->mutable_output_type()->append(output_type()->full_name());
2105 
2106   if (&options() != &MethodOptions::default_instance()) {
2107     proto->mutable_options()->CopyFrom(options());
2108   }
2109 
2110   if (client_streaming_) {
2111     proto->set_client_streaming(true);
2112   }
2113   if (server_streaming_) {
2114     proto->set_server_streaming(true);
2115   }
2116 }
2117 
2118 // DebugString methods ===============================================
2119 
2120 namespace {
2121 
RetrieveOptionsAssumingRightPool(int depth,const Message & options,std::vector<string> * option_entries)2122 bool RetrieveOptionsAssumingRightPool(int depth, const Message& options,
2123                                       std::vector<string>* option_entries) {
2124   option_entries->clear();
2125   const Reflection* reflection = options.GetReflection();
2126   std::vector<const FieldDescriptor*> fields;
2127   reflection->ListFields(options, &fields);
2128   for (int i = 0; i < fields.size(); i++) {
2129     int count = 1;
2130     bool repeated = false;
2131     if (fields[i]->is_repeated()) {
2132       count = reflection->FieldSize(options, fields[i]);
2133       repeated = true;
2134     }
2135     for (int j = 0; j < count; j++) {
2136       string fieldval;
2137       if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2138         string tmp;
2139         TextFormat::Printer printer;
2140         printer.SetInitialIndentLevel(depth + 1);
2141         printer.PrintFieldValueToString(options, fields[i],
2142                                         repeated ? j : -1, &tmp);
2143         fieldval.append("{\n");
2144         fieldval.append(tmp);
2145         fieldval.append(depth * 2, ' ');
2146         fieldval.append("}");
2147       } else {
2148         TextFormat::PrintFieldValueToString(options, fields[i],
2149                                             repeated ? j : -1, &fieldval);
2150       }
2151       string name;
2152       if (fields[i]->is_extension()) {
2153         name = "(." + fields[i]->full_name() + ")";
2154       } else {
2155         name = fields[i]->name();
2156       }
2157       option_entries->push_back(name + " = " + fieldval);
2158     }
2159   }
2160   return !option_entries->empty();
2161 }
2162 
2163 // Used by each of the option formatters.
RetrieveOptions(int depth,const Message & options,const DescriptorPool * pool,std::vector<string> * option_entries)2164 bool RetrieveOptions(int depth, const Message& options,
2165                      const DescriptorPool* pool,
2166                      std::vector<string>* option_entries) {
2167   // When printing custom options for a descriptor, we must use an options
2168   // message built on top of the same DescriptorPool where the descriptor
2169   // is coming from. This is to ensure we are interpreting custom options
2170   // against the right pool.
2171   if (options.GetDescriptor()->file()->pool() == pool) {
2172     return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2173   } else {
2174     const Descriptor* option_descriptor =
2175         pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2176     if (option_descriptor == NULL) {
2177       // google/protobuf/descriptor.proto is not in the pool. This means no
2178       // custom options are used so we are safe to proceed with the compiled
2179       // options message type.
2180       return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2181     }
2182     DynamicMessageFactory factory;
2183     google::protobuf::scoped_ptr<Message> dynamic_options(
2184         factory.GetPrototype(option_descriptor)->New());
2185     if (dynamic_options->ParseFromString(options.SerializeAsString())) {
2186       return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2187                                               option_entries);
2188     } else {
2189       GOOGLE_LOG(ERROR) << "Found invalid proto option data for: "
2190                  << options.GetDescriptor()->full_name();
2191       return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2192     }
2193   }
2194 }
2195 
2196 // Formats options that all appear together in brackets. Does not include
2197 // brackets.
FormatBracketedOptions(int depth,const Message & options,const DescriptorPool * pool,string * output)2198 bool FormatBracketedOptions(int depth, const Message& options,
2199                             const DescriptorPool* pool, string* output) {
2200   std::vector<string> all_options;
2201   if (RetrieveOptions(depth, options, pool, &all_options)) {
2202     output->append(Join(all_options, ", "));
2203   }
2204   return !all_options.empty();
2205 }
2206 
2207 // Formats options one per line
FormatLineOptions(int depth,const Message & options,const DescriptorPool * pool,string * output)2208 bool FormatLineOptions(int depth, const Message& options,
2209                        const DescriptorPool* pool, string* output) {
2210   string prefix(depth * 2, ' ');
2211   std::vector<string> all_options;
2212   if (RetrieveOptions(depth, options, pool, &all_options)) {
2213     for (int i = 0; i < all_options.size(); i++) {
2214       strings::SubstituteAndAppend(output, "$0option $1;\n",
2215                                    prefix, all_options[i]);
2216     }
2217   }
2218   return !all_options.empty();
2219 }
2220 
2221 class SourceLocationCommentPrinter {
2222  public:
2223   template<typename DescType>
SourceLocationCommentPrinter(const DescType * desc,const string & prefix,const DebugStringOptions & options)2224   SourceLocationCommentPrinter(const DescType* desc,
2225                                const string& prefix,
2226                                const DebugStringOptions& options)
2227       : options_(options), prefix_(prefix) {
2228     // Perform the SourceLocation lookup only if we're including user comments,
2229     // because the lookup is fairly expensive.
2230     have_source_loc_ = options.include_comments &&
2231         desc->GetSourceLocation(&source_loc_);
2232   }
SourceLocationCommentPrinter(const FileDescriptor * file,const std::vector<int> & path,const string & prefix,const DebugStringOptions & options)2233   SourceLocationCommentPrinter(const FileDescriptor* file,
2234                                const std::vector<int>& path,
2235                                const string& prefix,
2236                                const DebugStringOptions& options)
2237       : options_(options), prefix_(prefix) {
2238     // Perform the SourceLocation lookup only if we're including user comments,
2239     // because the lookup is fairly expensive.
2240     have_source_loc_ = options.include_comments &&
2241         file->GetSourceLocation(path, &source_loc_);
2242   }
AddPreComment(string * output)2243   void AddPreComment(string* output) {
2244     if (have_source_loc_) {
2245       // Detached leading comments.
2246       for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) {
2247         *output += FormatComment(source_loc_.leading_detached_comments[i]);
2248         *output += "\n";
2249       }
2250       // Attached leading comments.
2251       if (!source_loc_.leading_comments.empty()) {
2252         *output += FormatComment(source_loc_.leading_comments);
2253       }
2254     }
2255   }
AddPostComment(string * output)2256   void AddPostComment(string* output) {
2257     if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2258       *output += FormatComment(source_loc_.trailing_comments);
2259     }
2260   }
2261 
2262   // Format comment such that each line becomes a full-line C++-style comment in
2263   // the DebugString() output.
FormatComment(const string & comment_text)2264   string FormatComment(const string& comment_text) {
2265     string stripped_comment = comment_text;
2266     StripWhitespace(&stripped_comment);
2267     std::vector<string> lines = Split(stripped_comment, "\n");
2268     string output;
2269     for (int i = 0; i < lines.size(); ++i) {
2270       const string& line = lines[i];
2271       strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
2272     }
2273     return output;
2274   }
2275 
2276  private:
2277 
2278   bool have_source_loc_;
2279   SourceLocation source_loc_;
2280   DebugStringOptions options_;
2281   string prefix_;
2282 };
2283 
2284 }  // anonymous namespace
2285 
DebugString() const2286 string FileDescriptor::DebugString() const {
2287   DebugStringOptions options;  // default options
2288   return DebugStringWithOptions(options);
2289 }
2290 
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2291 string FileDescriptor::DebugStringWithOptions(
2292     const DebugStringOptions& debug_string_options) const {
2293   string contents;
2294   {
2295     std::vector<int> path;
2296     path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
2297     SourceLocationCommentPrinter syntax_comment(
2298         this, path, "", debug_string_options);
2299     syntax_comment.AddPreComment(&contents);
2300     strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
2301                                  SyntaxName(syntax()));
2302     syntax_comment.AddPostComment(&contents);
2303   }
2304 
2305   SourceLocationCommentPrinter
2306       comment_printer(this, "", debug_string_options);
2307   comment_printer.AddPreComment(&contents);
2308 
2309   std::set<int> public_dependencies;
2310   std::set<int> weak_dependencies;
2311   public_dependencies.insert(public_dependencies_,
2312                              public_dependencies_ + public_dependency_count_);
2313   weak_dependencies.insert(weak_dependencies_,
2314                            weak_dependencies_ + weak_dependency_count_);
2315 
2316   for (int i = 0; i < dependency_count(); i++) {
2317     if (public_dependencies.count(i) > 0) {
2318       strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
2319                                    dependency(i)->name());
2320     } else if (weak_dependencies.count(i) > 0) {
2321       strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
2322                                    dependency(i)->name());
2323     } else {
2324       strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
2325                                    dependency(i)->name());
2326     }
2327   }
2328 
2329   if (!package().empty()) {
2330     std::vector<int> path;
2331     path.push_back(FileDescriptorProto::kPackageFieldNumber);
2332     SourceLocationCommentPrinter package_comment(
2333         this, path, "", debug_string_options);
2334     package_comment.AddPreComment(&contents);
2335     strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
2336     package_comment.AddPostComment(&contents);
2337   }
2338 
2339   if (FormatLineOptions(0, options(), pool(), &contents)) {
2340     contents.append("\n");  // add some space if we had options
2341   }
2342 
2343   for (int i = 0; i < enum_type_count(); i++) {
2344     enum_type(i)->DebugString(0, &contents, debug_string_options);
2345     contents.append("\n");
2346   }
2347 
2348   // Find all the 'group' type extensions; we will not output their nested
2349   // definitions (those will be done with their group field descriptor).
2350   std::set<const Descriptor*> groups;
2351   for (int i = 0; i < extension_count(); i++) {
2352     if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2353       groups.insert(extension(i)->message_type());
2354     }
2355   }
2356 
2357   for (int i = 0; i < message_type_count(); i++) {
2358     if (groups.count(message_type(i)) == 0) {
2359       message_type(i)->DebugString(0, &contents, debug_string_options,
2360                                    /* include_opening_clause */ true);
2361       contents.append("\n");
2362     }
2363   }
2364 
2365   for (int i = 0; i < service_count(); i++) {
2366     service(i)->DebugString(&contents, debug_string_options);
2367     contents.append("\n");
2368   }
2369 
2370   const Descriptor* containing_type = NULL;
2371   for (int i = 0; i < extension_count(); i++) {
2372     if (extension(i)->containing_type() != containing_type) {
2373       if (i > 0) contents.append("}\n\n");
2374       containing_type = extension(i)->containing_type();
2375       strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2376                                    containing_type->full_name());
2377     }
2378     extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents,
2379                               debug_string_options);
2380   }
2381   if (extension_count() > 0) contents.append("}\n\n");
2382 
2383   comment_printer.AddPostComment(&contents);
2384 
2385   return contents;
2386 }
2387 
DebugString() const2388 string Descriptor::DebugString() const {
2389   DebugStringOptions options;  // default options
2390   return DebugStringWithOptions(options);
2391 }
2392 
DebugStringWithOptions(const DebugStringOptions & options) const2393 string Descriptor::DebugStringWithOptions(
2394     const DebugStringOptions& options) const {
2395   string contents;
2396   DebugString(0, &contents, options, /* include_opening_clause */ true);
2397   return contents;
2398 }
2399 
DebugString(int depth,string * contents,const DebugStringOptions & debug_string_options,bool include_opening_clause) const2400 void Descriptor::DebugString(int depth, string *contents,
2401                              const DebugStringOptions&
2402                              debug_string_options,
2403                              bool include_opening_clause) const {
2404   if (options().map_entry()) {
2405     // Do not generate debug string for auto-generated map-entry type.
2406     return;
2407   }
2408   string prefix(depth * 2, ' ');
2409   ++depth;
2410 
2411   SourceLocationCommentPrinter
2412       comment_printer(this, prefix, debug_string_options);
2413   comment_printer.AddPreComment(contents);
2414 
2415   if (include_opening_clause) {
2416     strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
2417   }
2418   contents->append(" {\n");
2419 
2420   FormatLineOptions(depth, options(), file()->pool(), contents);
2421 
2422   // Find all the 'group' types for fields and extensions; we will not output
2423   // their nested definitions (those will be done with their group field
2424   // descriptor).
2425   std::set<const Descriptor*> groups;
2426   for (int i = 0; i < field_count(); i++) {
2427     if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
2428       groups.insert(field(i)->message_type());
2429     }
2430   }
2431   for (int i = 0; i < extension_count(); i++) {
2432     if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2433       groups.insert(extension(i)->message_type());
2434     }
2435   }
2436 
2437   for (int i = 0; i < nested_type_count(); i++) {
2438     if (groups.count(nested_type(i)) == 0) {
2439       nested_type(i)->DebugString(depth, contents, debug_string_options,
2440                                   /* include_opening_clause */ true);
2441     }
2442   }
2443   for (int i = 0; i < enum_type_count(); i++) {
2444     enum_type(i)->DebugString(depth, contents, debug_string_options);
2445   }
2446   for (int i = 0; i < field_count(); i++) {
2447     if (field(i)->containing_oneof() == NULL) {
2448       field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents,
2449                             debug_string_options);
2450     } else if (field(i)->containing_oneof()->field(0) == field(i)) {
2451       // This is the first field in this oneof, so print the whole oneof.
2452       field(i)->containing_oneof()->DebugString(depth, contents,
2453                                                 debug_string_options);
2454     }
2455   }
2456 
2457   for (int i = 0; i < extension_range_count(); i++) {
2458     strings::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n",
2459                                  prefix,
2460                                  extension_range(i)->start,
2461                                  extension_range(i)->end - 1);
2462   }
2463 
2464   // Group extensions by what they extend, so they can be printed out together.
2465   const Descriptor* containing_type = NULL;
2466   for (int i = 0; i < extension_count(); i++) {
2467     if (extension(i)->containing_type() != containing_type) {
2468       if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
2469       containing_type = extension(i)->containing_type();
2470       strings::SubstituteAndAppend(contents, "$0  extend .$1 {\n",
2471                                    prefix, containing_type->full_name());
2472     }
2473     extension(i)->DebugString(
2474         depth + 1, FieldDescriptor::PRINT_LABEL, contents,
2475         debug_string_options);
2476   }
2477   if (extension_count() > 0)
2478     strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
2479 
2480   if (reserved_range_count() > 0) {
2481     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2482     for (int i = 0; i < reserved_range_count(); i++) {
2483       const Descriptor::ReservedRange* range = reserved_range(i);
2484       if (range->end == range->start + 1) {
2485         strings::SubstituteAndAppend(contents, "$0, ", range->start);
2486       } else {
2487         strings::SubstituteAndAppend(contents, "$0 to $1, ",
2488                                      range->start, range->end - 1);
2489       }
2490     }
2491     contents->replace(contents->size() - 2, 2, ";\n");
2492   }
2493 
2494   if (reserved_name_count() > 0) {
2495     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2496     for (int i = 0; i < reserved_name_count(); i++) {
2497       strings::SubstituteAndAppend(contents, "\"$0\", ",
2498                                    CEscape(reserved_name(i)));
2499     }
2500     contents->replace(contents->size() - 2, 2, ";\n");
2501   }
2502 
2503   strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2504   comment_printer.AddPostComment(contents);
2505 }
2506 
DebugString() const2507 string FieldDescriptor::DebugString() const {
2508   DebugStringOptions options;  // default options
2509   return DebugStringWithOptions(options);
2510 }
2511 
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2512 string FieldDescriptor::DebugStringWithOptions(
2513     const DebugStringOptions& debug_string_options) const {
2514   string contents;
2515   int depth = 0;
2516   if (is_extension()) {
2517     strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2518                                  containing_type()->full_name());
2519     depth = 1;
2520   }
2521   DebugString(depth, PRINT_LABEL, &contents, debug_string_options);
2522   if (is_extension()) {
2523     contents.append("}\n");
2524   }
2525   return contents;
2526 }
2527 
2528 // The field type string used in FieldDescriptor::DebugString()
FieldTypeNameDebugString() const2529 string FieldDescriptor::FieldTypeNameDebugString() const {
2530   switch(type()) {
2531     case TYPE_MESSAGE:
2532       return "." + message_type()->full_name();
2533     case TYPE_ENUM:
2534       return "." + enum_type()->full_name();
2535     default:
2536       return kTypeToName[type()];
2537   }
2538 }
2539 
DebugString(int depth,PrintLabelFlag print_label_flag,string * contents,const DebugStringOptions & debug_string_options) const2540 void FieldDescriptor::DebugString(int depth,
2541                                   PrintLabelFlag print_label_flag,
2542                                   string *contents,
2543                                   const DebugStringOptions&
2544                                   debug_string_options) const {
2545   string prefix(depth * 2, ' ');
2546   string field_type;
2547 
2548   // Special case map fields.
2549   if (is_map()) {
2550     strings::SubstituteAndAppend(
2551         &field_type, "map<$0, $1>",
2552         message_type()->field(0)->FieldTypeNameDebugString(),
2553         message_type()->field(1)->FieldTypeNameDebugString());
2554   } else {
2555     field_type = FieldTypeNameDebugString();
2556   }
2557 
2558   bool print_label = true;
2559   // Determine whether to omit label:
2560   //   1. For an optional field, omit label if it's in oneof or in proto3.
2561   //   2. For a repeated field, omit label if it's a map.
2562   if (is_optional() && (print_label_flag == OMIT_LABEL ||
2563                         file()->syntax() == FileDescriptor::SYNTAX_PROTO3)) {
2564     print_label = false;
2565   } else if (is_map()) {
2566     print_label = false;
2567   }
2568   string label;
2569   if (print_label) {
2570     label = kLabelToName[this->label()];
2571     label.push_back(' ');
2572   }
2573 
2574   SourceLocationCommentPrinter
2575       comment_printer(this, prefix, debug_string_options);
2576   comment_printer.AddPreComment(contents);
2577 
2578   strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4",
2579                                prefix,
2580                                label,
2581                                field_type,
2582                                type() == TYPE_GROUP ? message_type()->name() :
2583                                                       name(),
2584                                number());
2585 
2586   bool bracketed = false;
2587   if (has_default_value()) {
2588     bracketed = true;
2589     strings::SubstituteAndAppend(contents, " [default = $0",
2590                                  DefaultValueAsString(true));
2591   }
2592   if (has_json_name_) {
2593     if (!bracketed) {
2594       bracketed = true;
2595       contents->append("[");
2596     } else {
2597       contents->append(", ");
2598     }
2599     contents->append("json_name = \"");
2600     contents->append(CEscape(json_name()));
2601     contents->append("\"");
2602   }
2603 
2604   string formatted_options;
2605   if (FormatBracketedOptions(depth, options(), file()->pool(),
2606                              &formatted_options)) {
2607     contents->append(bracketed ? ", " : " [");
2608     bracketed = true;
2609     contents->append(formatted_options);
2610   }
2611 
2612   if (bracketed) {
2613     contents->append("]");
2614   }
2615 
2616   if (type() == TYPE_GROUP) {
2617     if (debug_string_options.elide_group_body) {
2618       contents->append(" { ... };\n");
2619     } else {
2620       message_type()->DebugString(depth, contents, debug_string_options,
2621                                   /* include_opening_clause */ false);
2622     }
2623   } else {
2624     contents->append(";\n");
2625   }
2626 
2627   comment_printer.AddPostComment(contents);
2628 }
2629 
DebugString() const2630 string OneofDescriptor::DebugString() const {
2631   DebugStringOptions options;  // default values
2632   return DebugStringWithOptions(options);
2633 }
2634 
DebugStringWithOptions(const DebugStringOptions & options) const2635 string OneofDescriptor::DebugStringWithOptions(
2636     const DebugStringOptions& options) const {
2637   string contents;
2638   DebugString(0, &contents, options);
2639   return contents;
2640 }
2641 
DebugString(int depth,string * contents,const DebugStringOptions & debug_string_options) const2642 void OneofDescriptor::DebugString(int depth, string* contents,
2643                                   const DebugStringOptions&
2644                                   debug_string_options) const {
2645   string prefix(depth * 2, ' ');
2646   ++depth;
2647   SourceLocationCommentPrinter
2648       comment_printer(this, prefix, debug_string_options);
2649   comment_printer.AddPreComment(contents);
2650   strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
2651 
2652   FormatLineOptions(depth, options(), containing_type()->file()->pool(),
2653                     contents);
2654 
2655   if (debug_string_options.elide_oneof_body) {
2656     contents->append(" ... }\n");
2657   } else {
2658     contents->append("\n");
2659     for (int i = 0; i < field_count(); i++) {
2660       field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
2661                             debug_string_options);
2662     }
2663     strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2664   }
2665   comment_printer.AddPostComment(contents);
2666 }
2667 
DebugString() const2668 string EnumDescriptor::DebugString() const {
2669   DebugStringOptions options;  // default values
2670   return DebugStringWithOptions(options);
2671 }
2672 
DebugStringWithOptions(const DebugStringOptions & options) const2673 string EnumDescriptor::DebugStringWithOptions(
2674     const DebugStringOptions& options) const {
2675   string contents;
2676   DebugString(0, &contents, options);
2677   return contents;
2678 }
2679 
DebugString(int depth,string * contents,const DebugStringOptions & debug_string_options) const2680 void EnumDescriptor::DebugString(int depth, string *contents,
2681                                  const DebugStringOptions&
2682                                  debug_string_options) const {
2683   string prefix(depth * 2, ' ');
2684   ++depth;
2685 
2686   SourceLocationCommentPrinter
2687       comment_printer(this, prefix, debug_string_options);
2688   comment_printer.AddPreComment(contents);
2689 
2690   strings::SubstituteAndAppend(contents, "$0enum $1 {\n",
2691                                prefix, name());
2692 
2693   FormatLineOptions(depth, options(), file()->pool(), contents);
2694 
2695   for (int i = 0; i < value_count(); i++) {
2696     value(i)->DebugString(depth, contents, debug_string_options);
2697   }
2698   strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2699 
2700   comment_printer.AddPostComment(contents);
2701 }
2702 
DebugString() const2703 string EnumValueDescriptor::DebugString() const {
2704   DebugStringOptions options;  // default values
2705   return DebugStringWithOptions(options);
2706 }
2707 
DebugStringWithOptions(const DebugStringOptions & options) const2708 string EnumValueDescriptor::DebugStringWithOptions(
2709     const DebugStringOptions& options) const {
2710   string contents;
2711   DebugString(0, &contents, options);
2712   return contents;
2713 }
2714 
DebugString(int depth,string * contents,const DebugStringOptions & debug_string_options) const2715 void EnumValueDescriptor::DebugString(int depth, string *contents,
2716                                       const DebugStringOptions&
2717                                       debug_string_options) const {
2718   string prefix(depth * 2, ' ');
2719 
2720   SourceLocationCommentPrinter
2721       comment_printer(this, prefix, debug_string_options);
2722   comment_printer.AddPreComment(contents);
2723 
2724   strings::SubstituteAndAppend(contents, "$0$1 = $2",
2725                                prefix, name(), number());
2726 
2727   string formatted_options;
2728   if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
2729                              &formatted_options)) {
2730     strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
2731   }
2732   contents->append(";\n");
2733 
2734   comment_printer.AddPostComment(contents);
2735 }
2736 
DebugString() const2737 string ServiceDescriptor::DebugString() const {
2738   DebugStringOptions options;  // default values
2739   return DebugStringWithOptions(options);
2740 }
2741 
DebugStringWithOptions(const DebugStringOptions & options) const2742 string ServiceDescriptor::DebugStringWithOptions(
2743     const DebugStringOptions& options) const {
2744   string contents;
2745   DebugString(&contents, options);
2746   return contents;
2747 }
2748 
DebugString(string * contents,const DebugStringOptions & debug_string_options) const2749 void ServiceDescriptor::DebugString(string *contents,
2750                                     const DebugStringOptions&
2751                                     debug_string_options) const {
2752   SourceLocationCommentPrinter
2753       comment_printer(this, /* prefix */ "", debug_string_options);
2754   comment_printer.AddPreComment(contents);
2755 
2756   strings::SubstituteAndAppend(contents, "service $0 {\n", name());
2757 
2758   FormatLineOptions(1, options(), file()->pool(), contents);
2759 
2760   for (int i = 0; i < method_count(); i++) {
2761     method(i)->DebugString(1, contents, debug_string_options);
2762   }
2763 
2764   contents->append("}\n");
2765 
2766   comment_printer.AddPostComment(contents);
2767 }
2768 
DebugString() const2769 string MethodDescriptor::DebugString() const {
2770   DebugStringOptions options;  // default values
2771   return DebugStringWithOptions(options);
2772 }
2773 
DebugStringWithOptions(const DebugStringOptions & options) const2774 string MethodDescriptor::DebugStringWithOptions(
2775     const DebugStringOptions& options) const {
2776   string contents;
2777   DebugString(0, &contents, options);
2778   return contents;
2779 }
2780 
DebugString(int depth,string * contents,const DebugStringOptions & debug_string_options) const2781 void MethodDescriptor::DebugString(int depth, string *contents,
2782                                    const DebugStringOptions&
2783                                    debug_string_options) const {
2784   string prefix(depth * 2, ' ');
2785   ++depth;
2786 
2787   SourceLocationCommentPrinter
2788       comment_printer(this, prefix, debug_string_options);
2789   comment_printer.AddPreComment(contents);
2790 
2791   strings::SubstituteAndAppend(contents, "$0rpc $1($4.$2) returns ($5.$3)",
2792                                prefix, name(),
2793                                input_type()->full_name(),
2794                                output_type()->full_name(),
2795                                client_streaming() ? "stream " : "",
2796                                server_streaming() ? "stream " : "");
2797 
2798   string formatted_options;
2799   if (FormatLineOptions(depth, options(), service()->file()->pool(),
2800                         &formatted_options)) {
2801     strings::SubstituteAndAppend(contents, " {\n$0$1}\n",
2802                                  formatted_options, prefix);
2803   } else {
2804     contents->append(";\n");
2805   }
2806 
2807   comment_printer.AddPostComment(contents);
2808 }
2809 
2810 
2811 // Location methods ===============================================
2812 
GetSourceLocation(const std::vector<int> & path,SourceLocation * out_location) const2813 bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
2814                                        SourceLocation* out_location) const {
2815   GOOGLE_CHECK_NOTNULL(out_location);
2816   if (source_code_info_) {
2817     if (const SourceCodeInfo_Location* loc =
2818         tables_->GetSourceLocation(path, source_code_info_)) {
2819       const RepeatedField<int32>& span = loc->span();
2820       if (span.size() == 3 || span.size() == 4) {
2821         out_location->start_line   = span.Get(0);
2822         out_location->start_column = span.Get(1);
2823         out_location->end_line     = span.Get(span.size() == 3 ? 0 : 2);
2824         out_location->end_column   = span.Get(span.size() - 1);
2825 
2826         out_location->leading_comments = loc->leading_comments();
2827         out_location->trailing_comments = loc->trailing_comments();
2828         out_location->leading_detached_comments.assign(
2829             loc->leading_detached_comments().begin(),
2830             loc->leading_detached_comments().end());
2831         return true;
2832       }
2833     }
2834   }
2835   return false;
2836 }
2837 
GetSourceLocation(SourceLocation * out_location) const2838 bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2839   std::vector<int> path;  // empty path for root FileDescriptor
2840   return GetSourceLocation(path, out_location);
2841 }
2842 
is_packed() const2843 bool FieldDescriptor::is_packed() const {
2844   if (!is_packable()) return false;
2845   if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
2846     return (options_ != NULL) && options_->packed();
2847   } else {
2848     return options_ == NULL || !options_->has_packed() || options_->packed();
2849   }
2850 }
2851 
GetSourceLocation(SourceLocation * out_location) const2852 bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
2853   std::vector<int> path;
2854   GetLocationPath(&path);
2855   return file()->GetSourceLocation(path, out_location);
2856 }
2857 
GetSourceLocation(SourceLocation * out_location) const2858 bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2859   std::vector<int> path;
2860   GetLocationPath(&path);
2861   return file()->GetSourceLocation(path, out_location);
2862 }
2863 
GetSourceLocation(SourceLocation * out_location) const2864 bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2865   std::vector<int> path;
2866   GetLocationPath(&path);
2867   return containing_type()->file()->GetSourceLocation(path, out_location);
2868 }
2869 
GetSourceLocation(SourceLocation * out_location) const2870 bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2871   std::vector<int> path;
2872   GetLocationPath(&path);
2873   return file()->GetSourceLocation(path, out_location);
2874 }
2875 
GetSourceLocation(SourceLocation * out_location) const2876 bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2877   std::vector<int> path;
2878   GetLocationPath(&path);
2879   return service()->file()->GetSourceLocation(path, out_location);
2880 }
2881 
GetSourceLocation(SourceLocation * out_location) const2882 bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2883   std::vector<int> path;
2884   GetLocationPath(&path);
2885   return file()->GetSourceLocation(path, out_location);
2886 }
2887 
GetSourceLocation(SourceLocation * out_location) const2888 bool EnumValueDescriptor::GetSourceLocation(
2889     SourceLocation* out_location) const {
2890   std::vector<int> path;
2891   GetLocationPath(&path);
2892   return type()->file()->GetSourceLocation(path, out_location);
2893 }
2894 
GetLocationPath(std::vector<int> * output) const2895 void Descriptor::GetLocationPath(std::vector<int>* output) const {
2896   if (containing_type()) {
2897     containing_type()->GetLocationPath(output);
2898     output->push_back(DescriptorProto::kNestedTypeFieldNumber);
2899     output->push_back(index());
2900   } else {
2901     output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
2902     output->push_back(index());
2903   }
2904 }
2905 
GetLocationPath(std::vector<int> * output) const2906 void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
2907   if (is_extension()) {
2908     if (extension_scope() == NULL) {
2909       output->push_back(FileDescriptorProto::kExtensionFieldNumber);
2910       output->push_back(index());
2911     } else {
2912       extension_scope()->GetLocationPath(output);
2913       output->push_back(DescriptorProto::kExtensionFieldNumber);
2914       output->push_back(index());
2915     }
2916   } else {
2917     containing_type()->GetLocationPath(output);
2918     output->push_back(DescriptorProto::kFieldFieldNumber);
2919     output->push_back(index());
2920   }
2921 }
2922 
GetLocationPath(std::vector<int> * output) const2923 void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
2924   containing_type()->GetLocationPath(output);
2925   output->push_back(DescriptorProto::kOneofDeclFieldNumber);
2926   output->push_back(index());
2927 }
2928 
GetLocationPath(std::vector<int> * output) const2929 void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
2930   if (containing_type()) {
2931     containing_type()->GetLocationPath(output);
2932     output->push_back(DescriptorProto::kEnumTypeFieldNumber);
2933     output->push_back(index());
2934   } else {
2935     output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
2936     output->push_back(index());
2937   }
2938 }
2939 
GetLocationPath(std::vector<int> * output) const2940 void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
2941   type()->GetLocationPath(output);
2942   output->push_back(EnumDescriptorProto::kValueFieldNumber);
2943   output->push_back(index());
2944 }
2945 
GetLocationPath(std::vector<int> * output) const2946 void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
2947   output->push_back(FileDescriptorProto::kServiceFieldNumber);
2948   output->push_back(index());
2949 }
2950 
GetLocationPath(std::vector<int> * output) const2951 void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
2952   service()->GetLocationPath(output);
2953   output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
2954   output->push_back(index());
2955 }
2956 
2957 // ===================================================================
2958 
2959 namespace {
2960 
2961 // Represents an options message to interpret. Extension names in the option
2962 // name are resolved relative to name_scope. element_name and orig_opt are
2963 // used only for error reporting (since the parser records locations against
2964 // pointers in the original options, not the mutable copy). The Message must be
2965 // one of the Options messages in descriptor.proto.
2966 struct OptionsToInterpret {
OptionsToInterpretgoogle::protobuf::__anon78c7d0840611::OptionsToInterpret2967   OptionsToInterpret(const string& ns,
2968                      const string& el,
2969                      const Message* orig_opt,
2970                      Message* opt)
2971       : name_scope(ns),
2972         element_name(el),
2973         original_options(orig_opt),
2974         options(opt) {
2975   }
2976   string name_scope;
2977   string element_name;
2978   const Message* original_options;
2979   Message* options;
2980 };
2981 
2982 }  // namespace
2983 
2984 class DescriptorBuilder {
2985  public:
2986   DescriptorBuilder(const DescriptorPool* pool,
2987                     DescriptorPool::Tables* tables,
2988                     DescriptorPool::ErrorCollector* error_collector);
2989   ~DescriptorBuilder();
2990 
2991   const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
2992 
2993  private:
2994   friend class OptionInterpreter;
2995 
2996   // Non-recursive part of BuildFile functionality.
2997   const FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto);
2998 
2999   const DescriptorPool* pool_;
3000   DescriptorPool::Tables* tables_;  // for convenience
3001   DescriptorPool::ErrorCollector* error_collector_;
3002 
3003   // As we build descriptors we store copies of the options messages in
3004   // them. We put pointers to those copies in this vector, as we build, so we
3005   // can later (after cross-linking) interpret those options.
3006   std::vector<OptionsToInterpret> options_to_interpret_;
3007 
3008   bool had_errors_;
3009   string filename_;
3010   FileDescriptor* file_;
3011   FileDescriptorTables* file_tables_;
3012   std::set<const FileDescriptor*> dependencies_;
3013 
3014   // unused_dependency_ is used to record the unused imported files.
3015   // Note: public import is not considered.
3016   std::set<const FileDescriptor*> unused_dependency_;
3017 
3018   // If LookupSymbol() finds a symbol that is in a file which is not a declared
3019   // dependency of this file, it will fail, but will set
3020   // possible_undeclared_dependency_ to point at that file.  This is only used
3021   // by AddNotDefinedError() to report a more useful error message.
3022   // possible_undeclared_dependency_name_ is the name of the symbol that was
3023   // actually found in possible_undeclared_dependency_, which may be a parent
3024   // of the symbol actually looked for.
3025   const FileDescriptor* possible_undeclared_dependency_;
3026   string possible_undeclared_dependency_name_;
3027 
3028   // If LookupSymbol() could resolve a symbol which is not defined,
3029   // record the resolved name.  This is only used by AddNotDefinedError()
3030   // to report a more useful error message.
3031   string undefine_resolved_name_;
3032 
3033   void AddError(const string& element_name,
3034                 const Message& descriptor,
3035                 DescriptorPool::ErrorCollector::ErrorLocation location,
3036                 const string& error);
3037   void AddError(const string& element_name,
3038                 const Message& descriptor,
3039                 DescriptorPool::ErrorCollector::ErrorLocation location,
3040                 const char* error);
3041   void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3042   void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3043   void AddImportError(const FileDescriptorProto& proto, int index);
3044 
3045   // Adds an error indicating that undefined_symbol was not defined.  Must
3046   // only be called after LookupSymbol() fails.
3047   void AddNotDefinedError(
3048     const string& element_name,
3049     const Message& descriptor,
3050     DescriptorPool::ErrorCollector::ErrorLocation location,
3051     const string& undefined_symbol);
3052 
3053   void AddWarning(const string& element_name, const Message& descriptor,
3054                   DescriptorPool::ErrorCollector::ErrorLocation location,
3055                   const string& error);
3056 
3057   // Silly helper which determines if the given file is in the given package.
3058   // I.e., either file->package() == package_name or file->package() is a
3059   // nested package within package_name.
3060   bool IsInPackage(const FileDescriptor* file, const string& package_name);
3061 
3062   // Helper function which finds all public dependencies of the given file, and
3063   // stores the them in the dependencies_ set in the builder.
3064   void RecordPublicDependencies(const FileDescriptor* file);
3065 
3066   // Like tables_->FindSymbol(), but additionally:
3067   // - Search the pool's underlay if not found in tables_.
3068   // - Insure that the resulting Symbol is from one of the file's declared
3069   //   dependencies.
3070   Symbol FindSymbol(const string& name, bool build_it = true);
3071 
3072   // Like FindSymbol() but does not require that the symbol is in one of the
3073   // file's declared dependencies.
3074   Symbol FindSymbolNotEnforcingDeps(const string& name, bool build_it = true);
3075 
3076   // This implements the body of FindSymbolNotEnforcingDeps().
3077   Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3078                                           const string& name,
3079                                           bool build_it = true);
3080 
3081   // Like FindSymbol(), but looks up the name relative to some other symbol
3082   // name.  This first searches siblings of relative_to, then siblings of its
3083   // parents, etc.  For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
3084   // the following calls, returning the first non-null result:
3085   // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
3086   // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
3087   // on the DescriptorPool, this will generate a placeholder type if
3088   // the name is not found (unless the name itself is malformed).  The
3089   // placeholder_type parameter indicates what kind of placeholder should be
3090   // constructed in this case.  The resolve_mode parameter determines whether
3091   // any symbol is returned, or only symbols that are types.  Note, however,
3092   // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3093   // if it believes that's all it could refer to.  The caller should always
3094   // check that it receives the type of symbol it was expecting.
3095   enum ResolveMode {
3096     LOOKUP_ALL, LOOKUP_TYPES
3097   };
3098   Symbol LookupSymbol(const string& name, const string& relative_to,
3099                       DescriptorPool::PlaceholderType placeholder_type =
3100                           DescriptorPool::PLACEHOLDER_MESSAGE,
3101                       ResolveMode resolve_mode = LOOKUP_ALL,
3102                       bool build_it = true);
3103 
3104   // Like LookupSymbol() but will not return a placeholder even if
3105   // AllowUnknownDependencies() has been used.
3106   Symbol LookupSymbolNoPlaceholder(const string& name,
3107                                    const string& relative_to,
3108                                    ResolveMode resolve_mode = LOOKUP_ALL,
3109                                    bool build_it = true);
3110 
3111   // Calls tables_->AddSymbol() and records an error if it fails.  Returns
3112   // true if successful or false if failed, though most callers can ignore
3113   // the return value since an error has already been recorded.
3114   bool AddSymbol(const string& full_name,
3115                  const void* parent, const string& name,
3116                  const Message& proto, Symbol symbol);
3117 
3118   // Like AddSymbol(), but succeeds if the symbol is already defined as long
3119   // as the existing definition is also a package (because it's OK to define
3120   // the same package in two different files).  Also adds all parents of the
3121   // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3122   // "foo.bar" and "foo" to the table).
3123   void AddPackage(const string& name, const Message& proto,
3124                   const FileDescriptor* file);
3125 
3126   // Checks that the symbol name contains only alphanumeric characters and
3127   // underscores.  Records an error otherwise.
3128   void ValidateSymbolName(const string& name, const string& full_name,
3129                           const Message& proto);
3130 
3131   // Used by BUILD_ARRAY macro (below) to avoid having to have the type
3132   // specified as a macro parameter.
3133   template <typename Type>
AllocateArray(int size,Type ** output)3134   inline void AllocateArray(int size, Type** output) {
3135     *output = tables_->AllocateArray<Type>(size);
3136   }
3137 
3138   // Allocates a copy of orig_options in tables_ and stores it in the
3139   // descriptor. Remembers its uninterpreted options, to be interpreted
3140   // later. DescriptorT must be one of the Descriptor messages from
3141   // descriptor.proto.
3142   template<class DescriptorT> void AllocateOptions(
3143       const typename DescriptorT::OptionsType& orig_options,
3144       DescriptorT* descriptor);
3145   // Specialization for FileOptions.
3146   void AllocateOptions(const FileOptions& orig_options,
3147                        FileDescriptor* descriptor);
3148 
3149   // Implementation for AllocateOptions(). Don't call this directly.
3150   template<class DescriptorT> void AllocateOptionsImpl(
3151       const string& name_scope,
3152       const string& element_name,
3153       const typename DescriptorT::OptionsType& orig_options,
3154       DescriptorT* descriptor);
3155 
3156   // These methods all have the same signature for the sake of the BUILD_ARRAY
3157   // macro, below.
3158   void BuildMessage(const DescriptorProto& proto,
3159                     const Descriptor* parent,
3160                     Descriptor* result);
3161   void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3162                              const Descriptor* parent,
3163                              FieldDescriptor* result,
3164                              bool is_extension);
BuildField(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result)3165   void BuildField(const FieldDescriptorProto& proto,
3166                   const Descriptor* parent,
3167                   FieldDescriptor* result) {
3168     BuildFieldOrExtension(proto, parent, result, false);
3169   }
BuildExtension(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result)3170   void BuildExtension(const FieldDescriptorProto& proto,
3171                       const Descriptor* parent,
3172                       FieldDescriptor* result) {
3173     BuildFieldOrExtension(proto, parent, result, true);
3174   }
3175   void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3176                            const Descriptor* parent,
3177                            Descriptor::ExtensionRange* result);
3178   void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
3179                            const Descriptor* parent,
3180                            Descriptor::ReservedRange* result);
3181   void BuildOneof(const OneofDescriptorProto& proto,
3182                   Descriptor* parent,
3183                   OneofDescriptor* result);
3184   void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
3185                                 const EnumDescriptor* result);
3186   void BuildEnum(const EnumDescriptorProto& proto,
3187                  const Descriptor* parent,
3188                  EnumDescriptor* result);
3189   void BuildEnumValue(const EnumValueDescriptorProto& proto,
3190                       const EnumDescriptor* parent,
3191                       EnumValueDescriptor* result);
3192   void BuildService(const ServiceDescriptorProto& proto,
3193                     const void* dummy,
3194                     ServiceDescriptor* result);
3195   void BuildMethod(const MethodDescriptorProto& proto,
3196                    const ServiceDescriptor* parent,
3197                    MethodDescriptor* result);
3198 
3199   void LogUnusedDependency(const FileDescriptorProto& proto,
3200                            const FileDescriptor* result);
3201 
3202   // Must be run only after building.
3203   //
3204   // NOTE: Options will not be available during cross-linking, as they
3205   // have not yet been interpreted. Defer any handling of options to the
3206   // Validate*Options methods.
3207   void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
3208   void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
3209   void CrossLinkField(FieldDescriptor* field,
3210                       const FieldDescriptorProto& proto);
3211   void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
3212                                const DescriptorProto::ExtensionRange& proto);
3213   void CrossLinkEnum(EnumDescriptor* enum_type,
3214                      const EnumDescriptorProto& proto);
3215   void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
3216                           const EnumValueDescriptorProto& proto);
3217   void CrossLinkService(ServiceDescriptor* service,
3218                         const ServiceDescriptorProto& proto);
3219   void CrossLinkMethod(MethodDescriptor* method,
3220                        const MethodDescriptorProto& proto);
3221 
3222   // Must be run only after cross-linking.
3223   void InterpretOptions();
3224 
3225   // A helper class for interpreting options.
3226   class OptionInterpreter {
3227    public:
3228     // Creates an interpreter that operates in the context of the pool of the
3229     // specified builder, which must not be NULL. We don't take ownership of the
3230     // builder.
3231     explicit OptionInterpreter(DescriptorBuilder* builder);
3232 
3233     ~OptionInterpreter();
3234 
3235     // Interprets the uninterpreted options in the specified Options message.
3236     // On error, calls AddError() on the underlying builder and returns false.
3237     // Otherwise returns true.
3238     bool InterpretOptions(OptionsToInterpret* options_to_interpret);
3239 
3240     class AggregateOptionFinder;
3241 
3242    private:
3243     // Interprets uninterpreted_option_ on the specified message, which
3244     // must be the mutable copy of the original options message to which
3245     // uninterpreted_option_ belongs.
3246     bool InterpretSingleOption(Message* options);
3247 
3248     // Adds the uninterpreted_option to the given options message verbatim.
3249     // Used when AllowUnknownDependencies() is in effect and we can't find
3250     // the option's definition.
3251     void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
3252                                 Message* options);
3253 
3254     // A recursive helper function that drills into the intermediate fields
3255     // in unknown_fields to check if field innermost_field is set on the
3256     // innermost message. Returns false and sets an error if so.
3257     bool ExamineIfOptionIsSet(
3258         std::vector<const FieldDescriptor*>::const_iterator
3259             intermediate_fields_iter,
3260         std::vector<const FieldDescriptor*>::const_iterator
3261             intermediate_fields_end,
3262         const FieldDescriptor* innermost_field, const string& debug_msg_name,
3263         const UnknownFieldSet& unknown_fields);
3264 
3265     // Validates the value for the option field of the currently interpreted
3266     // option and then sets it on the unknown_field.
3267     bool SetOptionValue(const FieldDescriptor* option_field,
3268                         UnknownFieldSet* unknown_fields);
3269 
3270     // Parses an aggregate value for a CPPTYPE_MESSAGE option and
3271     // saves it into *unknown_fields.
3272     bool SetAggregateOption(const FieldDescriptor* option_field,
3273                             UnknownFieldSet* unknown_fields);
3274 
3275     // Convenience functions to set an int field the right way, depending on
3276     // its wire type (a single int CppType can represent multiple wire types).
3277     void SetInt32(int number, int32 value, FieldDescriptor::Type type,
3278                   UnknownFieldSet* unknown_fields);
3279     void SetInt64(int number, int64 value, FieldDescriptor::Type type,
3280                   UnknownFieldSet* unknown_fields);
3281     void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
3282                    UnknownFieldSet* unknown_fields);
3283     void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
3284                    UnknownFieldSet* unknown_fields);
3285 
3286     // A helper function that adds an error at the specified location of the
3287     // option we're currently interpreting, and returns false.
AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,const string & msg)3288     bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
3289                         const string& msg) {
3290       builder_->AddError(options_to_interpret_->element_name,
3291                          *uninterpreted_option_, location, msg);
3292       return false;
3293     }
3294 
3295     // A helper function that adds an error at the location of the option name
3296     // and returns false.
AddNameError(const string & msg)3297     bool AddNameError(const string& msg) {
3298       return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
3299     }
3300 
3301     // A helper function that adds an error at the location of the option name
3302     // and returns false.
AddValueError(const string & msg)3303     bool AddValueError(const string& msg) {
3304       return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
3305     }
3306 
3307     // We interpret against this builder's pool. Is never NULL. We don't own
3308     // this pointer.
3309     DescriptorBuilder* builder_;
3310 
3311     // The options we're currently interpreting, or NULL if we're not in a call
3312     // to InterpretOptions.
3313     const OptionsToInterpret* options_to_interpret_;
3314 
3315     // The option we're currently interpreting within options_to_interpret_, or
3316     // NULL if we're not in a call to InterpretOptions(). This points to a
3317     // submessage of the original option, not the mutable copy. Therefore we
3318     // can use it to find locations recorded by the parser.
3319     const UninterpretedOption* uninterpreted_option_;
3320 
3321     // Factory used to create the dynamic messages we need to parse
3322     // any aggregate option values we encounter.
3323     DynamicMessageFactory dynamic_factory_;
3324 
3325     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
3326   };
3327 
3328   // Work-around for broken compilers:  According to the C++ standard,
3329   // OptionInterpreter should have access to the private members of any class
3330   // which has declared DescriptorBuilder as a friend.  Unfortunately some old
3331   // versions of GCC and other compilers do not implement this correctly.  So,
3332   // we have to have these intermediate methods to provide access.  We also
3333   // redundantly declare OptionInterpreter a friend just to make things extra
3334   // clear for these bad compilers.
3335   friend class OptionInterpreter;
3336   friend class OptionInterpreter::AggregateOptionFinder;
3337 
get_allow_unknown(const DescriptorPool * pool)3338   static inline bool get_allow_unknown(const DescriptorPool* pool) {
3339     return pool->allow_unknown_;
3340   }
get_enforce_weak(const DescriptorPool * pool)3341   static inline bool get_enforce_weak(const DescriptorPool* pool) {
3342     return pool->enforce_weak_;
3343   }
get_is_placeholder(const Descriptor * descriptor)3344   static inline bool get_is_placeholder(const Descriptor* descriptor) {
3345     return descriptor->is_placeholder_;
3346   }
assert_mutex_held(const DescriptorPool * pool)3347   static inline void assert_mutex_held(const DescriptorPool* pool) {
3348     if (pool->mutex_ != NULL) {
3349       pool->mutex_->AssertHeld();
3350     }
3351   }
3352 
3353   // Must be run only after options have been interpreted.
3354   //
3355   // NOTE: Validation code must only reference the options in the mutable
3356   // descriptors, which are the ones that have been interpreted. The const
3357   // proto references are passed in only so they can be provided to calls to
3358   // AddError(). Do not look at their options, which have not been interpreted.
3359   void ValidateFileOptions(FileDescriptor* file,
3360                            const FileDescriptorProto& proto);
3361   void ValidateMessageOptions(Descriptor* message,
3362                               const DescriptorProto& proto);
3363   void ValidateFieldOptions(FieldDescriptor* field,
3364                             const FieldDescriptorProto& proto);
3365   void ValidateEnumOptions(EnumDescriptor* enm,
3366                            const EnumDescriptorProto& proto);
3367   void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
3368                                 const EnumValueDescriptorProto& proto);
3369   void ValidateServiceOptions(ServiceDescriptor* service,
3370                               const ServiceDescriptorProto& proto);
3371   void ValidateMethodOptions(MethodDescriptor* method,
3372                              const MethodDescriptorProto& proto);
3373   void ValidateProto3(FileDescriptor* file,
3374                       const FileDescriptorProto& proto);
3375   void ValidateProto3Message(Descriptor* message,
3376                              const DescriptorProto& proto);
3377   void ValidateProto3Field(FieldDescriptor* field,
3378                            const FieldDescriptorProto& proto);
3379   void ValidateProto3Enum(EnumDescriptor* enm,
3380                           const EnumDescriptorProto& proto);
3381 
3382   // Returns true if the map entry message is compatible with the
3383   // auto-generated entry message from map fields syntax.
3384   bool ValidateMapEntry(FieldDescriptor* field,
3385                         const FieldDescriptorProto& proto);
3386 
3387   // Recursively detects naming conflicts with map entry types for a
3388   // better error message.
3389   void DetectMapConflicts(const Descriptor* message,
3390                           const DescriptorProto& proto);
3391 
3392   void ValidateJSType(FieldDescriptor* field,
3393                       const FieldDescriptorProto& proto);
3394 };
3395 
BuildFile(const FileDescriptorProto & proto)3396 const FileDescriptor* DescriptorPool::BuildFile(
3397     const FileDescriptorProto& proto) {
3398   GOOGLE_CHECK(fallback_database_ == NULL)
3399     << "Cannot call BuildFile on a DescriptorPool that uses a "
3400        "DescriptorDatabase.  You must instead find a way to get your file "
3401        "into the underlying database.";
3402   GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
3403   tables_->known_bad_symbols_.clear();
3404   tables_->known_bad_files_.clear();
3405   return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
3406 }
3407 
BuildFileCollectingErrors(const FileDescriptorProto & proto,ErrorCollector * error_collector)3408 const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
3409     const FileDescriptorProto& proto,
3410     ErrorCollector* error_collector) {
3411   GOOGLE_CHECK(fallback_database_ == NULL)
3412     << "Cannot call BuildFile on a DescriptorPool that uses a "
3413        "DescriptorDatabase.  You must instead find a way to get your file "
3414        "into the underlying database.";
3415   GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
3416   tables_->known_bad_symbols_.clear();
3417   tables_->known_bad_files_.clear();
3418   return DescriptorBuilder(this, tables_.get(),
3419                            error_collector).BuildFile(proto);
3420 }
3421 
BuildFileFromDatabase(const FileDescriptorProto & proto) const3422 const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
3423     const FileDescriptorProto& proto) const {
3424   mutex_->AssertHeld();
3425   if (tables_->known_bad_files_.count(proto.name()) > 0) {
3426     return NULL;
3427   }
3428   const FileDescriptor* result =
3429       DescriptorBuilder(this, tables_.get(),
3430                         default_error_collector_).BuildFile(proto);
3431   if (result == NULL) {
3432     tables_->known_bad_files_.insert(proto.name());
3433   }
3434   return result;
3435 }
3436 
DescriptorBuilder(const DescriptorPool * pool,DescriptorPool::Tables * tables,DescriptorPool::ErrorCollector * error_collector)3437 DescriptorBuilder::DescriptorBuilder(
3438     const DescriptorPool* pool,
3439     DescriptorPool::Tables* tables,
3440     DescriptorPool::ErrorCollector* error_collector)
3441   : pool_(pool),
3442     tables_(tables),
3443     error_collector_(error_collector),
3444     had_errors_(false),
3445     possible_undeclared_dependency_(NULL),
3446     undefine_resolved_name_("") {}
3447 
~DescriptorBuilder()3448 DescriptorBuilder::~DescriptorBuilder() {}
3449 
AddError(const string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const string & error)3450 void DescriptorBuilder::AddError(
3451     const string& element_name,
3452     const Message& descriptor,
3453     DescriptorPool::ErrorCollector::ErrorLocation location,
3454     const string& error) {
3455   if (error_collector_ == NULL) {
3456     if (!had_errors_) {
3457       GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
3458                  << "\":";
3459     }
3460     GOOGLE_LOG(ERROR) << "  " << element_name << ": " << error;
3461   } else {
3462     error_collector_->AddError(filename_, element_name,
3463                                &descriptor, location, error);
3464   }
3465   had_errors_ = true;
3466 }
3467 
AddError(const string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const char * error)3468 void DescriptorBuilder::AddError(
3469     const string& element_name,
3470     const Message& descriptor,
3471     DescriptorPool::ErrorCollector::ErrorLocation location,
3472     const char* error) {
3473   AddError(element_name, descriptor, location, string(error));
3474 }
3475 
AddNotDefinedError(const string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const string & undefined_symbol)3476 void DescriptorBuilder::AddNotDefinedError(
3477     const string& element_name,
3478     const Message& descriptor,
3479     DescriptorPool::ErrorCollector::ErrorLocation location,
3480     const string& undefined_symbol) {
3481   if (possible_undeclared_dependency_ == NULL &&
3482       undefine_resolved_name_.empty()) {
3483     AddError(element_name, descriptor, location,
3484              "\"" + undefined_symbol + "\" is not defined.");
3485   } else {
3486     if (possible_undeclared_dependency_ != NULL) {
3487       AddError(element_name, descriptor, location,
3488                "\"" + possible_undeclared_dependency_name_ +
3489                "\" seems to be defined in \"" +
3490                possible_undeclared_dependency_->name() + "\", which is not "
3491                "imported by \"" + filename_ + "\".  To use it here, please "
3492                "add the necessary import.");
3493     }
3494     if (!undefine_resolved_name_.empty()) {
3495       AddError(element_name, descriptor, location,
3496                "\"" + undefined_symbol + "\" is resolved to \"" +
3497                undefine_resolved_name_ + "\", which is not defined. "
3498                "The innermost scope is searched first in name resolution. "
3499                "Consider using a leading '.'(i.e., \"."
3500                + undefined_symbol +
3501                "\") to start from the outermost scope.");
3502     }
3503   }
3504 }
3505 
AddWarning(const string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const string & error)3506 void DescriptorBuilder::AddWarning(
3507     const string& element_name, const Message& descriptor,
3508     DescriptorPool::ErrorCollector::ErrorLocation location,
3509     const string& error) {
3510   if (error_collector_ == NULL) {
3511     GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
3512   } else {
3513     error_collector_->AddWarning(filename_, element_name, &descriptor, location,
3514                                  error);
3515   }
3516 }
3517 
IsInPackage(const FileDescriptor * file,const string & package_name)3518 bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
3519                                     const string& package_name) {
3520   return HasPrefixString(file->package(), package_name) &&
3521          (file->package().size() == package_name.size() ||
3522           file->package()[package_name.size()] == '.');
3523 }
3524 
RecordPublicDependencies(const FileDescriptor * file)3525 void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
3526   if (file == NULL || !dependencies_.insert(file).second) return;
3527   for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
3528     RecordPublicDependencies(file->public_dependency(i));
3529   }
3530 }
3531 
FindSymbolNotEnforcingDepsHelper(const DescriptorPool * pool,const string & name,bool build_it)3532 Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
3533     const DescriptorPool* pool, const string& name, bool build_it) {
3534   // If we are looking at an underlay, we must lock its mutex_, since we are
3535   // accessing the underlay's tables_ directly.
3536   MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
3537 
3538   Symbol result = pool->tables_->FindSymbol(name);
3539   if (result.IsNull() && pool->underlay_ != NULL) {
3540     // Symbol not found; check the underlay.
3541     result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
3542   }
3543 
3544   if (result.IsNull()) {
3545     // With lazily_build_dependencies_, a symbol lookup at cross link time is
3546     // not guaranteed to be successful. In most cases, build_it will be false,
3547     // which intentionally prevents us from building an import until it's
3548     // actually needed. In some cases, like registering an extension, we want
3549     // to build the file containing the symbol, and build_it will be set.
3550     // Also, build_it will be true when !lazily_build_dependencies_, to provide
3551     // better error reporting of missing dependencies.
3552     if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
3553       result = pool->tables_->FindSymbol(name);
3554     }
3555   }
3556 
3557   return result;
3558 }
3559 
FindSymbolNotEnforcingDeps(const string & name,bool build_it)3560 Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name,
3561                                                      bool build_it) {
3562   return FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
3563 }
3564 
FindSymbol(const string & name,bool build_it)3565 Symbol DescriptorBuilder::FindSymbol(const string& name, bool build_it) {
3566   Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
3567 
3568   if (result.IsNull()) return result;
3569 
3570   if (!pool_->enforce_dependencies_) {
3571     // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
3572     return result;
3573   }
3574 
3575   // Only find symbols which were defined in this file or one of its
3576   // dependencies.
3577   const FileDescriptor* file = result.GetFile();
3578   if (file == file_ || dependencies_.count(file) > 0) {
3579     unused_dependency_.erase(file);
3580     return result;
3581   }
3582 
3583   if (result.type == Symbol::PACKAGE) {
3584     // Arg, this is overcomplicated.  The symbol is a package name.  It could
3585     // be that the package was defined in multiple files.  result.GetFile()
3586     // returns the first file we saw that used this package.  We've determined
3587     // that that file is not a direct dependency of the file we are currently
3588     // building, but it could be that some other file which *is* a direct
3589     // dependency also defines the same package.  We can't really rule out this
3590     // symbol unless none of the dependencies define it.
3591     if (IsInPackage(file_, name)) return result;
3592     for (std::set<const FileDescriptor*>::const_iterator it =
3593              dependencies_.begin();
3594          it != dependencies_.end(); ++it) {
3595       // Note:  A dependency may be NULL if it was not found or had errors.
3596       if (*it != NULL && IsInPackage(*it, name)) return result;
3597     }
3598   }
3599 
3600   possible_undeclared_dependency_ = file;
3601   possible_undeclared_dependency_name_ = name;
3602   return kNullSymbol;
3603 }
3604 
LookupSymbolNoPlaceholder(const string & name,const string & relative_to,ResolveMode resolve_mode,bool build_it)3605 Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(const string& name,
3606                                                     const string& relative_to,
3607                                                     ResolveMode resolve_mode,
3608                                                     bool build_it) {
3609   possible_undeclared_dependency_ = NULL;
3610   undefine_resolved_name_.clear();
3611 
3612   if (!name.empty() && name[0] == '.') {
3613     // Fully-qualified name.
3614     return FindSymbol(name.substr(1), build_it);
3615   }
3616 
3617   // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
3618   // defined in multiple parent scopes, we only want to find "Bar.baz" in the
3619   // innermost one.  E.g., the following should produce an error:
3620   //   message Bar { message Baz {} }
3621   //   message Foo {
3622   //     message Bar {
3623   //     }
3624   //     optional Bar.Baz baz = 1;
3625   //   }
3626   // So, we look for just "Foo" first, then look for "Bar.baz" within it if
3627   // found.
3628   string::size_type name_dot_pos = name.find_first_of('.');
3629   string first_part_of_name;
3630   if (name_dot_pos == string::npos) {
3631     first_part_of_name = name;
3632   } else {
3633     first_part_of_name = name.substr(0, name_dot_pos);
3634   }
3635 
3636   string scope_to_try(relative_to);
3637 
3638   while (true) {
3639     // Chop off the last component of the scope.
3640     string::size_type dot_pos = scope_to_try.find_last_of('.');
3641     if (dot_pos == string::npos) {
3642       return FindSymbol(name, build_it);
3643     } else {
3644       scope_to_try.erase(dot_pos);
3645     }
3646 
3647     // Append ".first_part_of_name" and try to find.
3648     string::size_type old_size = scope_to_try.size();
3649     scope_to_try.append(1, '.');
3650     scope_to_try.append(first_part_of_name);
3651     Symbol result = FindSymbol(scope_to_try, build_it);
3652     if (!result.IsNull()) {
3653       if (first_part_of_name.size() < name.size()) {
3654         // name is a compound symbol, of which we only found the first part.
3655         // Now try to look up the rest of it.
3656         if (result.IsAggregate()) {
3657           scope_to_try.append(name, first_part_of_name.size(),
3658                               name.size() - first_part_of_name.size());
3659           result = FindSymbol(scope_to_try, build_it);
3660           if (result.IsNull()) {
3661             undefine_resolved_name_ = scope_to_try;
3662           }
3663           return result;
3664         } else {
3665           // We found a symbol but it's not an aggregate.  Continue the loop.
3666         }
3667       } else {
3668         if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
3669           // We found a symbol but it's not a type.  Continue the loop.
3670         } else {
3671           return result;
3672         }
3673       }
3674     }
3675 
3676     // Not found.  Remove the name so we can try again.
3677     scope_to_try.erase(old_size);
3678   }
3679 }
3680 
LookupSymbol(const string & name,const string & relative_to,DescriptorPool::PlaceholderType placeholder_type,ResolveMode resolve_mode,bool build_it)3681 Symbol DescriptorBuilder::LookupSymbol(
3682     const string& name, const string& relative_to,
3683     DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
3684     bool build_it) {
3685   Symbol result =
3686       LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
3687   if (result.IsNull() && pool_->allow_unknown_) {
3688     // Not found, but AllowUnknownDependencies() is enabled.  Return a
3689     // placeholder instead.
3690     result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
3691   }
3692   return result;
3693 }
3694 
ValidateQualifiedName(const string & name)3695 static bool ValidateQualifiedName(const string& name) {
3696   bool last_was_period = false;
3697 
3698   for (int i = 0; i < name.size(); i++) {
3699     // I don't trust isalnum() due to locales.  :(
3700     if (('a' <= name[i] && name[i] <= 'z') ||
3701         ('A' <= name[i] && name[i] <= 'Z') ||
3702         ('0' <= name[i] && name[i] <= '9') || (name[i] == '_')) {
3703       last_was_period = false;
3704     } else if (name[i] == '.') {
3705       if (last_was_period) return false;
3706       last_was_period = true;
3707     } else {
3708       return false;
3709     }
3710   }
3711 
3712   return !name.empty() && !last_was_period;
3713 }
3714 
NewPlaceholder(const string & name,PlaceholderType placeholder_type) const3715 Symbol DescriptorPool::NewPlaceholder(const string& name,
3716                                       PlaceholderType placeholder_type) const {
3717   MutexLockMaybe lock(mutex_);
3718   return NewPlaceholderWithMutexHeld(name, placeholder_type);
3719 }
3720 
NewPlaceholderWithMutexHeld(const string & name,PlaceholderType placeholder_type) const3721 Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
3722     const string& name, PlaceholderType placeholder_type) const {
3723   if (mutex_) {
3724     mutex_->AssertHeld();
3725   }
3726   // Compute names.
3727   const string* placeholder_full_name;
3728   const string* placeholder_name;
3729   const string* placeholder_package;
3730 
3731   if (!ValidateQualifiedName(name)) return kNullSymbol;
3732   if (name[0] == '.') {
3733     // Fully-qualified.
3734     placeholder_full_name = tables_->AllocateString(name.substr(1));
3735   } else {
3736     placeholder_full_name = tables_->AllocateString(name);
3737   }
3738 
3739   string::size_type dotpos = placeholder_full_name->find_last_of('.');
3740   if (dotpos != string::npos) {
3741     placeholder_package = tables_->AllocateString(
3742       placeholder_full_name->substr(0, dotpos));
3743     placeholder_name = tables_->AllocateString(
3744       placeholder_full_name->substr(dotpos + 1));
3745   } else {
3746     placeholder_package = &internal::GetEmptyString();
3747     placeholder_name = placeholder_full_name;
3748   }
3749 
3750   // Create the placeholders.
3751   FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
3752       *placeholder_full_name + ".placeholder.proto");
3753   placeholder_file->package_ = placeholder_package;
3754 
3755   if (placeholder_type == PLACEHOLDER_ENUM) {
3756     placeholder_file->enum_type_count_ = 1;
3757     placeholder_file->enum_types_ =
3758       tables_->AllocateArray<EnumDescriptor>(1);
3759 
3760     EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
3761     memset(placeholder_enum, 0, sizeof(*placeholder_enum));
3762 
3763     placeholder_enum->full_name_ = placeholder_full_name;
3764     placeholder_enum->name_ = placeholder_name;
3765     placeholder_enum->file_ = placeholder_file;
3766     placeholder_enum->options_ = &EnumOptions::default_instance();
3767     placeholder_enum->is_placeholder_ = true;
3768     placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
3769 
3770     // Enums must have at least one value.
3771     placeholder_enum->value_count_ = 1;
3772     placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
3773 
3774     EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
3775     memset(placeholder_value, 0, sizeof(*placeholder_value));
3776 
3777     placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
3778     // Note that enum value names are siblings of their type, not children.
3779     placeholder_value->full_name_ =
3780       placeholder_package->empty() ? placeholder_value->name_ :
3781         tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE");
3782 
3783     placeholder_value->number_ = 0;
3784     placeholder_value->type_ = placeholder_enum;
3785     placeholder_value->options_ = &EnumValueOptions::default_instance();
3786 
3787     return Symbol(placeholder_enum);
3788   } else {
3789     placeholder_file->message_type_count_ = 1;
3790     placeholder_file->message_types_ =
3791       tables_->AllocateArray<Descriptor>(1);
3792 
3793     Descriptor* placeholder_message = &placeholder_file->message_types_[0];
3794     memset(placeholder_message, 0, sizeof(*placeholder_message));
3795 
3796     placeholder_message->full_name_ = placeholder_full_name;
3797     placeholder_message->name_ = placeholder_name;
3798     placeholder_message->file_ = placeholder_file;
3799     placeholder_message->options_ = &MessageOptions::default_instance();
3800     placeholder_message->is_placeholder_ = true;
3801     placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
3802 
3803     if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
3804       placeholder_message->extension_range_count_ = 1;
3805       placeholder_message->extension_ranges_ =
3806         tables_->AllocateArray<Descriptor::ExtensionRange>(1);
3807       placeholder_message->extension_ranges_->start = 1;
3808       // kMaxNumber + 1 because ExtensionRange::end is exclusive.
3809       placeholder_message->extension_ranges_->end =
3810         FieldDescriptor::kMaxNumber + 1;
3811     }
3812 
3813     return Symbol(placeholder_message);
3814   }
3815 }
3816 
NewPlaceholderFile(const string & name) const3817 FileDescriptor* DescriptorPool::NewPlaceholderFile(const string& name) const {
3818   MutexLockMaybe lock(mutex_);
3819   return NewPlaceholderFileWithMutexHeld(name);
3820 }
3821 
NewPlaceholderFileWithMutexHeld(const string & name) const3822 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
3823     const string& name) const {
3824   if (mutex_) {
3825     mutex_->AssertHeld();
3826   }
3827   FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
3828   memset(placeholder, 0, sizeof(*placeholder));
3829 
3830   placeholder->name_ = tables_->AllocateString(name);
3831   placeholder->package_ = &internal::GetEmptyString();
3832   placeholder->pool_ = this;
3833   placeholder->options_ = &FileOptions::default_instance();
3834   placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
3835   placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
3836   placeholder->is_placeholder_ = true;
3837   placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;
3838   placeholder->finished_building_ = true;
3839   // All other fields are zero or NULL.
3840 
3841   return placeholder;
3842 }
3843 
AddSymbol(const string & full_name,const void * parent,const string & name,const Message & proto,Symbol symbol)3844 bool DescriptorBuilder::AddSymbol(
3845     const string& full_name, const void* parent, const string& name,
3846     const Message& proto, Symbol symbol) {
3847   // If the caller passed NULL for the parent, the symbol is at file scope.
3848   // Use its file as the parent instead.
3849   if (parent == NULL) parent = file_;
3850 
3851   if (tables_->AddSymbol(full_name, symbol)) {
3852     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
3853       // This is only possible if there was already an error adding something of
3854       // the same name.
3855       if (!had_errors_) {
3856         GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in "
3857                        "symbols_by_name_, but was defined in "
3858                        "symbols_by_parent_; this shouldn't be possible.";
3859       }
3860       return false;
3861     }
3862     return true;
3863   } else {
3864     const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
3865     if (other_file == file_) {
3866       string::size_type dot_pos = full_name.find_last_of('.');
3867       if (dot_pos == string::npos) {
3868         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
3869                  "\"" + full_name + "\" is already defined.");
3870       } else {
3871         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
3872                  "\"" + full_name.substr(dot_pos + 1) +
3873                  "\" is already defined in \"" +
3874                  full_name.substr(0, dot_pos) + "\".");
3875       }
3876     } else {
3877       // Symbol seems to have been defined in a different file.
3878       AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
3879                "\"" + full_name + "\" is already defined in file \"" +
3880                other_file->name() + "\".");
3881     }
3882     return false;
3883   }
3884 }
3885 
AddPackage(const string & name,const Message & proto,const FileDescriptor * file)3886 void DescriptorBuilder::AddPackage(
3887     const string& name, const Message& proto, const FileDescriptor* file) {
3888   if (tables_->AddSymbol(name, Symbol(file))) {
3889     // Success.  Also add parent package, if any.
3890     string::size_type dot_pos = name.find_last_of('.');
3891     if (dot_pos == string::npos) {
3892       // No parents.
3893       ValidateSymbolName(name, name, proto);
3894     } else {
3895       // Has parent.
3896       string* parent_name = tables_->AllocateString(name.substr(0, dot_pos));
3897       AddPackage(*parent_name, proto, file);
3898       ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
3899     }
3900   } else {
3901     Symbol existing_symbol = tables_->FindSymbol(name);
3902     // It's OK to redefine a package.
3903     if (existing_symbol.type != Symbol::PACKAGE) {
3904       // Symbol seems to have been defined in a different file.
3905       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
3906                "\"" + name + "\" is already defined (as something other than "
3907                "a package) in file \"" + existing_symbol.GetFile()->name() +
3908                "\".");
3909     }
3910   }
3911 }
3912 
ValidateSymbolName(const string & name,const string & full_name,const Message & proto)3913 void DescriptorBuilder::ValidateSymbolName(
3914     const string& name, const string& full_name, const Message& proto) {
3915   if (name.empty()) {
3916     AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
3917              "Missing name.");
3918   } else {
3919     for (int i = 0; i < name.size(); i++) {
3920       // I don't trust isalnum() due to locales.  :(
3921       if ((name[i] < 'a' || 'z' < name[i]) &&
3922           (name[i] < 'A' || 'Z' < name[i]) &&
3923           (name[i] < '0' || '9' < name[i]) &&
3924           (name[i] != '_')) {
3925         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
3926                  "\"" + name + "\" is not a valid identifier.");
3927       }
3928     }
3929   }
3930 }
3931 
3932 // -------------------------------------------------------------------
3933 
3934 // This generic implementation is good for all descriptors except
3935 // FileDescriptor.
AllocateOptions(const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor)3936 template<class DescriptorT> void DescriptorBuilder::AllocateOptions(
3937     const typename DescriptorT::OptionsType& orig_options,
3938     DescriptorT* descriptor) {
3939   AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
3940                       orig_options, descriptor);
3941 }
3942 
3943 // We specialize for FileDescriptor.
AllocateOptions(const FileOptions & orig_options,FileDescriptor * descriptor)3944 void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
3945                                         FileDescriptor* descriptor) {
3946   // We add the dummy token so that LookupSymbol does the right thing.
3947   AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(),
3948                       orig_options, descriptor);
3949 }
3950 
AllocateOptionsImpl(const string & name_scope,const string & element_name,const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor)3951 template<class DescriptorT> void DescriptorBuilder::AllocateOptionsImpl(
3952     const string& name_scope,
3953     const string& element_name,
3954     const typename DescriptorT::OptionsType& orig_options,
3955     DescriptorT* descriptor) {
3956   // We need to use a dummy pointer to work around a bug in older versions of
3957   // GCC.  Otherwise, the following two lines could be replaced with:
3958   //   typename DescriptorT::OptionsType* options =
3959   //       tables_->AllocateMessage<typename DescriptorT::OptionsType>();
3960   typename DescriptorT::OptionsType* const dummy = NULL;
3961   typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
3962   // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
3963   // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
3964   // reflection based method, which requires the Descriptor. However, we are in
3965   // the middle of building the descriptors, thus the deadlock.
3966   options->ParseFromString(orig_options.SerializeAsString());
3967   descriptor->options_ = options;
3968 
3969   // Don't add to options_to_interpret_ unless there were uninterpreted
3970   // options.  This not only avoids unnecessary work, but prevents a
3971   // bootstrapping problem when building descriptors for descriptor.proto.
3972   // descriptor.proto does not contain any uninterpreted options, but
3973   // attempting to interpret options anyway will cause
3974   // OptionsType::GetDescriptor() to be called which may then deadlock since
3975   // we're still trying to build it.
3976   if (options->uninterpreted_option_size() > 0) {
3977     options_to_interpret_.push_back(
3978         OptionsToInterpret(name_scope, element_name, &orig_options, options));
3979   }
3980 }
3981 
3982 
3983 // A common pattern:  We want to convert a repeated field in the descriptor
3984 // to an array of values, calling some method to build each value.
3985 #define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)             \
3986   OUTPUT->NAME##_count_ = INPUT.NAME##_size();                       \
3987   AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_);             \
3988   for (int i = 0; i < INPUT.NAME##_size(); i++) {                    \
3989     METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i);             \
3990   }
3991 
AddRecursiveImportError(const FileDescriptorProto & proto,int from_here)3992 void DescriptorBuilder::AddRecursiveImportError(
3993     const FileDescriptorProto& proto, int from_here) {
3994   string error_message("File recursively imports itself: ");
3995   for (int i = from_here; i < tables_->pending_files_.size(); i++) {
3996     error_message.append(tables_->pending_files_[i]);
3997     error_message.append(" -> ");
3998   }
3999   error_message.append(proto.name());
4000 
4001   AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4002            error_message);
4003 }
4004 
AddTwiceListedError(const FileDescriptorProto & proto,int index)4005 void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
4006                                             int index) {
4007   AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4008            "Import \"" + proto.dependency(index) + "\" was listed twice.");
4009 }
4010 
AddImportError(const FileDescriptorProto & proto,int index)4011 void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
4012                                        int index) {
4013   string message;
4014   if (pool_->fallback_database_ == NULL) {
4015     message = "Import \"" + proto.dependency(index) +
4016               "\" has not been loaded.";
4017   } else {
4018     message = "Import \"" + proto.dependency(index) +
4019               "\" was not found or had errors.";
4020   }
4021   AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message);
4022 }
4023 
ExistingFileMatchesProto(const FileDescriptor * existing_file,const FileDescriptorProto & proto)4024 static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
4025                                      const FileDescriptorProto& proto) {
4026   FileDescriptorProto existing_proto;
4027   existing_file->CopyTo(&existing_proto);
4028   // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
4029   // syntax="proto2".
4030   if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
4031       proto.has_syntax()) {
4032     existing_proto.set_syntax(
4033         existing_file->SyntaxName(existing_file->syntax()));
4034   }
4035 
4036   return existing_proto.SerializeAsString() == proto.SerializeAsString();
4037 }
4038 
BuildFile(const FileDescriptorProto & proto)4039 const FileDescriptor* DescriptorBuilder::BuildFile(
4040     const FileDescriptorProto& proto) {
4041   filename_ = proto.name();
4042 
4043   // Check if the file already exists and is identical to the one being built.
4044   // Note:  This only works if the input is canonical -- that is, it
4045   //   fully-qualifies all type names, has no UninterpretedOptions, etc.
4046   //   This is fine, because this idempotency "feature" really only exists to
4047   //   accommodate one hack in the proto1->proto2 migration layer.
4048   const FileDescriptor* existing_file = tables_->FindFile(filename_);
4049   if (existing_file != NULL) {
4050     // File already in pool.  Compare the existing one to the input.
4051     if (ExistingFileMatchesProto(existing_file, proto)) {
4052       // They're identical.  Return the existing descriptor.
4053       return existing_file;
4054     }
4055 
4056     // Not a match.  The error will be detected and handled later.
4057   }
4058 
4059   // Check to see if this file is already on the pending files list.
4060   // TODO(kenton):  Allow recursive imports?  It may not work with some
4061   //   (most?) programming languages.  E.g., in C++, a forward declaration
4062   //   of a type is not sufficient to allow it to be used even in a
4063   //   generated header file due to inlining.  This could perhaps be
4064   //   worked around using tricks involving inserting #include statements
4065   //   mid-file, but that's pretty ugly, and I'm pretty sure there are
4066   //   some languages out there that do not allow recursive dependencies
4067   //   at all.
4068   for (int i = 0; i < tables_->pending_files_.size(); i++) {
4069     if (tables_->pending_files_[i] == proto.name()) {
4070       AddRecursiveImportError(proto, i);
4071       return NULL;
4072     }
4073   }
4074 
4075   // If we have a fallback_database_, and we aren't doing lazy import building,
4076   // attempt to load all dependencies now, before checkpointing tables_.  This
4077   // avoids confusion with recursive checkpoints.
4078   if (!pool_->lazily_build_dependencies_) {
4079     if (pool_->fallback_database_ != NULL) {
4080       tables_->pending_files_.push_back(proto.name());
4081       for (int i = 0; i < proto.dependency_size(); i++) {
4082         if (tables_->FindFile(proto.dependency(i)) == NULL &&
4083             (pool_->underlay_ == NULL ||
4084              pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) {
4085           // We don't care what this returns since we'll find out below anyway.
4086           pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
4087         }
4088       }
4089       tables_->pending_files_.pop_back();
4090     }
4091   }
4092   return BuildFileImpl(proto);
4093 }
4094 
BuildFileImpl(const FileDescriptorProto & proto)4095 const FileDescriptor* DescriptorBuilder::BuildFileImpl(
4096     const FileDescriptorProto& proto) {
4097   // Checkpoint the tables so that we can roll back if something goes wrong.
4098   tables_->AddCheckpoint();
4099 
4100   FileDescriptor* result = tables_->Allocate<FileDescriptor>();
4101   file_ = result;
4102 
4103   result->is_placeholder_ = false;
4104   result->finished_building_ = false;
4105   if (proto.has_source_code_info()) {
4106     SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
4107     info->CopyFrom(proto.source_code_info());
4108     result->source_code_info_ = info;
4109   } else {
4110     result->source_code_info_ = &SourceCodeInfo::default_instance();
4111   }
4112 
4113   file_tables_ = tables_->AllocateFileTables();
4114   file_->tables_ = file_tables_;
4115 
4116   if (!proto.has_name()) {
4117     AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
4118              "Missing field: FileDescriptorProto.name.");
4119   }
4120 
4121   // TODO(liujisi): Report error when the syntax is empty after all the protos
4122   // have added the syntax statement.
4123   if (proto.syntax().empty() || proto.syntax() == "proto2") {
4124     file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
4125   } else if (proto.syntax() == "proto3") {
4126     file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
4127   } else {
4128     file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
4129     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4130              "Unrecognized syntax: " + proto.syntax());
4131   }
4132 
4133   result->name_ = tables_->AllocateString(proto.name());
4134   if (proto.has_package()) {
4135     result->package_ = tables_->AllocateString(proto.package());
4136   } else {
4137     // We cannot rely on proto.package() returning a valid string if
4138     // proto.has_package() is false, because we might be running at static
4139     // initialization time, in which case default values have not yet been
4140     // initialized.
4141     result->package_ = tables_->AllocateString("");
4142   }
4143   result->pool_ = pool_;
4144 
4145   // Add to tables.
4146   if (!tables_->AddFile(result)) {
4147     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4148              "A file with this name is already in the pool.");
4149     // Bail out early so that if this is actually the exact same file, we
4150     // don't end up reporting that every single symbol is already defined.
4151     tables_->RollbackToLastCheckpoint();
4152     return NULL;
4153   }
4154   if (!result->package().empty()) {
4155     AddPackage(result->package(), proto, result);
4156   }
4157 
4158   // Make sure all dependencies are loaded.
4159   std::set<string> seen_dependencies;
4160   result->dependency_count_ = proto.dependency_size();
4161   result->dependencies_ =
4162       tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
4163   if (pool_->lazily_build_dependencies_) {
4164     result->dependencies_once_ = tables_->AllocateOnceDynamic();
4165     result->dependencies_names_ =
4166         tables_->AllocateArray<const string*>(proto.dependency_size());
4167     memset(result->dependencies_names_, 0,
4168            sizeof(*result->dependencies_names_) * proto.dependency_size());
4169   } else {
4170     result->dependencies_once_ = NULL;
4171     result->dependencies_names_ = NULL;
4172   }
4173   unused_dependency_.clear();
4174   std::set<int> weak_deps;
4175   for (int i = 0; i < proto.weak_dependency_size(); ++i) {
4176     weak_deps.insert(proto.weak_dependency(i));
4177   }
4178   for (int i = 0; i < proto.dependency_size(); i++) {
4179     if (!seen_dependencies.insert(proto.dependency(i)).second) {
4180       AddTwiceListedError(proto, i);
4181     }
4182 
4183     const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
4184     if (dependency == NULL && pool_->underlay_ != NULL) {
4185       dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
4186     }
4187 
4188     if (dependency == result) {
4189       // Recursive import.  dependency/result is not fully initialized, and it's
4190       // dangerous to try to do anything with it.  The recursive import error
4191       // will be detected and reported in DescriptorBuilder::BuildFile().
4192       tables_->RollbackToLastCheckpoint();
4193       return NULL;
4194     }
4195 
4196     if (dependency == NULL) {
4197       if (pool_->allow_unknown_ ||
4198           (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
4199         dependency =
4200             pool_->NewPlaceholderFileWithMutexHeld(proto.dependency(i));
4201       } else {
4202         if (!pool_->lazily_build_dependencies_) {
4203           AddImportError(proto, i);
4204         }
4205       }
4206     } else {
4207       // Add to unused_dependency_ to track unused imported files.
4208       // Note: do not track unused imported files for public import.
4209       if (pool_->enforce_dependencies_ &&
4210           (pool_->unused_import_track_files_.find(proto.name()) !=
4211            pool_->unused_import_track_files_.end()) &&
4212           (dependency->public_dependency_count() == 0)) {
4213         unused_dependency_.insert(dependency);
4214       }
4215     }
4216 
4217     result->dependencies_[i] = dependency;
4218     if (pool_->lazily_build_dependencies_ && !dependency) {
4219       result->dependencies_names_[i] =
4220           tables_->AllocateString(proto.dependency(i));
4221     }
4222   }
4223 
4224   // Check public dependencies.
4225   int public_dependency_count = 0;
4226   result->public_dependencies_ = tables_->AllocateArray<int>(
4227       proto.public_dependency_size());
4228   for (int i = 0; i < proto.public_dependency_size(); i++) {
4229     // Only put valid public dependency indexes.
4230     int index = proto.public_dependency(i);
4231     if (index >= 0 && index < proto.dependency_size()) {
4232       result->public_dependencies_[public_dependency_count++] = index;
4233       // Do not track unused imported files for public import.
4234       // Calling dependency(i) builds that file when doing lazy imports,
4235       // need to avoid doing this. Unused dependency detection isn't done
4236       // when building lazily, anyways.
4237       if (!pool_->lazily_build_dependencies_) {
4238         unused_dependency_.erase(result->dependency(index));
4239       }
4240     } else {
4241       AddError(proto.name(), proto,
4242                DescriptorPool::ErrorCollector::OTHER,
4243                "Invalid public dependency index.");
4244     }
4245   }
4246   result->public_dependency_count_ = public_dependency_count;
4247 
4248   // Build dependency set
4249   dependencies_.clear();
4250   // We don't/can't do proper dependency error checking when
4251   // lazily_build_dependencies_, and calling dependency(i) will force
4252   // a dependency to be built, which we don't want.
4253   if (!pool_->lazily_build_dependencies_) {
4254     for (int i = 0; i < result->dependency_count(); i++) {
4255       RecordPublicDependencies(result->dependency(i));
4256     }
4257   }
4258 
4259   // Check weak dependencies.
4260   int weak_dependency_count = 0;
4261   result->weak_dependencies_ = tables_->AllocateArray<int>(
4262       proto.weak_dependency_size());
4263   for (int i = 0; i < proto.weak_dependency_size(); i++) {
4264     int index = proto.weak_dependency(i);
4265     if (index >= 0 && index < proto.dependency_size()) {
4266       result->weak_dependencies_[weak_dependency_count++] = index;
4267     } else {
4268       AddError(proto.name(), proto,
4269                DescriptorPool::ErrorCollector::OTHER,
4270                "Invalid weak dependency index.");
4271     }
4272   }
4273   result->weak_dependency_count_ = weak_dependency_count;
4274 
4275   // Convert children.
4276   BUILD_ARRAY(proto, result, message_type, BuildMessage  , NULL);
4277   BUILD_ARRAY(proto, result, enum_type   , BuildEnum     , NULL);
4278   BUILD_ARRAY(proto, result, service     , BuildService  , NULL);
4279   BUILD_ARRAY(proto, result, extension   , BuildExtension, NULL);
4280 
4281   // Copy options.
4282   if (!proto.has_options()) {
4283     result->options_ = NULL;  // Will set to default_instance later.
4284   } else {
4285     AllocateOptions(proto.options(), result);
4286   }
4287 
4288   // Note that the following steps must occur in exactly the specified order.
4289 
4290   // Cross-link.
4291   CrossLinkFile(result, proto);
4292 
4293   // Interpret any remaining uninterpreted options gathered into
4294   // options_to_interpret_ during descriptor building.  Cross-linking has made
4295   // extension options known, so all interpretations should now succeed.
4296   if (!had_errors_) {
4297     OptionInterpreter option_interpreter(this);
4298     for (std::vector<OptionsToInterpret>::iterator iter =
4299              options_to_interpret_.begin();
4300          iter != options_to_interpret_.end(); ++iter) {
4301       option_interpreter.InterpretOptions(&(*iter));
4302     }
4303     options_to_interpret_.clear();
4304   }
4305 
4306   // Validate options. See comments at InternalSetLazilyBuildDependencies about
4307   // error checking and lazy import building.
4308   if (!had_errors_ && !pool_->lazily_build_dependencies_) {
4309     ValidateFileOptions(result, proto);
4310   }
4311 
4312   // Additional naming conflict check for map entry types. Only need to check
4313   // this if there are already errors.
4314   if (had_errors_) {
4315     for (int i = 0; i < proto.message_type_size(); ++i) {
4316       DetectMapConflicts(result->message_type(i), proto.message_type(i));
4317     }
4318   }
4319 
4320 
4321   // Again, see comments at InternalSetLazilyBuildDependencies about error
4322   // checking.
4323   if (!unused_dependency_.empty() && !pool_->lazily_build_dependencies_) {
4324     LogUnusedDependency(proto, result);
4325   }
4326 
4327   if (had_errors_) {
4328     tables_->RollbackToLastCheckpoint();
4329     return NULL;
4330   } else {
4331     tables_->ClearLastCheckpoint();
4332     result->finished_building_ = true;
4333     return result;
4334   }
4335 }
4336 
BuildMessage(const DescriptorProto & proto,const Descriptor * parent,Descriptor * result)4337 void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
4338                                      const Descriptor* parent,
4339                                      Descriptor* result) {
4340   const string& scope = (parent == NULL) ?
4341     file_->package() : parent->full_name();
4342   string* full_name = tables_->AllocateString(scope);
4343   if (!full_name->empty()) full_name->append(1, '.');
4344   full_name->append(proto.name());
4345 
4346   ValidateSymbolName(proto.name(), *full_name, proto);
4347 
4348   result->name_            = tables_->AllocateString(proto.name());
4349   result->full_name_       = full_name;
4350   result->file_            = file_;
4351   result->containing_type_ = parent;
4352   result->is_placeholder_  = false;
4353   result->is_unqualified_placeholder_ = false;
4354 
4355   // Build oneofs first so that fields and extension ranges can refer to them.
4356   BUILD_ARRAY(proto, result, oneof_decl     , BuildOneof         , result);
4357   BUILD_ARRAY(proto, result, field          , BuildField         , result);
4358   BUILD_ARRAY(proto, result, nested_type    , BuildMessage       , result);
4359   BUILD_ARRAY(proto, result, enum_type      , BuildEnum          , result);
4360   BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
4361   BUILD_ARRAY(proto, result, extension      , BuildExtension     , result);
4362   BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result);
4363 
4364   // Copy reserved names.
4365   int reserved_name_count = proto.reserved_name_size();
4366   result->reserved_name_count_ = reserved_name_count;
4367   result->reserved_names_ =
4368       tables_->AllocateArray<const string*>(reserved_name_count);
4369   for (int i = 0; i < reserved_name_count; ++i) {
4370     result->reserved_names_[i] =
4371         tables_->AllocateString(proto.reserved_name(i));
4372   }
4373 
4374   // Copy options.
4375   if (!proto.has_options()) {
4376     result->options_ = NULL;  // Will set to default_instance later.
4377   } else {
4378     AllocateOptions(proto.options(), result);
4379   }
4380 
4381   AddSymbol(result->full_name(), parent, result->name(),
4382             proto, Symbol(result));
4383 
4384   for (int i = 0; i < proto.reserved_range_size(); i++) {
4385     const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
4386     for (int j = i + 1; j < proto.reserved_range_size(); j++) {
4387       const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
4388       if (range1.end() > range2.start() && range2.end() > range1.start()) {
4389         AddError(result->full_name(), proto.reserved_range(i),
4390                  DescriptorPool::ErrorCollector::NUMBER,
4391                  strings::Substitute("Reserved range $0 to $1 overlaps with "
4392                                      "already-defined range $2 to $3.",
4393                                      range2.start(), range2.end() - 1,
4394                                      range1.start(), range1.end() - 1));
4395       }
4396     }
4397   }
4398 
4399   hash_set<string> reserved_name_set;
4400   for (int i = 0; i < proto.reserved_name_size(); i++) {
4401     const string& name = proto.reserved_name(i);
4402     if (reserved_name_set.find(name) == reserved_name_set.end()) {
4403       reserved_name_set.insert(name);
4404     } else {
4405       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4406                strings::Substitute(
4407                  "Field name \"$0\" is reserved multiple times.",
4408                  name));
4409     }
4410   }
4411 
4412   for (int i = 0; i < result->field_count(); i++) {
4413     const FieldDescriptor* field = result->field(i);
4414     for (int j = 0; j < result->extension_range_count(); j++) {
4415       const Descriptor::ExtensionRange* range = result->extension_range(j);
4416       if (range->start <= field->number() && field->number() < range->end) {
4417         AddError(field->full_name(), proto.extension_range(j),
4418                  DescriptorPool::ErrorCollector::NUMBER,
4419                  strings::Substitute(
4420                    "Extension range $0 to $1 includes field \"$2\" ($3).",
4421                    range->start, range->end - 1,
4422                    field->name(), field->number()));
4423       }
4424     }
4425     for (int j = 0; j < result->reserved_range_count(); j++) {
4426       const Descriptor::ReservedRange* range = result->reserved_range(j);
4427       if (range->start <= field->number() && field->number() < range->end) {
4428         AddError(field->full_name(), proto.reserved_range(j),
4429                  DescriptorPool::ErrorCollector::NUMBER,
4430                  strings::Substitute(
4431                    "Field \"$0\" uses reserved number $1.",
4432                    field->name(), field->number()));
4433       }
4434     }
4435     if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
4436       AddError(field->full_name(), proto.field(i),
4437                DescriptorPool::ErrorCollector::NAME,
4438                strings::Substitute(
4439                  "Field name \"$0\" is reserved.", field->name()));
4440     }
4441   }
4442 
4443   // Check that extension ranges don't overlap and don't include
4444   // reserved field numbers.
4445   for (int i = 0; i < result->extension_range_count(); i++) {
4446     const Descriptor::ExtensionRange* range1 = result->extension_range(i);
4447     for (int j = 0; j < result->reserved_range_count(); j++) {
4448       const Descriptor::ReservedRange* range2 = result->reserved_range(j);
4449       if (range1->end > range2->start && range2->end > range1->start) {
4450         AddError(result->full_name(), proto.extension_range(i),
4451                  DescriptorPool::ErrorCollector::NUMBER,
4452                  strings::Substitute("Extension range $0 to $1 overlaps with "
4453                                      "reserved range $2 to $3.",
4454                                      range1->start, range1->end - 1,
4455                                      range2->start, range2->end - 1));
4456       }
4457     }
4458     for (int j = i + 1; j < result->extension_range_count(); j++) {
4459       const Descriptor::ExtensionRange* range2 = result->extension_range(j);
4460       if (range1->end > range2->start && range2->end > range1->start) {
4461         AddError(result->full_name(), proto.extension_range(i),
4462                  DescriptorPool::ErrorCollector::NUMBER,
4463                  strings::Substitute("Extension range $0 to $1 overlaps with "
4464                                      "already-defined range $2 to $3.",
4465                                      range2->start, range2->end - 1,
4466                                      range1->start, range1->end - 1));
4467       }
4468     }
4469   }
4470 }
4471 
4472 
BuildFieldOrExtension(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result,bool is_extension)4473 void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
4474                                               const Descriptor* parent,
4475                                               FieldDescriptor* result,
4476                                               bool is_extension) {
4477   const string& scope = (parent == NULL) ?
4478     file_->package() : parent->full_name();
4479   string* full_name = tables_->AllocateString(scope);
4480   if (!full_name->empty()) full_name->append(1, '.');
4481   full_name->append(proto.name());
4482 
4483   ValidateSymbolName(proto.name(), *full_name, proto);
4484 
4485   result->name_         = tables_->AllocateString(proto.name());
4486   result->full_name_    = full_name;
4487   result->file_         = file_;
4488   result->number_       = proto.number();
4489   result->is_extension_ = is_extension;
4490 
4491   // If .proto files follow the style guide then the name should already be
4492   // lower-cased.  If that's the case we can just reuse the string we already
4493   // allocated rather than allocate a new one.
4494   string lowercase_name(proto.name());
4495   LowerString(&lowercase_name);
4496   if (lowercase_name == proto.name()) {
4497     result->lowercase_name_ = result->name_;
4498   } else {
4499     result->lowercase_name_ = tables_->AllocateString(lowercase_name);
4500   }
4501 
4502   // Don't bother with the above optimization for camel-case names since
4503   // .proto files that follow the guide shouldn't be using names in this
4504   // format, so the optimization wouldn't help much.
4505   result->camelcase_name_ =
4506       tables_->AllocateString(ToCamelCase(proto.name(),
4507                                           /* lower_first = */ true));
4508 
4509   if (proto.has_json_name()) {
4510     result->has_json_name_ = true;
4511     result->json_name_ = tables_->AllocateString(proto.json_name());
4512   } else {
4513     result->has_json_name_ = false;
4514     result->json_name_ = tables_->AllocateString(ToJsonName(proto.name()));
4515   }
4516 
4517   // Some compilers do not allow static_cast directly between two enum types,
4518   // so we must cast to int first.
4519   result->type_  = static_cast<FieldDescriptor::Type>(
4520                      implicit_cast<int>(proto.type()));
4521   result->label_ = static_cast<FieldDescriptor::Label>(
4522                      implicit_cast<int>(proto.label()));
4523 
4524   // An extension cannot have a required field (b/13365836).
4525   if (result->is_extension_ &&
4526       result->label_ == FieldDescriptor::LABEL_REQUIRED) {
4527     AddError(result->full_name(), proto,
4528              // Error location `TYPE`: we would really like to indicate
4529              // `LABEL`, but the `ErrorLocation` enum has no entry for this, and
4530              // we don't necessarily know about all implementations of the
4531              // `ErrorCollector` interface to extend them to handle the new
4532              // error location type properly.
4533              DescriptorPool::ErrorCollector::TYPE,
4534              "Message extensions cannot have required fields.");
4535   }
4536 
4537   // Some of these may be filled in when cross-linking.
4538   result->containing_type_ = NULL;
4539   result->extension_scope_ = NULL;
4540   result->message_type_ = NULL;
4541   result->enum_type_ = NULL;
4542   result->type_name_ = NULL;
4543   result->type_once_ = NULL;
4544   result->default_value_enum_ = NULL;
4545   result->default_value_enum_name_ = NULL;
4546 
4547   result->has_default_value_ = proto.has_default_value();
4548   if (proto.has_default_value() && result->is_repeated()) {
4549     AddError(result->full_name(), proto,
4550              DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4551              "Repeated fields can't have default values.");
4552   }
4553 
4554   if (proto.has_type()) {
4555     if (proto.has_default_value()) {
4556       char* end_pos = NULL;
4557       switch (result->cpp_type()) {
4558         case FieldDescriptor::CPPTYPE_INT32:
4559           result->default_value_int32_ =
4560             strtol(proto.default_value().c_str(), &end_pos, 0);
4561           break;
4562         case FieldDescriptor::CPPTYPE_INT64:
4563           result->default_value_int64_ =
4564             strto64(proto.default_value().c_str(), &end_pos, 0);
4565           break;
4566         case FieldDescriptor::CPPTYPE_UINT32:
4567           result->default_value_uint32_ =
4568             strtoul(proto.default_value().c_str(), &end_pos, 0);
4569           break;
4570         case FieldDescriptor::CPPTYPE_UINT64:
4571           result->default_value_uint64_ =
4572             strtou64(proto.default_value().c_str(), &end_pos, 0);
4573           break;
4574         case FieldDescriptor::CPPTYPE_FLOAT:
4575           if (proto.default_value() == "inf") {
4576             result->default_value_float_ =
4577                 std::numeric_limits<float>::infinity();
4578           } else if (proto.default_value() == "-inf") {
4579             result->default_value_float_ =
4580                 -std::numeric_limits<float>::infinity();
4581           } else if (proto.default_value() == "nan") {
4582             result->default_value_float_ =
4583                 std::numeric_limits<float>::quiet_NaN();
4584           } else  {
4585             result->default_value_float_ = io::SafeDoubleToFloat(
4586                 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
4587           }
4588           break;
4589         case FieldDescriptor::CPPTYPE_DOUBLE:
4590           if (proto.default_value() == "inf") {
4591             result->default_value_double_ =
4592                 std::numeric_limits<double>::infinity();
4593           } else if (proto.default_value() == "-inf") {
4594             result->default_value_double_ =
4595                 -std::numeric_limits<double>::infinity();
4596           } else if (proto.default_value() == "nan") {
4597             result->default_value_double_ =
4598                 std::numeric_limits<double>::quiet_NaN();
4599           } else  {
4600             result->default_value_double_ =
4601                 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
4602           }
4603           break;
4604         case FieldDescriptor::CPPTYPE_BOOL:
4605           if (proto.default_value() == "true") {
4606             result->default_value_bool_ = true;
4607           } else if (proto.default_value() == "false") {
4608             result->default_value_bool_ = false;
4609           } else {
4610             AddError(result->full_name(), proto,
4611                      DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4612                      "Boolean default must be true or false.");
4613           }
4614           break;
4615         case FieldDescriptor::CPPTYPE_ENUM:
4616           // This will be filled in when cross-linking.
4617           result->default_value_enum_ = NULL;
4618           break;
4619         case FieldDescriptor::CPPTYPE_STRING:
4620           if (result->type() == FieldDescriptor::TYPE_BYTES) {
4621             result->default_value_string_ = tables_->AllocateString(
4622               UnescapeCEscapeString(proto.default_value()));
4623           } else {
4624             result->default_value_string_ =
4625                 tables_->AllocateString(proto.default_value());
4626           }
4627           break;
4628         case FieldDescriptor::CPPTYPE_MESSAGE:
4629           AddError(result->full_name(), proto,
4630                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4631                    "Messages can't have default values.");
4632           result->has_default_value_ = false;
4633           break;
4634       }
4635 
4636       if (end_pos != NULL) {
4637         // end_pos is only set non-NULL by the parsers for numeric types, above.
4638         // This checks that the default was non-empty and had no extra junk
4639         // after the end of the number.
4640         if (proto.default_value().empty() || *end_pos != '\0') {
4641           AddError(result->full_name(), proto,
4642                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4643                    "Couldn't parse default value \"" + proto.default_value() +
4644                    "\".");
4645         }
4646       }
4647     } else {
4648       // No explicit default value
4649       switch (result->cpp_type()) {
4650         case FieldDescriptor::CPPTYPE_INT32:
4651           result->default_value_int32_ = 0;
4652           break;
4653         case FieldDescriptor::CPPTYPE_INT64:
4654           result->default_value_int64_ = 0;
4655           break;
4656         case FieldDescriptor::CPPTYPE_UINT32:
4657           result->default_value_uint32_ = 0;
4658           break;
4659         case FieldDescriptor::CPPTYPE_UINT64:
4660           result->default_value_uint64_ = 0;
4661           break;
4662         case FieldDescriptor::CPPTYPE_FLOAT:
4663           result->default_value_float_ = 0.0f;
4664           break;
4665         case FieldDescriptor::CPPTYPE_DOUBLE:
4666           result->default_value_double_ = 0.0;
4667           break;
4668         case FieldDescriptor::CPPTYPE_BOOL:
4669           result->default_value_bool_ = false;
4670           break;
4671         case FieldDescriptor::CPPTYPE_ENUM:
4672           // This will be filled in when cross-linking.
4673           result->default_value_enum_ = NULL;
4674           break;
4675         case FieldDescriptor::CPPTYPE_STRING:
4676           result->default_value_string_ = &internal::GetEmptyString();
4677           break;
4678         case FieldDescriptor::CPPTYPE_MESSAGE:
4679           break;
4680       }
4681     }
4682   }
4683 
4684   if (result->number() <= 0) {
4685     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4686              "Field numbers must be positive integers.");
4687   } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
4688     // Only validate that the number is within the valid field range if it is
4689     // not an extension. Since extension numbers are validated with the
4690     // extendee's valid set of extension numbers, and those are in turn
4691     // validated against the max allowed number, the check is unnecessary for
4692     // extension fields.
4693     // This avoids cross-linking issues that arise when attempting to check if
4694     // the extendee is a message_set_wire_format message, which has a higher max
4695     // on extension numbers.
4696     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4697              strings::Substitute("Field numbers cannot be greater than $0.",
4698                                  FieldDescriptor::kMaxNumber));
4699   } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
4700              result->number() <= FieldDescriptor::kLastReservedNumber) {
4701     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4702              strings::Substitute(
4703                "Field numbers $0 through $1 are reserved for the protocol "
4704                "buffer library implementation.",
4705                FieldDescriptor::kFirstReservedNumber,
4706                FieldDescriptor::kLastReservedNumber));
4707   }
4708 
4709   if (is_extension) {
4710     if (!proto.has_extendee()) {
4711       AddError(result->full_name(), proto,
4712                DescriptorPool::ErrorCollector::EXTENDEE,
4713                "FieldDescriptorProto.extendee not set for extension field.");
4714     }
4715 
4716     result->extension_scope_ = parent;
4717 
4718     if (proto.has_oneof_index()) {
4719       AddError(result->full_name(), proto,
4720                DescriptorPool::ErrorCollector::OTHER,
4721                "FieldDescriptorProto.oneof_index should not be set for "
4722                "extensions.");
4723     }
4724 
4725     // Fill in later (maybe).
4726     result->containing_oneof_ = NULL;
4727   } else {
4728     if (proto.has_extendee()) {
4729       AddError(result->full_name(), proto,
4730                DescriptorPool::ErrorCollector::EXTENDEE,
4731                "FieldDescriptorProto.extendee set for non-extension field.");
4732     }
4733 
4734     result->containing_type_ = parent;
4735 
4736     if (proto.has_oneof_index()) {
4737       if (proto.oneof_index() < 0 ||
4738           proto.oneof_index() >= parent->oneof_decl_count()) {
4739         AddError(result->full_name(), proto,
4740                  DescriptorPool::ErrorCollector::OTHER,
4741                  strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
4742                                      "out of range for type \"$1\".",
4743                                      proto.oneof_index(),
4744                                      parent->name()));
4745         result->containing_oneof_ = NULL;
4746       } else {
4747         result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
4748       }
4749     } else {
4750       result->containing_oneof_ = NULL;
4751     }
4752   }
4753 
4754   // Copy options.
4755   if (!proto.has_options()) {
4756     result->options_ = NULL;  // Will set to default_instance later.
4757   } else {
4758     AllocateOptions(proto.options(), result);
4759   }
4760 
4761 
4762   AddSymbol(result->full_name(), parent, result->name(),
4763             proto, Symbol(result));
4764 }
4765 
BuildExtensionRange(const DescriptorProto::ExtensionRange & proto,const Descriptor * parent,Descriptor::ExtensionRange * result)4766 void DescriptorBuilder::BuildExtensionRange(
4767     const DescriptorProto::ExtensionRange& proto,
4768     const Descriptor* parent,
4769     Descriptor::ExtensionRange* result) {
4770   result->start = proto.start();
4771   result->end = proto.end();
4772   if (result->start <= 0) {
4773     AddError(parent->full_name(), proto,
4774              DescriptorPool::ErrorCollector::NUMBER,
4775              "Extension numbers must be positive integers.");
4776   }
4777 
4778   // Checking of the upper bound of the extension range is deferred until after
4779   // options interpreting. This allows messages with message_set_wire_format to
4780   // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
4781   // numbers are actually used as int32s in the message_set_wire_format.
4782 
4783   if (result->start >= result->end) {
4784     AddError(parent->full_name(), proto,
4785              DescriptorPool::ErrorCollector::NUMBER,
4786              "Extension range end number must be greater than start number.");
4787   }
4788 
4789   if (!proto.has_options()) {
4790     result->options_ = NULL;  // Will set to default_instance later.
4791   } else {
4792     AllocateOptionsImpl(parent->full_name(), parent->full_name(),
4793                         proto.options(), result);
4794   }
4795 }
4796 
BuildReservedRange(const DescriptorProto::ReservedRange & proto,const Descriptor * parent,Descriptor::ReservedRange * result)4797 void DescriptorBuilder::BuildReservedRange(
4798     const DescriptorProto::ReservedRange& proto,
4799     const Descriptor* parent,
4800     Descriptor::ReservedRange* result) {
4801   result->start = proto.start();
4802   result->end = proto.end();
4803   if (result->start <= 0) {
4804     AddError(parent->full_name(), proto,
4805              DescriptorPool::ErrorCollector::NUMBER,
4806              "Reserved numbers must be positive integers.");
4807   }
4808 }
4809 
BuildOneof(const OneofDescriptorProto & proto,Descriptor * parent,OneofDescriptor * result)4810 void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
4811                                    Descriptor* parent,
4812                                    OneofDescriptor* result) {
4813   string* full_name = tables_->AllocateString(parent->full_name());
4814   full_name->append(1, '.');
4815   full_name->append(proto.name());
4816 
4817   ValidateSymbolName(proto.name(), *full_name, proto);
4818 
4819   result->name_ = tables_->AllocateString(proto.name());
4820   result->full_name_ = full_name;
4821 
4822   result->containing_type_ = parent;
4823 
4824   // We need to fill these in later.
4825   result->field_count_ = 0;
4826   result->fields_ = NULL;
4827 
4828   // Copy options.
4829   if (!proto.has_options()) {
4830     result->options_ = NULL;  // Will set to default_instance later.
4831   } else {
4832     AllocateOptions(proto.options(), result);
4833   }
4834 
4835   AddSymbol(result->full_name(), parent, result->name(),
4836             proto, Symbol(result));
4837 }
4838 
CheckEnumValueUniqueness(const EnumDescriptorProto & proto,const EnumDescriptor * result)4839 void DescriptorBuilder::CheckEnumValueUniqueness(
4840     const EnumDescriptorProto& proto, const EnumDescriptor* result) {
4841 
4842   // Check that enum labels are still unique when we remove the enum prefix from
4843   // values that have it.
4844   //
4845   // This will fail for something like:
4846   //
4847   //   enum MyEnum {
4848   //     MY_ENUM_FOO = 0;
4849   //     FOO = 1;
4850   //   }
4851   //
4852   // By enforcing this reasonable constraint, we allow code generators to strip
4853   // the prefix and/or PascalCase it without creating conflicts.  This can lead
4854   // to much nicer language-specific enums like:
4855   //
4856   //   enum NameType {
4857   //     FirstName = 1,
4858   //     LastName = 2,
4859   //   }
4860   //
4861   // Instead of:
4862   //
4863   //   enum NameType {
4864   //     NAME_TYPE_FIRST_NAME = 1,
4865   //     NAME_TYPE_LAST_NAME = 2,
4866   //   }
4867   PrefixRemover remover(result->name());
4868   std::map<string, const google::protobuf::EnumValueDescriptor*> values;
4869   for (int i = 0; i < result->value_count(); i++) {
4870     const google::protobuf::EnumValueDescriptor* value = result->value(i);
4871     string stripped =
4872         EnumValueToPascalCase(remover.MaybeRemove(value->name()));
4873     std::pair<std::map<string, const google::protobuf::EnumValueDescriptor*>::iterator,
4874               bool>
4875         insert_result = values.insert(std::make_pair(stripped, value));
4876     bool inserted = insert_result.second;
4877 
4878     // We don't throw the error if the two conflicting symbols are identical, or
4879     // if they map to the same number.  In the former case, the normal symbol
4880     // duplication error will fire so we don't need to (and its error message
4881     // will make more sense). We allow the latter case so users can create
4882     // aliases which add or remove the prefix (code generators that do prefix
4883     // stripping should de-dup the labels in this case).
4884     if (!inserted && insert_result.first->second->name() != value->name() &&
4885         insert_result.first->second->number() != value->number()) {
4886       string error_message =
4887           "When enum name is stripped and label is PascalCased (" + stripped +
4888           "), this value label conflicts with " + values[stripped]->name() +
4889           ". This will make the proto fail to compile for some languages, such "
4890           "as C#.";
4891       // There are proto2 enums out there with conflicting names, so to preserve
4892       // compatibility we issue only a warning for proto2.
4893       if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
4894         AddWarning(value->full_name(), proto.value(i),
4895                    DescriptorPool::ErrorCollector::NAME, error_message);
4896       } else {
4897         AddError(value->full_name(), proto.value(i),
4898                  DescriptorPool::ErrorCollector::NAME, error_message);
4899       }
4900     }
4901   }
4902 }
4903 
BuildEnum(const EnumDescriptorProto & proto,const Descriptor * parent,EnumDescriptor * result)4904 void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
4905                                   const Descriptor* parent,
4906                                   EnumDescriptor* result) {
4907   const string& scope = (parent == NULL) ?
4908     file_->package() : parent->full_name();
4909   string* full_name = tables_->AllocateString(scope);
4910   if (!full_name->empty()) full_name->append(1, '.');
4911   full_name->append(proto.name());
4912 
4913   ValidateSymbolName(proto.name(), *full_name, proto);
4914 
4915   result->name_            = tables_->AllocateString(proto.name());
4916   result->full_name_       = full_name;
4917   result->file_            = file_;
4918   result->containing_type_ = parent;
4919   result->is_placeholder_  = false;
4920   result->is_unqualified_placeholder_ = false;
4921 
4922   if (proto.value_size() == 0) {
4923     // We cannot allow enums with no values because this would mean there
4924     // would be no valid default value for fields of this type.
4925     AddError(result->full_name(), proto,
4926              DescriptorPool::ErrorCollector::NAME,
4927              "Enums must contain at least one value.");
4928   }
4929 
4930   BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
4931 
4932   CheckEnumValueUniqueness(proto, result);
4933 
4934   // Copy options.
4935   if (!proto.has_options()) {
4936     result->options_ = NULL;  // Will set to default_instance later.
4937   } else {
4938     AllocateOptions(proto.options(), result);
4939   }
4940 
4941   AddSymbol(result->full_name(), parent, result->name(),
4942             proto, Symbol(result));
4943 }
4944 
BuildEnumValue(const EnumValueDescriptorProto & proto,const EnumDescriptor * parent,EnumValueDescriptor * result)4945 void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
4946                                        const EnumDescriptor* parent,
4947                                        EnumValueDescriptor* result) {
4948   result->name_   = tables_->AllocateString(proto.name());
4949   result->number_ = proto.number();
4950   result->type_   = parent;
4951 
4952   // Note:  full_name for enum values is a sibling to the parent's name, not a
4953   //   child of it.
4954   string* full_name = tables_->AllocateString(*parent->full_name_);
4955   full_name->resize(full_name->size() - parent->name_->size());
4956   full_name->append(*result->name_);
4957   result->full_name_ = full_name;
4958 
4959   ValidateSymbolName(proto.name(), *full_name, proto);
4960 
4961   // Copy options.
4962   if (!proto.has_options()) {
4963     result->options_ = NULL;  // Will set to default_instance later.
4964   } else {
4965     AllocateOptions(proto.options(), result);
4966   }
4967 
4968   // Again, enum values are weird because we makes them appear as siblings
4969   // of the enum type instead of children of it.  So, we use
4970   // parent->containing_type() as the value's parent.
4971   bool added_to_outer_scope =
4972     AddSymbol(result->full_name(), parent->containing_type(), result->name(),
4973               proto, Symbol(result));
4974 
4975   // However, we also want to be able to search for values within a single
4976   // enum type, so we add it as a child of the enum type itself, too.
4977   // Note:  This could fail, but if it does, the error has already been
4978   //   reported by the above AddSymbol() call, so we ignore the return code.
4979   bool added_to_inner_scope =
4980     file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
4981 
4982   if (added_to_inner_scope && !added_to_outer_scope) {
4983     // This value did not conflict with any values defined in the same enum,
4984     // but it did conflict with some other symbol defined in the enum type's
4985     // scope.  Let's print an additional error to explain this.
4986     string outer_scope;
4987     if (parent->containing_type() == NULL) {
4988       outer_scope = file_->package();
4989     } else {
4990       outer_scope = parent->containing_type()->full_name();
4991     }
4992 
4993     if (outer_scope.empty()) {
4994       outer_scope = "the global scope";
4995     } else {
4996       outer_scope = "\"" + outer_scope + "\"";
4997     }
4998 
4999     AddError(result->full_name(), proto,
5000              DescriptorPool::ErrorCollector::NAME,
5001              "Note that enum values use C++ scoping rules, meaning that "
5002              "enum values are siblings of their type, not children of it.  "
5003              "Therefore, \"" + result->name() + "\" must be unique within "
5004              + outer_scope + ", not just within \"" + parent->name() + "\".");
5005   }
5006 
5007   // An enum is allowed to define two numbers that refer to the same value.
5008   // FindValueByNumber() should return the first such value, so we simply
5009   // ignore AddEnumValueByNumber()'s return code.
5010   file_tables_->AddEnumValueByNumber(result);
5011 }
5012 
BuildService(const ServiceDescriptorProto & proto,const void *,ServiceDescriptor * result)5013 void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
5014                                      const void* /* dummy */,
5015                                      ServiceDescriptor* result) {
5016   string* full_name = tables_->AllocateString(file_->package());
5017   if (!full_name->empty()) full_name->append(1, '.');
5018   full_name->append(proto.name());
5019 
5020   ValidateSymbolName(proto.name(), *full_name, proto);
5021 
5022   result->name_      = tables_->AllocateString(proto.name());
5023   result->full_name_ = full_name;
5024   result->file_      = file_;
5025 
5026   BUILD_ARRAY(proto, result, method, BuildMethod, result);
5027 
5028   // Copy options.
5029   if (!proto.has_options()) {
5030     result->options_ = NULL;  // Will set to default_instance later.
5031   } else {
5032     AllocateOptions(proto.options(), result);
5033   }
5034 
5035   AddSymbol(result->full_name(), NULL, result->name(),
5036             proto, Symbol(result));
5037 }
5038 
BuildMethod(const MethodDescriptorProto & proto,const ServiceDescriptor * parent,MethodDescriptor * result)5039 void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
5040                                     const ServiceDescriptor* parent,
5041                                     MethodDescriptor* result) {
5042   result->name_    = tables_->AllocateString(proto.name());
5043   result->service_ = parent;
5044 
5045   string* full_name = tables_->AllocateString(parent->full_name());
5046   full_name->append(1, '.');
5047   full_name->append(*result->name_);
5048   result->full_name_ = full_name;
5049 
5050   ValidateSymbolName(proto.name(), *full_name, proto);
5051 
5052   // These will be filled in when cross-linking.
5053   result->input_type_.Init();
5054   result->output_type_.Init();
5055 
5056   // Copy options.
5057   if (!proto.has_options()) {
5058     result->options_ = NULL;  // Will set to default_instance later.
5059   } else {
5060     AllocateOptions(proto.options(), result);
5061   }
5062 
5063   result->client_streaming_ = proto.client_streaming();
5064   result->server_streaming_ = proto.server_streaming();
5065 
5066   AddSymbol(result->full_name(), parent, result->name(),
5067             proto, Symbol(result));
5068 }
5069 
5070 #undef BUILD_ARRAY
5071 
5072 // -------------------------------------------------------------------
5073 
CrossLinkFile(FileDescriptor * file,const FileDescriptorProto & proto)5074 void DescriptorBuilder::CrossLinkFile(
5075     FileDescriptor* file, const FileDescriptorProto& proto) {
5076   if (file->options_ == NULL) {
5077     file->options_ = &FileOptions::default_instance();
5078   }
5079 
5080   for (int i = 0; i < file->message_type_count(); i++) {
5081     CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
5082   }
5083 
5084   for (int i = 0; i < file->extension_count(); i++) {
5085     CrossLinkField(&file->extensions_[i], proto.extension(i));
5086   }
5087 
5088   for (int i = 0; i < file->enum_type_count(); i++) {
5089     CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
5090   }
5091 
5092   for (int i = 0; i < file->service_count(); i++) {
5093     CrossLinkService(&file->services_[i], proto.service(i));
5094   }
5095 }
5096 
CrossLinkMessage(Descriptor * message,const DescriptorProto & proto)5097 void DescriptorBuilder::CrossLinkMessage(
5098     Descriptor* message, const DescriptorProto& proto) {
5099   if (message->options_ == NULL) {
5100     message->options_ = &MessageOptions::default_instance();
5101   }
5102 
5103   for (int i = 0; i < message->nested_type_count(); i++) {
5104     CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
5105   }
5106 
5107   for (int i = 0; i < message->enum_type_count(); i++) {
5108     CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
5109   }
5110 
5111   for (int i = 0; i < message->field_count(); i++) {
5112     CrossLinkField(&message->fields_[i], proto.field(i));
5113   }
5114 
5115   for (int i = 0; i < message->extension_count(); i++) {
5116     CrossLinkField(&message->extensions_[i], proto.extension(i));
5117   }
5118 
5119   for (int i = 0; i < message->extension_range_count(); i++) {
5120     CrossLinkExtensionRange(&message->extension_ranges_[i],
5121                             proto.extension_range(i));
5122   }
5123 
5124   // Set up field array for each oneof.
5125 
5126   // First count the number of fields per oneof.
5127   for (int i = 0; i < message->field_count(); i++) {
5128     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5129     if (oneof_decl != NULL) {
5130       // Make sure fields belonging to the same oneof are defined consecutively.
5131       // This enables optimizations in codegens and reflection libraries to
5132       // skip fields in the oneof group, as only one of the field can be set.
5133       // Note that field_count() returns how many fields in this oneof we have
5134       // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
5135       // safe.
5136       if (oneof_decl->field_count() > 0 &&
5137           message->field(i - 1)->containing_oneof() != oneof_decl) {
5138         AddError(
5139             message->full_name() + "." + message->field(i - 1)->name(),
5140             proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
5141             strings::Substitute(
5142                 "Fields in the same oneof must be defined consecutively. "
5143                 "\"$0\" cannot be defined before the completion of the "
5144                 "\"$1\" oneof definition.",
5145                 message->field(i - 1)->name(), oneof_decl->name()));
5146       }
5147       // Must go through oneof_decls_ array to get a non-const version of the
5148       // OneofDescriptor.
5149       ++message->oneof_decls_[oneof_decl->index()].field_count_;
5150     }
5151   }
5152 
5153   // Then allocate the arrays.
5154   for (int i = 0; i < message->oneof_decl_count(); i++) {
5155     OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
5156 
5157     if (oneof_decl->field_count() == 0) {
5158       AddError(message->full_name() + "." + oneof_decl->name(),
5159                proto.oneof_decl(i),
5160                DescriptorPool::ErrorCollector::NAME,
5161                "Oneof must have at least one field.");
5162     }
5163 
5164     oneof_decl->fields_ =
5165       tables_->AllocateArray<const FieldDescriptor*>(oneof_decl->field_count_);
5166     oneof_decl->field_count_ = 0;
5167 
5168     if (oneof_decl->options_ == NULL) {
5169       oneof_decl->options_ = &OneofOptions::default_instance();
5170     }
5171   }
5172 
5173   // Then fill them in.
5174   for (int i = 0; i < message->field_count(); i++) {
5175     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5176     if (oneof_decl != NULL) {
5177       OneofDescriptor* mutable_oneof_decl =
5178           &message->oneof_decls_[oneof_decl->index()];
5179       message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
5180       mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] =
5181           message->field(i);
5182     }
5183   }
5184 }
5185 
CrossLinkExtensionRange(Descriptor::ExtensionRange * range,const DescriptorProto::ExtensionRange & proto)5186 void DescriptorBuilder::CrossLinkExtensionRange(
5187     Descriptor::ExtensionRange* range,
5188     const DescriptorProto::ExtensionRange& proto) {
5189   if (range->options_ == NULL) {
5190     range->options_ = &ExtensionRangeOptions::default_instance();
5191   }
5192 }
5193 
CrossLinkField(FieldDescriptor * field,const FieldDescriptorProto & proto)5194 void DescriptorBuilder::CrossLinkField(
5195     FieldDescriptor* field, const FieldDescriptorProto& proto) {
5196   if (field->options_ == NULL) {
5197     field->options_ = &FieldOptions::default_instance();
5198   }
5199 
5200   // Add the field to the lowercase-name and camelcase-name tables.
5201   file_tables_->AddFieldByStylizedNames(field);
5202 
5203   if (proto.has_extendee()) {
5204     Symbol extendee =
5205         LookupSymbol(proto.extendee(), field->full_name(),
5206                      DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
5207     if (extendee.IsNull()) {
5208       AddNotDefinedError(field->full_name(), proto,
5209                          DescriptorPool::ErrorCollector::EXTENDEE,
5210                          proto.extendee());
5211       return;
5212     } else if (extendee.type != Symbol::MESSAGE) {
5213       AddError(field->full_name(), proto,
5214                DescriptorPool::ErrorCollector::EXTENDEE,
5215                "\"" + proto.extendee() + "\" is not a message type.");
5216       return;
5217     }
5218     field->containing_type_ = extendee.descriptor;
5219 
5220     const Descriptor::ExtensionRange* extension_range = field->containing_type()
5221         ->FindExtensionRangeContainingNumber(field->number());
5222 
5223     if (extension_range == NULL) {
5224       AddError(field->full_name(), proto,
5225                DescriptorPool::ErrorCollector::NUMBER,
5226                strings::Substitute("\"$0\" does not declare $1 as an "
5227                                    "extension number.",
5228                                    field->containing_type()->full_name(),
5229                                    field->number()));
5230     }
5231   }
5232 
5233   if (field->containing_oneof() != NULL) {
5234     if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
5235       // Note that this error will never happen when parsing .proto files.
5236       // It can only happen if you manually construct a FileDescriptorProto
5237       // that is incorrect.
5238       AddError(field->full_name(), proto,
5239                DescriptorPool::ErrorCollector::NAME,
5240                "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
5241     }
5242   }
5243 
5244   if (proto.has_type_name()) {
5245     // Assume we are expecting a message type unless the proto contains some
5246     // evidence that it expects an enum type.  This only makes a difference if
5247     // we end up creating a placeholder.
5248     bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
5249                           proto.has_default_value();
5250 
5251     Symbol type =
5252         LookupSymbol(proto.type_name(), field->full_name(),
5253                      expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
5254                                     : DescriptorPool::PLACEHOLDER_MESSAGE,
5255                      LOOKUP_TYPES, !pool_->lazily_build_dependencies_);
5256 
5257     // If the type is a weak type, we change the type to a google.protobuf.Empty field.
5258     if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) {
5259       type = FindSymbol(kNonLinkedWeakMessageReplacementName);
5260     }
5261 
5262     if (type.IsNull()) {
5263       if (pool_->lazily_build_dependencies_) {
5264         // Save the symbol names for later for lookup, and allocate the once
5265         // object needed for the accessors.
5266         string name = proto.type_name();
5267         if (!pool_->enforce_weak_ && proto.options().weak()) {
5268           name = kNonLinkedWeakMessageReplacementName;
5269         }
5270         field->type_once_ = tables_->AllocateOnceDynamic();
5271         field->type_name_ = tables_->AllocateString(name);
5272         if (proto.has_default_value()) {
5273           field->default_value_enum_name_ =
5274               tables_->AllocateString(proto.default_value());
5275         }
5276         // AddFieldByNumber and AddExtension are done later in this function,
5277         // and can/must be done if the field type was not found. The related
5278         // error checking is not necessary when in lazily_build_dependencies_
5279         // mode, and can't be done without building the type's descriptor,
5280         // which we don't want to do.
5281         file_tables_->AddFieldByNumber(field);
5282         if (field->is_extension()) {
5283           tables_->AddExtension(field);
5284         }
5285         return;
5286       } else {
5287         AddNotDefinedError(field->full_name(), proto,
5288                            DescriptorPool::ErrorCollector::TYPE,
5289                            proto.type_name());
5290         return;
5291       }
5292     }
5293 
5294     if (!proto.has_type()) {
5295       // Choose field type based on symbol.
5296       if (type.type == Symbol::MESSAGE) {
5297         field->type_ = FieldDescriptor::TYPE_MESSAGE;
5298       } else if (type.type == Symbol::ENUM) {
5299         field->type_ = FieldDescriptor::TYPE_ENUM;
5300       } else {
5301         AddError(field->full_name(), proto,
5302                  DescriptorPool::ErrorCollector::TYPE,
5303                  "\"" + proto.type_name() + "\" is not a type.");
5304         return;
5305       }
5306     }
5307 
5308     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
5309       if (type.type != Symbol::MESSAGE) {
5310         AddError(field->full_name(), proto,
5311                  DescriptorPool::ErrorCollector::TYPE,
5312                  "\"" + proto.type_name() + "\" is not a message type.");
5313         return;
5314       }
5315       field->message_type_ = type.descriptor;
5316 
5317       if (field->has_default_value()) {
5318         AddError(field->full_name(), proto,
5319                  DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5320                  "Messages can't have default values.");
5321       }
5322     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5323       if (type.type != Symbol::ENUM) {
5324         AddError(field->full_name(), proto,
5325                  DescriptorPool::ErrorCollector::TYPE,
5326                  "\"" + proto.type_name() + "\" is not an enum type.");
5327         return;
5328       }
5329       field->enum_type_ = type.enum_descriptor;
5330 
5331       if (field->enum_type()->is_placeholder_) {
5332         // We can't look up default values for placeholder types.  We'll have
5333         // to just drop them.
5334         field->has_default_value_ = false;
5335       }
5336 
5337       if (field->has_default_value()) {
5338         // Ensure that the default value is an identifier. Parser cannot always
5339         // verify this because it does not have complete type information.
5340         // N.B. that this check yields better error messages but is not
5341         // necessary for correctness (an enum symbol must be a valid identifier
5342         // anyway), only for better errors.
5343         if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
5344           AddError(field->full_name(), proto,
5345                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5346                    "Default value for an enum field must be an identifier.");
5347         } else {
5348           // We can't just use field->enum_type()->FindValueByName() here
5349           // because that locks the pool's mutex, which we have already locked
5350           // at this point.
5351           Symbol default_value =
5352             LookupSymbolNoPlaceholder(proto.default_value(),
5353                                       field->enum_type()->full_name());
5354 
5355           if (default_value.type == Symbol::ENUM_VALUE &&
5356               default_value.enum_value_descriptor->type() ==
5357               field->enum_type()) {
5358             field->default_value_enum_ = default_value.enum_value_descriptor;
5359           } else {
5360             AddError(field->full_name(), proto,
5361                      DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5362                      "Enum type \"" + field->enum_type()->full_name() +
5363                      "\" has no value named \"" + proto.default_value() +
5364                      "\".");
5365           }
5366         }
5367       } else if (field->enum_type()->value_count() > 0) {
5368         // All enums must have at least one value, or we would have reported
5369         // an error elsewhere.  We use the first defined value as the default
5370         // if a default is not explicitly defined.
5371         field->default_value_enum_ = field->enum_type()->value(0);
5372       }
5373     } else {
5374       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5375                "Field with primitive type has type_name.");
5376     }
5377   } else {
5378     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
5379         field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5380       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5381                "Field with message or enum type missing type_name.");
5382     }
5383   }
5384 
5385   // Add the field to the fields-by-number table.
5386   // Note:  We have to do this *after* cross-linking because extensions do not
5387   // know their containing type until now. If we're in
5388   // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
5389   // risk to calling containing_type() or other accessors that will build
5390   // dependencies.
5391   if (!file_tables_->AddFieldByNumber(field)) {
5392     const FieldDescriptor* conflicting_field =
5393       file_tables_->FindFieldByNumber(field->containing_type(),
5394                                       field->number());
5395     string containing_type_name = field->containing_type() == NULL
5396                                       ? "unknown"
5397                                       : field->containing_type()->full_name();
5398     if (field->is_extension()) {
5399       AddError(field->full_name(), proto,
5400                DescriptorPool::ErrorCollector::NUMBER,
5401                strings::Substitute("Extension number $0 has already been used "
5402                                    "in \"$1\" by extension \"$2\".",
5403                                    field->number(),
5404                                    containing_type_name,
5405                                    conflicting_field->full_name()));
5406     } else {
5407       AddError(field->full_name(), proto,
5408                DescriptorPool::ErrorCollector::NUMBER,
5409                strings::Substitute("Field number $0 has already been used in "
5410                                    "\"$1\" by field \"$2\".",
5411                                    field->number(),
5412                                    containing_type_name,
5413                                    conflicting_field->name()));
5414     }
5415   } else {
5416     if (field->is_extension()) {
5417       if (!tables_->AddExtension(field)) {
5418         const FieldDescriptor* conflicting_field =
5419             tables_->FindExtension(field->containing_type(), field->number());
5420         string error_msg = strings::Substitute(
5421             "Extension number $0 has already been used in \"$1\" by extension "
5422             "\"$2\" defined in $3.",
5423             field->number(),
5424             field->containing_type()->full_name(),
5425             conflicting_field->full_name(),
5426             conflicting_field->file()->name());
5427         // Conflicting extension numbers should be an error. However, before
5428         // turning this into an error we need to fix all existing broken
5429         // protos first.
5430         // TODO(xiaofeng): Change this to an error.
5431         AddWarning(field->full_name(), proto,
5432                    DescriptorPool::ErrorCollector::NUMBER, error_msg);
5433       }
5434     }
5435   }
5436 }
5437 
CrossLinkEnum(EnumDescriptor * enum_type,const EnumDescriptorProto & proto)5438 void DescriptorBuilder::CrossLinkEnum(
5439     EnumDescriptor* enum_type, const EnumDescriptorProto& proto) {
5440   if (enum_type->options_ == NULL) {
5441     enum_type->options_ = &EnumOptions::default_instance();
5442   }
5443 
5444   for (int i = 0; i < enum_type->value_count(); i++) {
5445     CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
5446   }
5447 }
5448 
CrossLinkEnumValue(EnumValueDescriptor * enum_value,const EnumValueDescriptorProto &)5449 void DescriptorBuilder::CrossLinkEnumValue(
5450     EnumValueDescriptor* enum_value,
5451     const EnumValueDescriptorProto& /* proto */) {
5452   if (enum_value->options_ == NULL) {
5453     enum_value->options_ = &EnumValueOptions::default_instance();
5454   }
5455 }
5456 
CrossLinkService(ServiceDescriptor * service,const ServiceDescriptorProto & proto)5457 void DescriptorBuilder::CrossLinkService(
5458     ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
5459   if (service->options_ == NULL) {
5460     service->options_ = &ServiceOptions::default_instance();
5461   }
5462 
5463   for (int i = 0; i < service->method_count(); i++) {
5464     CrossLinkMethod(&service->methods_[i], proto.method(i));
5465   }
5466 }
5467 
CrossLinkMethod(MethodDescriptor * method,const MethodDescriptorProto & proto)5468 void DescriptorBuilder::CrossLinkMethod(
5469     MethodDescriptor* method, const MethodDescriptorProto& proto) {
5470   if (method->options_ == NULL) {
5471     method->options_ = &MethodOptions::default_instance();
5472   }
5473 
5474   Symbol input_type =
5475       LookupSymbol(proto.input_type(), method->full_name(),
5476                    DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5477                    !pool_->lazily_build_dependencies_);
5478   if (input_type.IsNull()) {
5479     if (!pool_->lazily_build_dependencies_) {
5480       AddNotDefinedError(method->full_name(), proto,
5481                          DescriptorPool::ErrorCollector::INPUT_TYPE,
5482                          proto.input_type());
5483     } else {
5484       method->input_type_.SetLazy(proto.input_type(), file_);
5485     }
5486   } else if (input_type.type != Symbol::MESSAGE) {
5487     AddError(method->full_name(), proto,
5488              DescriptorPool::ErrorCollector::INPUT_TYPE,
5489              "\"" + proto.input_type() + "\" is not a message type.");
5490   } else {
5491     method->input_type_.Set(input_type.descriptor);
5492   }
5493 
5494   Symbol output_type =
5495       LookupSymbol(proto.output_type(), method->full_name(),
5496                    DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5497                    !pool_->lazily_build_dependencies_);
5498   if (output_type.IsNull()) {
5499     if (!pool_->lazily_build_dependencies_) {
5500       AddNotDefinedError(method->full_name(), proto,
5501                          DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5502                          proto.output_type());
5503     } else {
5504       method->output_type_.SetLazy(proto.output_type(), file_);
5505     }
5506   } else if (output_type.type != Symbol::MESSAGE) {
5507     AddError(method->full_name(), proto,
5508              DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5509              "\"" + proto.output_type() + "\" is not a message type.");
5510   } else {
5511     method->output_type_.Set(output_type.descriptor);
5512   }
5513 }
5514 
5515 // -------------------------------------------------------------------
5516 
5517 #define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type)  \
5518   for (int i = 0; i < descriptor->array_name##_count(); ++i) {     \
5519     Validate##type##Options(descriptor->array_name##s_ + i,        \
5520                             proto.array_name(i));                  \
5521   }
5522 
5523 // Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
5524 // avoid problems that exist at init time.
IsLite(const FileDescriptor * file)5525 static bool IsLite(const FileDescriptor* file) {
5526   // TODO(kenton):  I don't even remember how many of these conditions are
5527   //   actually possible.  I'm just being super-safe.
5528   return file != NULL &&
5529          &file->options() != &FileOptions::default_instance() &&
5530          file->options().optimize_for() == FileOptions::LITE_RUNTIME;
5531 }
5532 
ValidateFileOptions(FileDescriptor * file,const FileDescriptorProto & proto)5533 void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
5534                                             const FileDescriptorProto& proto) {
5535   VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
5536   VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
5537   VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
5538   VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
5539 
5540   // Lite files can only be imported by other Lite files.
5541   if (!IsLite(file)) {
5542     for (int i = 0; i < file->dependency_count(); i++) {
5543       if (IsLite(file->dependency(i))) {
5544         AddError(
5545           file->name(), proto,
5546           DescriptorPool::ErrorCollector::OTHER,
5547           "Files that do not use optimize_for = LITE_RUNTIME cannot import "
5548           "files which do use this option.  This file is not lite, but it "
5549           "imports \"" + file->dependency(i)->name() + "\" which is.");
5550         break;
5551       }
5552     }
5553   }
5554   if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
5555     ValidateProto3(file, proto);
5556   }
5557 }
5558 
ValidateProto3(FileDescriptor * file,const FileDescriptorProto & proto)5559 void DescriptorBuilder::ValidateProto3(
5560     FileDescriptor* file, const FileDescriptorProto& proto) {
5561   for (int i = 0; i < file->extension_count(); ++i) {
5562     ValidateProto3Field(file->extensions_ + i, proto.extension(i));
5563   }
5564   for (int i = 0; i < file->message_type_count(); ++i) {
5565     ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
5566   }
5567   for (int i = 0; i < file->enum_type_count(); ++i) {
5568     ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
5569   }
5570 }
5571 
ToLowercaseWithoutUnderscores(const string & name)5572 static string ToLowercaseWithoutUnderscores(const string& name) {
5573   string result;
5574   for (int i = 0; i < name.size(); ++i) {
5575     if (name[i] != '_') {
5576       if (name[i] >= 'A' && name[i] <= 'Z') {
5577         result.push_back(name[i] - 'A' + 'a');
5578       } else {
5579         result.push_back(name[i]);
5580       }
5581     }
5582   }
5583   return result;
5584 }
5585 
ValidateProto3Message(Descriptor * message,const DescriptorProto & proto)5586 void DescriptorBuilder::ValidateProto3Message(
5587     Descriptor* message, const DescriptorProto& proto) {
5588   for (int i = 0; i < message->nested_type_count(); ++i) {
5589     ValidateProto3Message(message->nested_types_ + i,
5590                                  proto.nested_type(i));
5591   }
5592   for (int i = 0; i < message->enum_type_count(); ++i) {
5593     ValidateProto3Enum(message->enum_types_ + i,
5594                               proto.enum_type(i));
5595   }
5596   for (int i = 0; i < message->field_count(); ++i) {
5597     ValidateProto3Field(message->fields_ + i, proto.field(i));
5598   }
5599   for (int i = 0; i < message->extension_count(); ++i) {
5600     ValidateProto3Field(message->extensions_ +i, proto.extension(i));
5601   }
5602   if (message->extension_range_count() > 0) {
5603     AddError(message->full_name(), proto,
5604              DescriptorPool::ErrorCollector::OTHER,
5605              "Extension ranges are not allowed in proto3.");
5606   }
5607   if (message->options().message_set_wire_format()) {
5608     // Using MessageSet doesn't make sense since we disallow extensions.
5609     AddError(message->full_name(), proto,
5610              DescriptorPool::ErrorCollector::OTHER,
5611              "MessageSet is not supported in proto3.");
5612   }
5613 
5614   // In proto3, we reject field names if they conflict in camelCase.
5615   // Note that we currently enforce a stricter rule: Field names must be
5616   // unique after being converted to lowercase with underscores removed.
5617   std::map<string, const FieldDescriptor*> name_to_field;
5618   for (int i = 0; i < message->field_count(); ++i) {
5619     string lowercase_name = ToLowercaseWithoutUnderscores(
5620         message->field(i)->name());
5621     if (name_to_field.find(lowercase_name) != name_to_field.end()) {
5622       AddError(message->full_name(), proto,
5623                DescriptorPool::ErrorCollector::OTHER,
5624                "The JSON camel-case name of field \"" +
5625                message->field(i)->name() + "\" conflicts with field \"" +
5626                name_to_field[lowercase_name]->name() + "\". This is not " +
5627                "allowed in proto3.");
5628     } else {
5629       name_to_field[lowercase_name] = message->field(i);
5630     }
5631   }
5632 }
5633 
ValidateProto3Field(FieldDescriptor * field,const FieldDescriptorProto & proto)5634 void DescriptorBuilder::ValidateProto3Field(
5635     FieldDescriptor* field, const FieldDescriptorProto& proto) {
5636   if (field->is_extension() &&
5637       !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
5638     AddError(field->full_name(), proto,
5639              DescriptorPool::ErrorCollector::OTHER,
5640              "Extensions in proto3 are only allowed for defining options.");
5641   }
5642   if (field->is_required()) {
5643     AddError(field->full_name(), proto,
5644              DescriptorPool::ErrorCollector::OTHER,
5645              "Required fields are not allowed in proto3.");
5646   }
5647   if (field->has_default_value()) {
5648     AddError(
5649         field->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
5650         "Explicit default values are not allowed in proto3.");
5651   }
5652   if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
5653       field->enum_type() &&
5654       field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3) {
5655     // Proto3 messages can only use Proto3 enum types; otherwise we can't
5656     // guarantee that the default value is zero.
5657     AddError(field->full_name(), proto,
5658              DescriptorPool::ErrorCollector::TYPE,
5659              "Enum type \"" + field->enum_type()->full_name() +
5660              "\" is not a proto3 enum, but is used in \"" +
5661              field->containing_type()->full_name() +
5662              "\" which is a proto3 message type.");
5663   }
5664   if (field->type() == FieldDescriptor::TYPE_GROUP) {
5665     AddError(field->full_name(), proto,
5666              DescriptorPool::ErrorCollector::TYPE,
5667              "Groups are not supported in proto3 syntax.");
5668   }
5669 }
5670 
ValidateProto3Enum(EnumDescriptor * enm,const EnumDescriptorProto & proto)5671 void DescriptorBuilder::ValidateProto3Enum(
5672     EnumDescriptor* enm, const EnumDescriptorProto& proto) {
5673   if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
5674     AddError(
5675         enm->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
5676         "The first enum value must be zero in proto3.");
5677   }
5678 }
5679 
ValidateMessageOptions(Descriptor * message,const DescriptorProto & proto)5680 void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
5681                                                const DescriptorProto& proto) {
5682   VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
5683   VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
5684   VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
5685   VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
5686 
5687   const int64 max_extension_range =
5688       static_cast<int64>(message->options().message_set_wire_format() ?
5689                          kint32max :
5690                          FieldDescriptor::kMaxNumber);
5691   for (int i = 0; i < message->extension_range_count(); ++i) {
5692     if (message->extension_range(i)->end > max_extension_range + 1) {
5693       AddError(
5694           message->full_name(), proto.extension_range(i),
5695           DescriptorPool::ErrorCollector::NUMBER,
5696           strings::Substitute("Extension numbers cannot be greater than $0.",
5697                               max_extension_range));
5698     }
5699   }
5700 }
5701 
5702 
ValidateFieldOptions(FieldDescriptor * field,const FieldDescriptorProto & proto)5703 void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
5704     const FieldDescriptorProto& proto) {
5705   if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
5706     return;
5707   }
5708   // Only message type fields may be lazy.
5709   if (field->options().lazy()) {
5710     if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
5711       AddError(field->full_name(), proto,
5712                DescriptorPool::ErrorCollector::TYPE,
5713                "[lazy = true] can only be specified for submessage fields.");
5714     }
5715   }
5716 
5717   // Only repeated primitive fields may be packed.
5718   if (field->options().packed() && !field->is_packable()) {
5719     AddError(
5720       field->full_name(), proto,
5721       DescriptorPool::ErrorCollector::TYPE,
5722       "[packed = true] can only be specified for repeated primitive fields.");
5723   }
5724 
5725   // Note:  Default instance may not yet be initialized here, so we have to
5726   //   avoid reading from it.
5727   if (field->containing_type_ != NULL &&
5728       &field->containing_type()->options() !=
5729       &MessageOptions::default_instance() &&
5730       field->containing_type()->options().message_set_wire_format()) {
5731     if (field->is_extension()) {
5732       if (!field->is_optional() ||
5733           field->type() != FieldDescriptor::TYPE_MESSAGE) {
5734         AddError(field->full_name(), proto,
5735                  DescriptorPool::ErrorCollector::TYPE,
5736                  "Extensions of MessageSets must be optional messages.");
5737       }
5738     } else {
5739       AddError(field->full_name(), proto,
5740                DescriptorPool::ErrorCollector::NAME,
5741                "MessageSets cannot have fields, only extensions.");
5742     }
5743   }
5744 
5745   // Lite extensions can only be of Lite types.
5746   if (IsLite(field->file()) &&
5747       field->containing_type_ != NULL &&
5748       !IsLite(field->containing_type()->file())) {
5749     AddError(field->full_name(), proto,
5750              DescriptorPool::ErrorCollector::EXTENDEE,
5751              "Extensions to non-lite types can only be declared in non-lite "
5752              "files.  Note that you cannot extend a non-lite type to contain "
5753              "a lite type, but the reverse is allowed.");
5754   }
5755 
5756   // Validate map types.
5757   if (field->is_map()) {
5758     if (!ValidateMapEntry(field, proto)) {
5759       AddError(field->full_name(), proto,
5760                DescriptorPool::ErrorCollector::OTHER,
5761                "map_entry should not be set explicitly. Use map<KeyType, "
5762                "ValueType> instead.");
5763     }
5764   }
5765 
5766   ValidateJSType(field, proto);
5767 
5768 }
5769 
ValidateEnumOptions(EnumDescriptor * enm,const EnumDescriptorProto & proto)5770 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
5771                                             const EnumDescriptorProto& proto) {
5772   VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
5773   if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
5774     std::map<int, string> used_values;
5775     for (int i = 0; i < enm->value_count(); ++i) {
5776       const EnumValueDescriptor* enum_value = enm->value(i);
5777       if (used_values.find(enum_value->number()) != used_values.end()) {
5778         string error =
5779             "\"" + enum_value->full_name() +
5780             "\" uses the same enum value as \"" +
5781             used_values[enum_value->number()] + "\". If this is intended, set "
5782             "'option allow_alias = true;' to the enum definition.";
5783         if (!enm->options().allow_alias()) {
5784           // Generate error if duplicated enum values are explicitly disallowed.
5785           AddError(enm->full_name(), proto,
5786                    DescriptorPool::ErrorCollector::NUMBER,
5787                    error);
5788         } else {
5789           // Generate warning if duplicated values are found but the option
5790           // isn't set.
5791           GOOGLE_LOG(ERROR) << error;
5792         }
5793       } else {
5794         used_values[enum_value->number()] = enum_value->full_name();
5795       }
5796     }
5797   }
5798 }
5799 
ValidateEnumValueOptions(EnumValueDescriptor *,const EnumValueDescriptorProto &)5800 void DescriptorBuilder::ValidateEnumValueOptions(
5801     EnumValueDescriptor* /* enum_value */,
5802     const EnumValueDescriptorProto& /* proto */) {
5803   // Nothing to do so far.
5804 }
ValidateServiceOptions(ServiceDescriptor * service,const ServiceDescriptorProto & proto)5805 void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
5806     const ServiceDescriptorProto& proto) {
5807   if (IsLite(service->file()) &&
5808       (service->file()->options().cc_generic_services() ||
5809        service->file()->options().java_generic_services())) {
5810     AddError(service->full_name(), proto,
5811              DescriptorPool::ErrorCollector::NAME,
5812              "Files with optimize_for = LITE_RUNTIME cannot define services "
5813              "unless you set both options cc_generic_services and "
5814              "java_generic_sevices to false.");
5815   }
5816 
5817   VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
5818 }
5819 
ValidateMethodOptions(MethodDescriptor *,const MethodDescriptorProto &)5820 void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */,
5821     const MethodDescriptorProto& /* proto */) {
5822   // Nothing to do so far.
5823 }
5824 
ValidateMapEntry(FieldDescriptor * field,const FieldDescriptorProto & proto)5825 bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
5826                                          const FieldDescriptorProto& proto) {
5827   const Descriptor* message = field->message_type();
5828   if (// Must not contain extensions, extension range or nested message or
5829       // enums
5830       message->extension_count() != 0 ||
5831       field->label() != FieldDescriptor::LABEL_REPEATED ||
5832       message->extension_range_count() != 0 ||
5833       message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
5834       // Must contain exactly two fields
5835       message->field_count() != 2 ||
5836       // Field name and message name must match
5837       message->name() != ToCamelCase(field->name(), false) + "Entry" ||
5838       // Entry message must be in the same containing type of the field.
5839       field->containing_type() != message->containing_type()) {
5840     return false;
5841   }
5842 
5843   const FieldDescriptor* key = message->field(0);
5844   const FieldDescriptor* value = message->field(1);
5845   if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
5846       key->name() != "key") {
5847     return false;
5848   }
5849   if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
5850       value->number() != 2 || value->name() != "value") {
5851     return false;
5852   }
5853 
5854   // Check key types are legal.
5855   switch (key->type()) {
5856     case FieldDescriptor::TYPE_ENUM:
5857       AddError(
5858           field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5859           "Key in map fields cannot be enum types.");
5860       break;
5861     case FieldDescriptor::TYPE_FLOAT:
5862     case FieldDescriptor::TYPE_DOUBLE:
5863     case FieldDescriptor::TYPE_MESSAGE:
5864     case FieldDescriptor::TYPE_GROUP:
5865     case FieldDescriptor::TYPE_BYTES:
5866       AddError(
5867           field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5868           "Key in map fields cannot be float/double, bytes or message types.");
5869       break;
5870     case FieldDescriptor::TYPE_BOOL:
5871     case FieldDescriptor::TYPE_INT32:
5872     case FieldDescriptor::TYPE_INT64:
5873     case FieldDescriptor::TYPE_SINT32:
5874     case FieldDescriptor::TYPE_SINT64:
5875     case FieldDescriptor::TYPE_STRING:
5876     case FieldDescriptor::TYPE_UINT32:
5877     case FieldDescriptor::TYPE_UINT64:
5878     case FieldDescriptor::TYPE_FIXED32:
5879     case FieldDescriptor::TYPE_FIXED64:
5880     case FieldDescriptor::TYPE_SFIXED32:
5881     case FieldDescriptor::TYPE_SFIXED64:
5882       // Legal cases
5883       break;
5884     // Do not add a default, so that the compiler will complain when new types
5885     // are added.
5886   }
5887 
5888   if (value->type() == FieldDescriptor::TYPE_ENUM) {
5889     if (value->enum_type()->value(0)->number() != 0) {
5890       AddError(
5891           field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5892           "Enum value in map must define 0 as the first value.");
5893     }
5894   }
5895 
5896   return true;
5897 }
5898 
DetectMapConflicts(const Descriptor * message,const DescriptorProto & proto)5899 void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
5900                                            const DescriptorProto& proto) {
5901   std::map<string, const Descriptor*> seen_types;
5902   for (int i = 0; i < message->nested_type_count(); ++i) {
5903     const Descriptor* nested = message->nested_type(i);
5904     std::pair<std::map<string, const Descriptor*>::iterator, bool> result =
5905         seen_types.insert(std::make_pair(nested->name(), nested));
5906     if (!result.second) {
5907       if (result.first->second->options().map_entry() ||
5908           nested->options().map_entry()) {
5909         AddError(message->full_name(), proto,
5910                  DescriptorPool::ErrorCollector::NAME,
5911                  "Expanded map entry type " + nested->name() +
5912                  " conflicts with an existing nested message type.");
5913       }
5914     }
5915     // Recursively test on the nested types.
5916     DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
5917   }
5918   // Check for conflicted field names.
5919   for (int i = 0; i < message->field_count(); ++i) {
5920     const FieldDescriptor* field = message->field(i);
5921     std::map<string, const Descriptor*>::iterator iter =
5922         seen_types.find(field->name());
5923     if (iter != seen_types.end() && iter->second->options().map_entry()) {
5924       AddError(message->full_name(), proto,
5925                DescriptorPool::ErrorCollector::NAME,
5926                "Expanded map entry type " + iter->second->name() +
5927                " conflicts with an existing field.");
5928     }
5929   }
5930   // Check for conflicted enum names.
5931   for (int i = 0; i < message->enum_type_count(); ++i) {
5932     const EnumDescriptor* enum_desc = message->enum_type(i);
5933     std::map<string, const Descriptor*>::iterator iter =
5934         seen_types.find(enum_desc->name());
5935     if (iter != seen_types.end() && iter->second->options().map_entry()) {
5936       AddError(message->full_name(), proto,
5937                DescriptorPool::ErrorCollector::NAME,
5938                "Expanded map entry type " + iter->second->name() +
5939                " conflicts with an existing enum type.");
5940     }
5941   }
5942   // Check for conflicted oneof names.
5943   for (int i = 0; i < message->oneof_decl_count(); ++i) {
5944     const OneofDescriptor* oneof_desc = message->oneof_decl(i);
5945     std::map<string, const Descriptor*>::iterator iter =
5946         seen_types.find(oneof_desc->name());
5947     if (iter != seen_types.end() && iter->second->options().map_entry()) {
5948       AddError(message->full_name(), proto,
5949                DescriptorPool::ErrorCollector::NAME,
5950                "Expanded map entry type " + iter->second->name() +
5951                " conflicts with an existing oneof type.");
5952     }
5953   }
5954 }
5955 
ValidateJSType(FieldDescriptor * field,const FieldDescriptorProto & proto)5956 void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
5957                                        const FieldDescriptorProto& proto) {
5958   FieldOptions::JSType jstype = field->options().jstype();
5959   // The default is always acceptable.
5960   if (jstype == FieldOptions::JS_NORMAL) {
5961     return;
5962   }
5963 
5964   switch (field->type()) {
5965     // Integral 64-bit types may be represented as JavaScript numbers or
5966     // strings.
5967     case FieldDescriptor::TYPE_UINT64:
5968     case FieldDescriptor::TYPE_INT64:
5969     case FieldDescriptor::TYPE_SINT64:
5970     case FieldDescriptor::TYPE_FIXED64:
5971     case FieldDescriptor::TYPE_SFIXED64:
5972       if (jstype == FieldOptions::JS_STRING ||
5973           jstype == FieldOptions::JS_NUMBER) {
5974         return;
5975       }
5976       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5977                "Illegal jstype for int64, uint64, sint64, fixed64 "
5978                "or sfixed64 field: " +
5979                FieldOptions_JSType_descriptor()->value(jstype)->name());
5980       break;
5981 
5982     // No other types permit a jstype option.
5983     default:
5984       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5985                "jstype is only allowed on int64, uint64, sint64, fixed64 "
5986                "or sfixed64 fields.");
5987       break;
5988   }
5989 }
5990 
5991 #undef VALIDATE_OPTIONS_FROM_ARRAY
5992 
5993 // -------------------------------------------------------------------
5994 
OptionInterpreter(DescriptorBuilder * builder)5995 DescriptorBuilder::OptionInterpreter::OptionInterpreter(
5996     DescriptorBuilder* builder) : builder_(builder) {
5997   GOOGLE_CHECK(builder_);
5998 }
5999 
~OptionInterpreter()6000 DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {
6001 }
6002 
InterpretOptions(OptionsToInterpret * options_to_interpret)6003 bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
6004     OptionsToInterpret* options_to_interpret) {
6005   // Note that these may be in different pools, so we can't use the same
6006   // descriptor and reflection objects on both.
6007   Message* options = options_to_interpret->options;
6008   const Message* original_options = options_to_interpret->original_options;
6009 
6010   bool failed = false;
6011   options_to_interpret_ = options_to_interpret;
6012 
6013   // Find the uninterpreted_option field in the mutable copy of the options
6014   // and clear them, since we're about to interpret them.
6015   const FieldDescriptor* uninterpreted_options_field =
6016       options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6017   GOOGLE_CHECK(uninterpreted_options_field != NULL)
6018       << "No field named \"uninterpreted_option\" in the Options proto.";
6019   options->GetReflection()->ClearField(options, uninterpreted_options_field);
6020 
6021   // Find the uninterpreted_option field in the original options.
6022   const FieldDescriptor* original_uninterpreted_options_field =
6023       original_options->GetDescriptor()->
6024           FindFieldByName("uninterpreted_option");
6025   GOOGLE_CHECK(original_uninterpreted_options_field != NULL)
6026       << "No field named \"uninterpreted_option\" in the Options proto.";
6027 
6028   const int num_uninterpreted_options = original_options->GetReflection()->
6029       FieldSize(*original_options, original_uninterpreted_options_field);
6030   for (int i = 0; i < num_uninterpreted_options; ++i) {
6031     uninterpreted_option_ = down_cast<const UninterpretedOption*>(
6032         &original_options->GetReflection()->GetRepeatedMessage(
6033             *original_options, original_uninterpreted_options_field, i));
6034     if (!InterpretSingleOption(options)) {
6035       // Error already added by InterpretSingleOption().
6036       failed = true;
6037       break;
6038     }
6039   }
6040   // Reset these, so we don't have any dangling pointers.
6041   uninterpreted_option_ = NULL;
6042   options_to_interpret_ = NULL;
6043 
6044   if (!failed) {
6045     // InterpretSingleOption() added the interpreted options in the
6046     // UnknownFieldSet, in case the option isn't yet known to us.  Now we
6047     // serialize the options message and deserialize it back.  That way, any
6048     // option fields that we do happen to know about will get moved from the
6049     // UnknownFieldSet into the real fields, and thus be available right away.
6050     // If they are not known, that's OK too. They will get reparsed into the
6051     // UnknownFieldSet and wait there until the message is parsed by something
6052     // that does know about the options.
6053     string buf;
6054     GOOGLE_CHECK(options->AppendPartialToString(&buf))
6055         << "Protocol message could not be serialized.";
6056     GOOGLE_CHECK(options->ParsePartialFromString(buf))
6057         << "Protocol message serialized itself in invalid fashion.";
6058     if (!options->IsInitialized()) {
6059       builder_->AddWarning(
6060           options_to_interpret->element_name, *original_options,
6061           DescriptorPool::ErrorCollector::OTHER,
6062           "Options could not be fully parsed using the proto descriptors "
6063           "compiled into this binary. Missing required fields: " +
6064           options->InitializationErrorString());
6065     }
6066   }
6067   return !failed;
6068 }
6069 
InterpretSingleOption(Message * options)6070 bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
6071     Message* options) {
6072   // First do some basic validation.
6073   if (uninterpreted_option_->name_size() == 0) {
6074     // This should never happen unless the parser has gone seriously awry or
6075     // someone has manually created the uninterpreted option badly.
6076     return AddNameError("Option must have a name.");
6077   }
6078   if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
6079     return AddNameError("Option must not use reserved name "
6080                         "\"uninterpreted_option\".");
6081   }
6082 
6083   const Descriptor* options_descriptor = NULL;
6084   // Get the options message's descriptor from the builder's pool, so that we
6085   // get the version that knows about any extension options declared in the
6086   // file we're currently building. The descriptor should be there as long as
6087   // the file we're building imported "google/protobuf/descriptors.proto".
6088 
6089   // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
6090   // DescriptorPool::FindMessageTypeByName() because we're already holding the
6091   // pool's mutex, and the latter method locks it again.  We don't use
6092   // FindSymbol() because files that use custom options only need to depend on
6093   // the file that defines the option, not descriptor.proto itself.
6094   Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
6095     options->GetDescriptor()->full_name());
6096   if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
6097     options_descriptor = symbol.descriptor;
6098   } else {
6099     // The options message's descriptor was not in the builder's pool, so use
6100     // the standard version from the generated pool. We're not holding the
6101     // generated pool's mutex, so we can search it the straightforward way.
6102     options_descriptor = options->GetDescriptor();
6103   }
6104   GOOGLE_CHECK(options_descriptor);
6105 
6106   // We iterate over the name parts to drill into the submessages until we find
6107   // the leaf field for the option. As we drill down we remember the current
6108   // submessage's descriptor in |descriptor| and the next field in that
6109   // submessage in |field|. We also track the fields we're drilling down
6110   // through in |intermediate_fields|. As we go, we reconstruct the full option
6111   // name in |debug_msg_name|, for use in error messages.
6112   const Descriptor* descriptor = options_descriptor;
6113   const FieldDescriptor* field = NULL;
6114   std::vector<const FieldDescriptor*> intermediate_fields;
6115   string debug_msg_name = "";
6116 
6117   for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
6118     const string& name_part = uninterpreted_option_->name(i).name_part();
6119     if (debug_msg_name.size() > 0) {
6120       debug_msg_name += ".";
6121     }
6122     if (uninterpreted_option_->name(i).is_extension()) {
6123       debug_msg_name += "(" + name_part + ")";
6124       // Search for the extension's descriptor as an extension in the builder's
6125       // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
6126       // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
6127       // relative lookups, and 2) because we're already holding the pool's
6128       // mutex, and the latter method locks it again.
6129       symbol = builder_->LookupSymbol(name_part,
6130                                       options_to_interpret_->name_scope);
6131       if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
6132         field = symbol.field_descriptor;
6133       }
6134       // If we don't find the field then the field's descriptor was not in the
6135       // builder's pool, but there's no point in looking in the generated
6136       // pool. We require that you import the file that defines any extensions
6137       // you use, so they must be present in the builder's pool.
6138     } else {
6139       debug_msg_name += name_part;
6140       // Search for the field's descriptor as a regular field.
6141       field = descriptor->FindFieldByName(name_part);
6142     }
6143 
6144     if (field == NULL) {
6145       if (get_allow_unknown(builder_->pool_)) {
6146         // We can't find the option, but AllowUnknownDependencies() is enabled,
6147         // so we will just leave it as uninterpreted.
6148         AddWithoutInterpreting(*uninterpreted_option_, options);
6149         return true;
6150       } else if (!(builder_->undefine_resolved_name_).empty()) {
6151         // Option is resolved to a name which is not defined.
6152         return AddNameError(
6153             "Option \"" + debug_msg_name + "\" is resolved to \"(" +
6154             builder_->undefine_resolved_name_ +
6155             ")\", which is not defined. The innermost scope is searched first "
6156             "in name resolution. Consider using a leading '.'(i.e., \"(." +
6157             debug_msg_name.substr(1) +
6158             "\") to start from the outermost scope.");
6159       } else {
6160         return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
6161       }
6162     } else if (field->containing_type() != descriptor) {
6163       if (get_is_placeholder(field->containing_type())) {
6164         // The field is an extension of a placeholder type, so we can't
6165         // reliably verify whether it is a valid extension to use here (e.g.
6166         // we don't know if it is an extension of the correct *Options message,
6167         // or if it has a valid field number, etc.).  Just leave it as
6168         // uninterpreted instead.
6169         AddWithoutInterpreting(*uninterpreted_option_, options);
6170         return true;
6171       } else {
6172         // This can only happen if, due to some insane misconfiguration of the
6173         // pools, we find the options message in one pool but the field in
6174         // another. This would probably imply a hefty bug somewhere.
6175         return AddNameError("Option field \"" + debug_msg_name +
6176                             "\" is not a field or extension of message \"" +
6177                             descriptor->name() + "\".");
6178       }
6179     } else if (i < uninterpreted_option_->name_size() - 1) {
6180       if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
6181         return AddNameError("Option \"" +  debug_msg_name +
6182                             "\" is an atomic type, not a message.");
6183       } else if (field->is_repeated()) {
6184         return AddNameError("Option field \"" + debug_msg_name +
6185                             "\" is a repeated message. Repeated message "
6186                             "options must be initialized using an "
6187                             "aggregate value.");
6188       } else {
6189         // Drill down into the submessage.
6190         intermediate_fields.push_back(field);
6191         descriptor = field->message_type();
6192       }
6193     }
6194   }
6195 
6196   // We've found the leaf field. Now we use UnknownFieldSets to set its value
6197   // on the options message. We do so because the message may not yet know
6198   // about its extension fields, so we may not be able to set the fields
6199   // directly. But the UnknownFieldSets will serialize to the same wire-format
6200   // message, so reading that message back in once the extension fields are
6201   // known will populate them correctly.
6202 
6203   // First see if the option is already set.
6204   if (!field->is_repeated() && !ExamineIfOptionIsSet(
6205           intermediate_fields.begin(),
6206           intermediate_fields.end(),
6207           field, debug_msg_name,
6208           options->GetReflection()->GetUnknownFields(*options))) {
6209     return false;  // ExamineIfOptionIsSet() already added the error.
6210   }
6211 
6212 
6213   // First set the value on the UnknownFieldSet corresponding to the
6214   // innermost message.
6215   google::protobuf::scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
6216   if (!SetOptionValue(field, unknown_fields.get())) {
6217     return false;  // SetOptionValue() already added the error.
6218   }
6219 
6220   // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
6221   // the intermediate messages.
6222   for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
6223            intermediate_fields.rbegin();
6224        iter != intermediate_fields.rend(); ++iter) {
6225     google::protobuf::scoped_ptr<UnknownFieldSet> parent_unknown_fields(
6226         new UnknownFieldSet());
6227     switch ((*iter)->type()) {
6228       case FieldDescriptor::TYPE_MESSAGE: {
6229         io::StringOutputStream outstr(
6230             parent_unknown_fields->AddLengthDelimited((*iter)->number()));
6231         io::CodedOutputStream out(&outstr);
6232         internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out);
6233         GOOGLE_CHECK(!out.HadError())
6234             << "Unexpected failure while serializing option submessage "
6235             << debug_msg_name << "\".";
6236         break;
6237       }
6238 
6239       case FieldDescriptor::TYPE_GROUP: {
6240          parent_unknown_fields->AddGroup((*iter)->number())
6241                               ->MergeFrom(*unknown_fields);
6242         break;
6243       }
6244 
6245       default:
6246         GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
6247                    << (*iter)->type();
6248         return false;
6249     }
6250     unknown_fields.reset(parent_unknown_fields.release());
6251   }
6252 
6253   // Now merge the UnknownFieldSet corresponding to the top-level message into
6254   // the options message.
6255   options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
6256       *unknown_fields);
6257 
6258   return true;
6259 }
6260 
AddWithoutInterpreting(const UninterpretedOption & uninterpreted_option,Message * options)6261 void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
6262     const UninterpretedOption& uninterpreted_option, Message* options) {
6263   const FieldDescriptor* field =
6264     options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6265   GOOGLE_CHECK(field != NULL);
6266 
6267   options->GetReflection()->AddMessage(options, field)
6268     ->CopyFrom(uninterpreted_option);
6269 }
6270 
ExamineIfOptionIsSet(std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_iter,std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_end,const FieldDescriptor * innermost_field,const string & debug_msg_name,const UnknownFieldSet & unknown_fields)6271 bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
6272     std::vector<const FieldDescriptor*>::const_iterator
6273         intermediate_fields_iter,
6274     std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
6275     const FieldDescriptor* innermost_field, const string& debug_msg_name,
6276     const UnknownFieldSet& unknown_fields) {
6277   // We do linear searches of the UnknownFieldSet and its sub-groups.  This
6278   // should be fine since it's unlikely that any one options structure will
6279   // contain more than a handful of options.
6280 
6281   if (intermediate_fields_iter == intermediate_fields_end) {
6282     // We're at the innermost submessage.
6283     for (int i = 0; i < unknown_fields.field_count(); i++) {
6284       if (unknown_fields.field(i).number() == innermost_field->number()) {
6285         return AddNameError("Option \"" + debug_msg_name +
6286                             "\" was already set.");
6287       }
6288     }
6289     return true;
6290   }
6291 
6292   for (int i = 0; i < unknown_fields.field_count(); i++) {
6293     if (unknown_fields.field(i).number() ==
6294         (*intermediate_fields_iter)->number()) {
6295       const UnknownField* unknown_field = &unknown_fields.field(i);
6296       FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
6297       // Recurse into the next submessage.
6298       switch (type) {
6299         case FieldDescriptor::TYPE_MESSAGE:
6300           if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
6301             UnknownFieldSet intermediate_unknown_fields;
6302             if (intermediate_unknown_fields.ParseFromString(
6303                     unknown_field->length_delimited()) &&
6304                 !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6305                                       intermediate_fields_end,
6306                                       innermost_field, debug_msg_name,
6307                                       intermediate_unknown_fields)) {
6308               return false;  // Error already added.
6309             }
6310           }
6311           break;
6312 
6313         case FieldDescriptor::TYPE_GROUP:
6314           if (unknown_field->type() == UnknownField::TYPE_GROUP) {
6315             if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6316                                       intermediate_fields_end,
6317                                       innermost_field, debug_msg_name,
6318                                       unknown_field->group())) {
6319               return false;  // Error already added.
6320             }
6321           }
6322           break;
6323 
6324         default:
6325           GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
6326           return false;
6327       }
6328     }
6329   }
6330   return true;
6331 }
6332 
SetOptionValue(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)6333 bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
6334     const FieldDescriptor* option_field,
6335     UnknownFieldSet* unknown_fields) {
6336   // We switch on the CppType to validate.
6337   switch (option_field->cpp_type()) {
6338 
6339     case FieldDescriptor::CPPTYPE_INT32:
6340       if (uninterpreted_option_->has_positive_int_value()) {
6341         if (uninterpreted_option_->positive_int_value() >
6342             static_cast<uint64>(kint32max)) {
6343           return AddValueError("Value out of range for int32 option \"" +
6344                                option_field->full_name() + "\".");
6345         } else {
6346           SetInt32(option_field->number(),
6347                    uninterpreted_option_->positive_int_value(),
6348                    option_field->type(), unknown_fields);
6349         }
6350       } else if (uninterpreted_option_->has_negative_int_value()) {
6351         if (uninterpreted_option_->negative_int_value() <
6352             static_cast<int64>(kint32min)) {
6353           return AddValueError("Value out of range for int32 option \"" +
6354                                option_field->full_name() + "\".");
6355         } else {
6356           SetInt32(option_field->number(),
6357                    uninterpreted_option_->negative_int_value(),
6358                    option_field->type(), unknown_fields);
6359         }
6360       } else {
6361         return AddValueError("Value must be integer for int32 option \"" +
6362                              option_field->full_name() + "\".");
6363       }
6364       break;
6365 
6366     case FieldDescriptor::CPPTYPE_INT64:
6367       if (uninterpreted_option_->has_positive_int_value()) {
6368         if (uninterpreted_option_->positive_int_value() >
6369             static_cast<uint64>(kint64max)) {
6370           return AddValueError("Value out of range for int64 option \"" +
6371                                option_field->full_name() + "\".");
6372         } else {
6373           SetInt64(option_field->number(),
6374                    uninterpreted_option_->positive_int_value(),
6375                    option_field->type(), unknown_fields);
6376         }
6377       } else if (uninterpreted_option_->has_negative_int_value()) {
6378         SetInt64(option_field->number(),
6379                  uninterpreted_option_->negative_int_value(),
6380                  option_field->type(), unknown_fields);
6381       } else {
6382         return AddValueError("Value must be integer for int64 option \"" +
6383                              option_field->full_name() + "\".");
6384       }
6385       break;
6386 
6387     case FieldDescriptor::CPPTYPE_UINT32:
6388       if (uninterpreted_option_->has_positive_int_value()) {
6389         if (uninterpreted_option_->positive_int_value() > kuint32max) {
6390           return AddValueError("Value out of range for uint32 option \"" +
6391                                option_field->name() + "\".");
6392         } else {
6393           SetUInt32(option_field->number(),
6394                     uninterpreted_option_->positive_int_value(),
6395                     option_field->type(), unknown_fields);
6396         }
6397       } else {
6398         return AddValueError("Value must be non-negative integer for uint32 "
6399                              "option \"" + option_field->full_name() + "\".");
6400       }
6401       break;
6402 
6403     case FieldDescriptor::CPPTYPE_UINT64:
6404       if (uninterpreted_option_->has_positive_int_value()) {
6405         SetUInt64(option_field->number(),
6406                   uninterpreted_option_->positive_int_value(),
6407                   option_field->type(), unknown_fields);
6408       } else {
6409         return AddValueError("Value must be non-negative integer for uint64 "
6410                              "option \"" + option_field->full_name() + "\".");
6411       }
6412       break;
6413 
6414     case FieldDescriptor::CPPTYPE_FLOAT: {
6415       float value;
6416       if (uninterpreted_option_->has_double_value()) {
6417         value = uninterpreted_option_->double_value();
6418       } else if (uninterpreted_option_->has_positive_int_value()) {
6419         value = uninterpreted_option_->positive_int_value();
6420       } else if (uninterpreted_option_->has_negative_int_value()) {
6421         value = uninterpreted_option_->negative_int_value();
6422       } else {
6423         return AddValueError("Value must be number for float option \"" +
6424                              option_field->full_name() + "\".");
6425       }
6426       unknown_fields->AddFixed32(option_field->number(),
6427           google::protobuf::internal::WireFormatLite::EncodeFloat(value));
6428       break;
6429     }
6430 
6431     case FieldDescriptor::CPPTYPE_DOUBLE: {
6432       double value;
6433       if (uninterpreted_option_->has_double_value()) {
6434         value = uninterpreted_option_->double_value();
6435       } else if (uninterpreted_option_->has_positive_int_value()) {
6436         value = uninterpreted_option_->positive_int_value();
6437       } else if (uninterpreted_option_->has_negative_int_value()) {
6438         value = uninterpreted_option_->negative_int_value();
6439       } else {
6440         return AddValueError("Value must be number for double option \"" +
6441                              option_field->full_name() + "\".");
6442       }
6443       unknown_fields->AddFixed64(option_field->number(),
6444           google::protobuf::internal::WireFormatLite::EncodeDouble(value));
6445       break;
6446     }
6447 
6448     case FieldDescriptor::CPPTYPE_BOOL:
6449       uint64 value;
6450       if (!uninterpreted_option_->has_identifier_value()) {
6451         return AddValueError("Value must be identifier for boolean option "
6452                              "\"" + option_field->full_name() + "\".");
6453       }
6454       if (uninterpreted_option_->identifier_value() == "true") {
6455         value = 1;
6456       } else if (uninterpreted_option_->identifier_value() == "false") {
6457         value = 0;
6458       } else {
6459         return AddValueError("Value must be \"true\" or \"false\" for boolean "
6460                              "option \"" + option_field->full_name() + "\".");
6461       }
6462       unknown_fields->AddVarint(option_field->number(), value);
6463       break;
6464 
6465     case FieldDescriptor::CPPTYPE_ENUM: {
6466       if (!uninterpreted_option_->has_identifier_value()) {
6467         return AddValueError("Value must be identifier for enum-valued option "
6468                              "\"" + option_field->full_name() + "\".");
6469       }
6470       const EnumDescriptor* enum_type = option_field->enum_type();
6471       const string& value_name = uninterpreted_option_->identifier_value();
6472       const EnumValueDescriptor* enum_value = NULL;
6473 
6474       if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
6475         // Note that the enum value's fully-qualified name is a sibling of the
6476         // enum's name, not a child of it.
6477         string fully_qualified_name = enum_type->full_name();
6478         fully_qualified_name.resize(fully_qualified_name.size() -
6479                                     enum_type->name().size());
6480         fully_qualified_name += value_name;
6481 
6482         // Search for the enum value's descriptor in the builder's pool. Note
6483         // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
6484         // DescriptorPool::FindEnumValueByName() because we're already holding
6485         // the pool's mutex, and the latter method locks it again.
6486         Symbol symbol =
6487           builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
6488         if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) {
6489           if (symbol.enum_value_descriptor->type() != enum_type) {
6490             return AddValueError("Enum type \"" + enum_type->full_name() +
6491                 "\" has no value named \"" + value_name + "\" for option \"" +
6492                 option_field->full_name() +
6493                 "\". This appears to be a value from a sibling type.");
6494           } else {
6495             enum_value = symbol.enum_value_descriptor;
6496           }
6497         }
6498       } else {
6499         // The enum type is in the generated pool, so we can search for the
6500         // value there.
6501         enum_value = enum_type->FindValueByName(value_name);
6502       }
6503 
6504       if (enum_value == NULL) {
6505         return AddValueError("Enum type \"" +
6506                              option_field->enum_type()->full_name() +
6507                              "\" has no value named \"" + value_name + "\" for "
6508                              "option \"" + option_field->full_name() + "\".");
6509       } else {
6510         // Sign-extension is not a problem, since we cast directly from int32 to
6511         // uint64, without first going through uint32.
6512         unknown_fields->AddVarint(option_field->number(),
6513           static_cast<uint64>(static_cast<int64>(enum_value->number())));
6514       }
6515       break;
6516     }
6517 
6518     case FieldDescriptor::CPPTYPE_STRING:
6519       if (!uninterpreted_option_->has_string_value()) {
6520         return AddValueError("Value must be quoted string for string option "
6521                              "\"" + option_field->full_name() + "\".");
6522       }
6523       // The string has already been unquoted and unescaped by the parser.
6524       unknown_fields->AddLengthDelimited(option_field->number(),
6525           uninterpreted_option_->string_value());
6526       break;
6527 
6528     case FieldDescriptor::CPPTYPE_MESSAGE:
6529       if (!SetAggregateOption(option_field, unknown_fields)) {
6530         return false;
6531       }
6532       break;
6533   }
6534 
6535   return true;
6536 }
6537 
6538 class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
6539     : public TextFormat::Finder {
6540  public:
6541   DescriptorBuilder* builder_;
6542 
FindExtension(Message * message,const string & name) const6543   virtual const FieldDescriptor* FindExtension(
6544       Message* message, const string& name) const {
6545     assert_mutex_held(builder_->pool_);
6546     const Descriptor* descriptor = message->GetDescriptor();
6547     Symbol result = builder_->LookupSymbolNoPlaceholder(
6548         name, descriptor->full_name());
6549     if (result.type == Symbol::FIELD &&
6550         result.field_descriptor->is_extension()) {
6551       return result.field_descriptor;
6552     } else if (result.type == Symbol::MESSAGE &&
6553                descriptor->options().message_set_wire_format()) {
6554       const Descriptor* foreign_type = result.descriptor;
6555       // The text format allows MessageSet items to be specified using
6556       // the type name, rather than the extension identifier. If the symbol
6557       // lookup returned a Message, and the enclosing Message has
6558       // message_set_wire_format = true, then return the message set
6559       // extension, if one exists.
6560       for (int i = 0; i < foreign_type->extension_count(); i++) {
6561         const FieldDescriptor* extension = foreign_type->extension(i);
6562         if (extension->containing_type() == descriptor &&
6563             extension->type() == FieldDescriptor::TYPE_MESSAGE &&
6564             extension->is_optional() &&
6565             extension->message_type() == foreign_type) {
6566           // Found it.
6567           return extension;
6568         }
6569       }
6570     }
6571     return NULL;
6572   }
6573 };
6574 
6575 // A custom error collector to record any text-format parsing errors
6576 namespace {
6577 class AggregateErrorCollector : public io::ErrorCollector {
6578  public:
6579   string error_;
6580 
AddError(int,int,const string & message)6581   virtual void AddError(int /* line */, int /* column */,
6582                         const string& message) {
6583     if (!error_.empty()) {
6584       error_ += "; ";
6585     }
6586     error_ += message;
6587   }
6588 
AddWarning(int,int,const string &)6589   virtual void AddWarning(int /* line */, int /* column */,
6590                           const string& /* message */) {
6591     // Ignore warnings
6592   }
6593 };
6594 }
6595 
6596 // We construct a dynamic message of the type corresponding to
6597 // option_field, parse the supplied text-format string into this
6598 // message, and serialize the resulting message to produce the value.
SetAggregateOption(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)6599 bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
6600     const FieldDescriptor* option_field,
6601     UnknownFieldSet* unknown_fields) {
6602   if (!uninterpreted_option_->has_aggregate_value()) {
6603     return AddValueError("Option \"" + option_field->full_name() +
6604                          "\" is a message. To set the entire message, use "
6605                          "syntax like \"" + option_field->name() +
6606                          " = { <proto text format> }\". "
6607                          "To set fields within it, use "
6608                          "syntax like \"" + option_field->name() +
6609                          ".foo = value\".");
6610   }
6611 
6612   const Descriptor* type = option_field->message_type();
6613   google::protobuf::scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
6614   GOOGLE_CHECK(dynamic.get() != NULL)
6615       << "Could not create an instance of " << option_field->DebugString();
6616 
6617   AggregateErrorCollector collector;
6618   AggregateOptionFinder finder;
6619   finder.builder_ = builder_;
6620   TextFormat::Parser parser;
6621   parser.RecordErrorsTo(&collector);
6622   parser.SetFinder(&finder);
6623   if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
6624                               dynamic.get())) {
6625     AddValueError("Error while parsing option value for \"" +
6626                   option_field->name() + "\": " + collector.error_);
6627     return false;
6628   } else {
6629     string serial;
6630     dynamic->SerializeToString(&serial);  // Never fails
6631     if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
6632       unknown_fields->AddLengthDelimited(option_field->number(), serial);
6633     } else {
6634       GOOGLE_CHECK_EQ(option_field->type(),  FieldDescriptor::TYPE_GROUP);
6635       UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
6636       group->ParseFromString(serial);
6637     }
6638     return true;
6639   }
6640 }
6641 
SetInt32(int number,int32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)6642 void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
6643     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
6644   switch (type) {
6645     case FieldDescriptor::TYPE_INT32:
6646       unknown_fields->AddVarint(number,
6647         static_cast<uint64>(static_cast<int64>(value)));
6648       break;
6649 
6650     case FieldDescriptor::TYPE_SFIXED32:
6651       unknown_fields->AddFixed32(number, static_cast<uint32>(value));
6652       break;
6653 
6654     case FieldDescriptor::TYPE_SINT32:
6655       unknown_fields->AddVarint(number,
6656           google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
6657       break;
6658 
6659     default:
6660       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
6661       break;
6662   }
6663 }
6664 
SetInt64(int number,int64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)6665 void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
6666     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
6667   switch (type) {
6668     case FieldDescriptor::TYPE_INT64:
6669       unknown_fields->AddVarint(number, static_cast<uint64>(value));
6670       break;
6671 
6672     case FieldDescriptor::TYPE_SFIXED64:
6673       unknown_fields->AddFixed64(number, static_cast<uint64>(value));
6674       break;
6675 
6676     case FieldDescriptor::TYPE_SINT64:
6677       unknown_fields->AddVarint(number,
6678           google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
6679       break;
6680 
6681     default:
6682       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
6683       break;
6684   }
6685 }
6686 
SetUInt32(int number,uint32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)6687 void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value,
6688     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
6689   switch (type) {
6690     case FieldDescriptor::TYPE_UINT32:
6691       unknown_fields->AddVarint(number, static_cast<uint64>(value));
6692       break;
6693 
6694     case FieldDescriptor::TYPE_FIXED32:
6695       unknown_fields->AddFixed32(number, static_cast<uint32>(value));
6696       break;
6697 
6698     default:
6699       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
6700       break;
6701   }
6702 }
6703 
SetUInt64(int number,uint64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)6704 void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value,
6705     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
6706   switch (type) {
6707     case FieldDescriptor::TYPE_UINT64:
6708       unknown_fields->AddVarint(number, value);
6709       break;
6710 
6711     case FieldDescriptor::TYPE_FIXED64:
6712       unknown_fields->AddFixed64(number, value);
6713       break;
6714 
6715     default:
6716       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
6717       break;
6718   }
6719 }
6720 
LogUnusedDependency(const FileDescriptorProto & proto,const FileDescriptor * result)6721 void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
6722                                             const FileDescriptor* result) {
6723 
6724   if (!unused_dependency_.empty()) {
6725     std::set<string> annotation_extensions;
6726     annotation_extensions.insert("google.protobuf.MessageOptions");
6727     annotation_extensions.insert("google.protobuf.FileOptions");
6728     annotation_extensions.insert("google.protobuf.FieldOptions");
6729     annotation_extensions.insert("google.protobuf.EnumOptions");
6730     annotation_extensions.insert("google.protobuf.EnumValueOptions");
6731     annotation_extensions.insert("google.protobuf.EnumValueOptions");
6732     annotation_extensions.insert("google.protobuf.ServiceOptions");
6733     annotation_extensions.insert("google.protobuf.MethodOptions");
6734     annotation_extensions.insert("google.protobuf.StreamOptions");
6735     for (std::set<const FileDescriptor*>::const_iterator
6736              it = unused_dependency_.begin();
6737          it != unused_dependency_.end(); ++it) {
6738       // Do not log warnings for proto files which extend annotations.
6739       int i;
6740       for (i = 0 ; i < (*it)->extension_count(); ++i) {
6741         if (annotation_extensions.find(
6742                 (*it)->extension(i)->containing_type()->full_name())
6743             != annotation_extensions.end()) {
6744           break;
6745         }
6746       }
6747       // Log warnings for unused imported files.
6748       if (i == (*it)->extension_count()) {
6749         string error_message = "Import " + (*it)->name() + " but not used.";
6750         AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::OTHER,
6751                    error_message);
6752       }
6753     }
6754   }
6755 }
6756 
CrossLinkOnDemandHelper(const string & name,bool expecting_enum) const6757 Symbol DescriptorPool::CrossLinkOnDemandHelper(const string& name,
6758                                                bool expecting_enum) const {
6759   string lookup_name = name;
6760   if (!lookup_name.empty() && lookup_name[0] == '.') {
6761     lookup_name = lookup_name.substr(1);
6762   }
6763   Symbol result = tables_->FindByNameHelper(this, lookup_name);
6764   return result;
6765 }
6766 
6767 // Handle the lazy import building for a message field whose type wasn't built
6768 // at cross link time. If that was the case, we saved the name of the type to
6769 // be looked up when the accessor for the type was called. Set type_,
6770 // enum_type_, message_type_, and default_value_enum_ appropriately.
InternalTypeOnceInit() const6771 void FieldDescriptor::InternalTypeOnceInit() const {
6772   GOOGLE_CHECK(file()->finished_building_ == true);
6773   if (type_name_) {
6774     Symbol result = file()->pool()->CrossLinkOnDemandHelper(
6775         *type_name_, type_ == FieldDescriptor::TYPE_ENUM);
6776     if (result.type == Symbol::MESSAGE) {
6777       type_ = FieldDescriptor::TYPE_MESSAGE;
6778       message_type_ = result.descriptor;
6779     } else if (result.type == Symbol::ENUM) {
6780       type_ = FieldDescriptor::TYPE_ENUM;
6781       enum_type_ = result.enum_descriptor;
6782     }
6783   }
6784   if (enum_type_ && !default_value_enum_) {
6785     if (default_value_enum_name_) {
6786       // Have to build the full name now instead of at CrossLink time,
6787       // because enum_type_ may not be known at the time.
6788       string name = enum_type_->full_name();
6789       // Enum values reside in the same scope as the enum type.
6790       string::size_type last_dot = name.find_last_of('.');
6791       if (last_dot != string::npos) {
6792         name = name.substr(0, last_dot) + "." + *default_value_enum_name_;
6793       } else {
6794         name = *default_value_enum_name_;
6795       }
6796       Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
6797       if (result.type == Symbol::ENUM_VALUE) {
6798         default_value_enum_ = result.enum_value_descriptor;
6799       }
6800     }
6801     if (!default_value_enum_) {
6802       // We use the first defined value as the default
6803       // if a default is not explicitly defined.
6804       GOOGLE_CHECK(enum_type_->value_count());
6805       default_value_enum_ = enum_type_->value(0);
6806     }
6807   }
6808 }
6809 
TypeOnceInit(const FieldDescriptor * to_init)6810 void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
6811   to_init->InternalTypeOnceInit();
6812 }
6813 
6814 // message_type(), enum_type(), default_value_enum(), and type()
6815 // all share the same GoogleOnceDynamic init path to do lazy
6816 // import building and cross linking of a field of a message.
message_type() const6817 const Descriptor* FieldDescriptor::message_type() const {
6818   if (type_once_) {
6819     type_once_->Init(&FieldDescriptor::TypeOnceInit, this);
6820   }
6821   return message_type_;
6822 }
6823 
enum_type() const6824 const EnumDescriptor* FieldDescriptor::enum_type() const {
6825   if (type_once_) {
6826     type_once_->Init(&FieldDescriptor::TypeOnceInit, this);
6827   }
6828   return enum_type_;
6829 }
6830 
default_value_enum() const6831 const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
6832   if (type_once_) {
6833     type_once_->Init(&FieldDescriptor::TypeOnceInit, this);
6834   }
6835   return default_value_enum_;
6836 }
6837 
type() const6838 FieldDescriptor::Type FieldDescriptor::type() const {
6839   if (type_once_) {
6840     type_once_->Init(&FieldDescriptor::TypeOnceInit, this);
6841   }
6842   return type_;
6843 }
6844 
InternalDependenciesOnceInit() const6845 void FileDescriptor::InternalDependenciesOnceInit() const {
6846   GOOGLE_CHECK(finished_building_ == true);
6847   for (int i = 0; i < dependency_count(); i++) {
6848     if (dependencies_names_[i]) {
6849       dependencies_[i] = pool_->FindFileByName(*dependencies_names_[i]);
6850     }
6851   }
6852 }
6853 
DependenciesOnceInit(const FileDescriptor * to_init)6854 void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
6855   to_init->InternalDependenciesOnceInit();
6856 }
6857 
dependency(int index) const6858 const FileDescriptor* FileDescriptor::dependency(int index) const {
6859   if (dependencies_once_) {
6860     // Do once init for all indicies, as it's unlikely only a single index would
6861     // be called, and saves on GoogleOnceDynamic allocations.
6862     dependencies_once_->Init(&FileDescriptor::DependenciesOnceInit, this);
6863   }
6864   return dependencies_[index];
6865 }
6866 
input_type() const6867 const Descriptor* MethodDescriptor::input_type() const {
6868   return input_type_.Get();
6869 }
6870 
output_type() const6871 const Descriptor* MethodDescriptor::output_type() const {
6872   return output_type_.Get();
6873 }
6874 
6875 
6876 namespace internal {
Set(const Descriptor * descriptor)6877 void LazyDescriptor::Set(const Descriptor* descriptor) {
6878   GOOGLE_CHECK(!name_);
6879   GOOGLE_CHECK(!once_);
6880   GOOGLE_CHECK(!file_);
6881   descriptor_ = descriptor;
6882 }
6883 
SetLazy(const string & name,const FileDescriptor * file)6884 void LazyDescriptor::SetLazy(const string& name, const FileDescriptor* file) {
6885   // verify Init() has been called and Set hasn't been called yet.
6886   GOOGLE_CHECK(!descriptor_);
6887   GOOGLE_CHECK(!file_);
6888   GOOGLE_CHECK(!name_);
6889   GOOGLE_CHECK(!once_);
6890   GOOGLE_CHECK(file && file->pool_);
6891   GOOGLE_CHECK(file->pool_->lazily_build_dependencies_);
6892   GOOGLE_CHECK(!file->finished_building_);
6893   file_ = file;
6894   name_ = file->pool_->tables_->AllocateString(name);
6895   once_ = file->pool_->tables_->AllocateOnceDynamic();
6896 }
6897 
Once()6898 void LazyDescriptor::Once() {
6899   if (once_) {
6900     once_->Init(&LazyDescriptor::OnceStatic, this);
6901   }
6902 }
6903 
OnceStatic(LazyDescriptor * lazy)6904 void LazyDescriptor::OnceStatic(LazyDescriptor* lazy) { lazy->OnceInternal(); }
6905 
OnceInternal()6906 void LazyDescriptor::OnceInternal() {
6907   GOOGLE_CHECK(file_->finished_building_);
6908   if (!descriptor_ && name_) {
6909     Symbol result = file_->pool_->CrossLinkOnDemandHelper(*name_, false);
6910     if (!result.IsNull() && result.type == Symbol::MESSAGE) {
6911       descriptor_ = result.descriptor;
6912     }
6913   }
6914 }
6915 }  // namespace internal
6916 
6917 }  // namespace protobuf
6918 }  // namespace google
6919