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