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