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/compiler/cpp/cpp_file.h>
36 #include <map>
37 #include <memory>
38 #ifndef _SHARED_PTR_H
39 #include <google/protobuf/stubs/shared_ptr.h>
40 #endif
41 #include <set>
42
43 #include <google/protobuf/compiler/cpp/cpp_enum.h>
44 #include <google/protobuf/compiler/cpp/cpp_service.h>
45 #include <google/protobuf/compiler/cpp/cpp_extension.h>
46 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
47 #include <google/protobuf/compiler/cpp/cpp_message.h>
48 #include <google/protobuf/compiler/cpp/cpp_field.h>
49 #include <google/protobuf/io/printer.h>
50 #include <google/protobuf/descriptor.pb.h>
51 #include <google/protobuf/stubs/strutil.h>
52
53 namespace google {
54 namespace protobuf {
55 namespace compiler {
56 namespace cpp {
57
58 // ===================================================================
59
FileGenerator(const FileDescriptor * file,const Options & options)60 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
61 : file_(file),
62 options_(options),
63 message_generators_(
64 new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
65 enum_generators_(
66 new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
67 service_generators_(
68 new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
69 extension_generators_(
70 new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
71
72 for (int i = 0; i < file->message_type_count(); i++) {
73 message_generators_[i].reset(
74 new MessageGenerator(file->message_type(i), options));
75 }
76
77 for (int i = 0; i < file->enum_type_count(); i++) {
78 enum_generators_[i].reset(
79 new EnumGenerator(file->enum_type(i), options));
80 }
81
82 for (int i = 0; i < file->service_count(); i++) {
83 service_generators_[i].reset(
84 new ServiceGenerator(file->service(i), options));
85 }
86
87 for (int i = 0; i < file->extension_count(); i++) {
88 extension_generators_[i].reset(
89 new ExtensionGenerator(file->extension(i), options));
90 }
91
92 SplitStringUsing(file_->package(), ".", &package_parts_);
93 }
94
~FileGenerator()95 FileGenerator::~FileGenerator() {}
96
GenerateProtoHeader(io::Printer * printer,const string & info_path)97 void FileGenerator::GenerateProtoHeader(io::Printer* printer,
98 const string& info_path) {
99 if (!options_.proto_h) {
100 return;
101 }
102
103 string filename_identifier = FilenameIdentifier(file_->name());
104 GenerateTopHeaderGuard(printer, filename_identifier);
105
106
107 GenerateLibraryIncludes(printer);
108
109 for (int i = 0; i < file_->public_dependency_count(); i++) {
110 const FileDescriptor* dep = file_->public_dependency(i);
111 const char* extension = ".proto.h";
112 string dependency = StripProto(dep->name()) + extension;
113 printer->Print(
114 "#include \"$dependency$\" // IWYU pragma: export\n",
115 "dependency", dependency);
116 }
117
118 GenerateMetadataPragma(printer, info_path);
119
120 printer->Print(
121 "// @@protoc_insertion_point(includes)\n");
122
123
124 GenerateForwardDeclarations(printer);
125
126 // Open namespace.
127 GenerateNamespaceOpeners(printer);
128
129 GenerateGlobalStateFunctionDeclarations(printer);
130
131 printer->Print("\n");
132
133 GenerateEnumDefinitions(printer);
134
135 printer->Print(kThickSeparator);
136 printer->Print("\n");
137
138 GenerateMessageDefinitions(printer);
139
140 printer->Print("\n");
141 printer->Print(kThickSeparator);
142 printer->Print("\n");
143
144 GenerateServiceDefinitions(printer);
145
146 GenerateExtensionIdentifiers(printer);
147
148 printer->Print("\n");
149 printer->Print(kThickSeparator);
150 printer->Print("\n");
151
152 GenerateInlineFunctionDefinitions(printer);
153
154 printer->Print(
155 "\n"
156 "// @@protoc_insertion_point(namespace_scope)\n"
157 "\n");
158
159 // Close up namespace.
160 GenerateNamespaceClosers(printer);
161
162 // We need to specialize some templates in the ::google::protobuf namespace:
163 GenerateProto2NamespaceEnumSpecializations(printer);
164
165 printer->Print(
166 "\n"
167 "// @@protoc_insertion_point(global_scope)\n"
168 "\n");
169
170 GenerateBottomHeaderGuard(printer, filename_identifier);
171 }
172
GeneratePBHeader(io::Printer * printer,const string & info_path)173 void FileGenerator::GeneratePBHeader(io::Printer* printer,
174 const string& info_path) {
175 string filename_identifier =
176 FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
177 GenerateTopHeaderGuard(printer, filename_identifier);
178
179 if (options_.proto_h) {
180 printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
181 "basename", StripProto(file_->name()));
182 } else {
183 GenerateLibraryIncludes(printer);
184 }
185 GenerateDependencyIncludes(printer);
186 GenerateMetadataPragma(printer, info_path);
187
188 printer->Print(
189 "// @@protoc_insertion_point(includes)\n");
190
191
192
193 // Open namespace.
194 GenerateNamespaceOpeners(printer);
195
196 if (!options_.proto_h) {
197 GenerateGlobalStateFunctionDeclarations(printer);
198 GenerateMessageForwardDeclarations(printer);
199
200 printer->Print("\n");
201
202 GenerateEnumDefinitions(printer);
203
204 printer->Print(kThickSeparator);
205 printer->Print("\n");
206
207 GenerateMessageDefinitions(printer);
208
209 printer->Print("\n");
210 printer->Print(kThickSeparator);
211 printer->Print("\n");
212
213 GenerateServiceDefinitions(printer);
214
215 GenerateExtensionIdentifiers(printer);
216
217 printer->Print("\n");
218 printer->Print(kThickSeparator);
219 printer->Print("\n");
220
221 GenerateInlineFunctionDefinitions(printer);
222 }
223
224 printer->Print(
225 "\n"
226 "// @@protoc_insertion_point(namespace_scope)\n");
227
228 // Close up namespace.
229 GenerateNamespaceClosers(printer);
230
231 if (!options_.proto_h) {
232 // We need to specialize some templates in the ::google::protobuf namespace:
233 GenerateProto2NamespaceEnumSpecializations(printer);
234 }
235
236 printer->Print(
237 "\n"
238 "// @@protoc_insertion_point(global_scope)\n"
239 "\n");
240
241 GenerateBottomHeaderGuard(printer, filename_identifier);
242 }
243
GenerateSource(io::Printer * printer)244 void FileGenerator::GenerateSource(io::Printer* printer) {
245 const bool use_system_include = IsWellKnownMessage(file_);
246 string header =
247 StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
248 printer->Print(
249 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
250 "// source: $filename$\n"
251 "\n"
252 // The generated code calls accessors that might be deprecated. We don't
253 // want the compiler to warn in generated code.
254 "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
255 "#include $left$$header$$right$\n"
256 "\n"
257 "#include <algorithm>\n" // for swap()
258 "\n"
259 "#include <google/protobuf/stubs/common.h>\n"
260 "#include <google/protobuf/stubs/port.h>\n"
261 "#include <google/protobuf/stubs/once.h>\n"
262 "#include <google/protobuf/io/coded_stream.h>\n"
263 "#include <google/protobuf/wire_format_lite_inl.h>\n",
264 "filename", file_->name(),
265 "header", header,
266 "left", use_system_include ? "<" : "\"",
267 "right", use_system_include ? ">" : "\"");
268
269 // Unknown fields implementation in lite mode uses StringOutputStream
270 if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
271 printer->Print(
272 "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
273 }
274
275 if (HasDescriptorMethods(file_, options_)) {
276 printer->Print(
277 "#include <google/protobuf/descriptor.h>\n"
278 "#include <google/protobuf/generated_message_reflection.h>\n"
279 "#include <google/protobuf/reflection_ops.h>\n"
280 "#include <google/protobuf/wire_format.h>\n");
281 }
282
283 if (options_.proto_h) {
284 // Use the smaller .proto.h files.
285 for (int i = 0; i < file_->dependency_count(); i++) {
286 const FileDescriptor* dep = file_->dependency(i);
287 const char* extension = ".proto.h";
288 string dependency = StripProto(dep->name()) + extension;
289 printer->Print(
290 "#include \"$dependency$\"\n",
291 "dependency", dependency);
292 }
293 }
294
295 printer->Print(
296 "// @@protoc_insertion_point(includes)\n");
297
298 GenerateNamespaceOpeners(printer);
299
300 if (HasDescriptorMethods(file_, options_)) {
301 printer->Print(
302 "\n"
303 "namespace {\n"
304 "\n");
305 for (int i = 0; i < file_->message_type_count(); i++) {
306 message_generators_[i]->GenerateDescriptorDeclarations(printer);
307 }
308 for (int i = 0; i < file_->enum_type_count(); i++) {
309 printer->Print(
310 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
311 "name", ClassName(file_->enum_type(i), false));
312 }
313
314 if (HasGenericServices(file_, options_)) {
315 for (int i = 0; i < file_->service_count(); i++) {
316 printer->Print(
317 "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
318 "name", file_->service(i)->name());
319 }
320 }
321
322 printer->Print(
323 "\n"
324 "} // namespace\n"
325 "\n");
326 }
327
328 // Define our externally-visible BuildDescriptors() function. (For the lite
329 // library, all this does is initialize default instances.)
330 GenerateBuildDescriptors(printer);
331
332 // Generate enums.
333 for (int i = 0; i < file_->enum_type_count(); i++) {
334 enum_generators_[i]->GenerateMethods(printer);
335 }
336
337 // Generate classes.
338 for (int i = 0; i < file_->message_type_count(); i++) {
339 printer->Print("\n");
340 printer->Print(kThickSeparator);
341 printer->Print("\n");
342 message_generators_[i]->GenerateClassMethods(printer);
343
344 printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
345 // Generate class inline methods.
346 message_generators_[i]->GenerateInlineMethods(printer,
347 /* is_inline = */ false);
348 printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
349 }
350
351 if (HasGenericServices(file_, options_)) {
352 // Generate services.
353 for (int i = 0; i < file_->service_count(); i++) {
354 if (i == 0) printer->Print("\n");
355 printer->Print(kThickSeparator);
356 printer->Print("\n");
357 service_generators_[i]->GenerateImplementation(printer);
358 }
359 }
360
361 // Define extensions.
362 for (int i = 0; i < file_->extension_count(); i++) {
363 extension_generators_[i]->GenerateDefinition(printer);
364 }
365
366 printer->Print(
367 "\n"
368 "// @@protoc_insertion_point(namespace_scope)\n");
369
370 GenerateNamespaceClosers(printer);
371
372 printer->Print(
373 "\n"
374 "// @@protoc_insertion_point(global_scope)\n");
375 }
376
377 class FileGenerator::ForwardDeclarations {
378 public:
~ForwardDeclarations()379 ~ForwardDeclarations() {
380 for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
381 end = namespaces_.end();
382 it != end; ++it) {
383 delete it->second;
384 }
385 namespaces_.clear();
386 }
387
AddOrGetNamespace(const string & ns_name)388 ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
389 ForwardDeclarations*& ns = namespaces_[ns_name];
390 if (ns == NULL) {
391 ns = new ForwardDeclarations;
392 }
393 return ns;
394 }
395
classes()396 map<string, const Descriptor*>& classes() { return classes_; }
enums()397 map<string, const EnumDescriptor*>& enums() { return enums_; }
398
Print(io::Printer * printer) const399 void Print(io::Printer* printer) const {
400 for (map<string, const EnumDescriptor *>::const_iterator
401 it = enums_.begin(),
402 end = enums_.end();
403 it != end; ++it) {
404 printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
405 printer->Annotate("enumname", it->second);
406 printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
407 it->first);
408 }
409 for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
410 end = classes_.end();
411 it != end; ++it) {
412 printer->Print("class $classname$;\n", "classname", it->first);
413 printer->Annotate("classname", it->second);
414 }
415 for (map<string, ForwardDeclarations *>::const_iterator
416 it = namespaces_.begin(),
417 end = namespaces_.end();
418 it != end; ++it) {
419 printer->Print("namespace $nsname$ {\n",
420 "nsname", it->first);
421 it->second->Print(printer);
422 printer->Print("} // namespace $nsname$\n",
423 "nsname", it->first);
424 }
425 }
426
427
428 private:
429 map<string, ForwardDeclarations*> namespaces_;
430 map<string, const Descriptor*> classes_;
431 map<string, const EnumDescriptor*> enums_;
432 };
433
GenerateBuildDescriptors(io::Printer * printer)434 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
435 // AddDescriptors() is a file-level procedure which adds the encoded
436 // FileDescriptorProto for this .proto file to the global DescriptorPool for
437 // generated files (DescriptorPool::generated_pool()). It either runs at
438 // static initialization time (by default) or when default_instance() is
439 // called for the first time (in LITE_RUNTIME mode with
440 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
441 // constructs default instances and registers extensions.
442 //
443 // Its sibling, AssignDescriptors(), actually pulls the compiled
444 // FileDescriptor from the DescriptorPool and uses it to populate all of
445 // the global variables which store pointers to the descriptor objects.
446 // It also constructs the reflection objects. It is called the first time
447 // anyone calls descriptor() or GetReflection() on one of the types defined
448 // in the file.
449
450 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
451 // and we only use AddDescriptors() to allocate default instances.
452 if (HasDescriptorMethods(file_, options_)) {
453 printer->Print(
454 "\n"
455 "void $assigndescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
456 "void $assigndescriptorsname$() {\n",
457 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
458 printer->Indent();
459
460 // Make sure the file has found its way into the pool. If a descriptor
461 // is requested *during* static init then AddDescriptors() may not have
462 // been called yet, so we call it manually. Note that it's fine if
463 // AddDescriptors() is called multiple times.
464 printer->Print(
465 "$adddescriptorsname$();\n",
466 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
467
468 // Get the file's descriptor from the pool.
469 printer->Print(
470 "const ::google::protobuf::FileDescriptor* file =\n"
471 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
472 " \"$filename$\");\n"
473 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
474 // being unused when compiling an empty .proto file.
475 "GOOGLE_CHECK(file != NULL);\n",
476 "filename", file_->name());
477
478 // Go through all the stuff defined in this file and generated code to
479 // assign the global descriptor pointers based on the file descriptor.
480 for (int i = 0; i < file_->message_type_count(); i++) {
481 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
482 }
483 for (int i = 0; i < file_->enum_type_count(); i++) {
484 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
485 }
486 if (HasGenericServices(file_, options_)) {
487 for (int i = 0; i < file_->service_count(); i++) {
488 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
489 }
490 }
491
492 printer->Outdent();
493 printer->Print(
494 "}\n"
495 "\n");
496
497 // ---------------------------------------------------------------
498
499 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
500 // AssignDescriptors(). All later times, waits for the first call to
501 // complete and then returns.
502 printer->Print(
503 "namespace {\n"
504 "\n"
505 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
506 "inline void protobuf_AssignDescriptorsOnce() {\n"
507 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
508 " &$assigndescriptorsname$);\n"
509 "}\n"
510 "\n",
511 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
512
513 // protobuf_RegisterTypes(): Calls
514 // MessageFactory::InternalRegisterGeneratedType() for each message type.
515 printer->Print(
516 "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n"
517 "void protobuf_RegisterTypes(const ::std::string&) {\n"
518 " protobuf_AssignDescriptorsOnce();\n");
519 printer->Indent();
520
521 for (int i = 0; i < file_->message_type_count(); i++) {
522 message_generators_[i]->GenerateTypeRegistrations(printer);
523 }
524
525 printer->Outdent();
526 printer->Print(
527 "}\n"
528 "\n"
529 "} // namespace\n");
530 }
531
532 // -----------------------------------------------------------------
533
534 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
535 printer->Print(
536 "\n"
537 "void $shutdownfilename$() {\n",
538 "shutdownfilename", GlobalShutdownFileName(file_->name()));
539 printer->Indent();
540
541 for (int i = 0; i < file_->message_type_count(); i++) {
542 message_generators_[i]->GenerateShutdownCode(printer);
543 }
544
545 printer->Outdent();
546 printer->Print(
547 "}\n\n");
548
549 // -----------------------------------------------------------------
550
551 // Now generate the AddDescriptors() function.
552 PrintHandlingOptionalStaticInitializers(
553 file_, options_, printer,
554 // With static initializers.
555 // Note that we don't need any special synchronization in the following
556 // code
557 // because it is called at static init time before any threads exist.
558 "void $adddescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
559 "void $adddescriptorsname$() {\n"
560 " static bool already_here = false;\n"
561 " if (already_here) return;\n"
562 " already_here = true;\n"
563 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
564 "\n",
565 // Without.
566 "void $adddescriptorsname$_impl() {\n"
567 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
568 "\n",
569 // Vars.
570 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
571
572 printer->Indent();
573
574 // Call the AddDescriptors() methods for all of our dependencies, to make
575 // sure they get added first.
576 for (int i = 0; i < file_->dependency_count(); i++) {
577 const FileDescriptor* dependency = file_->dependency(i);
578 // Print the namespace prefix for the dependency.
579 string add_desc_name = QualifiedFileLevelSymbol(
580 dependency->package(), GlobalAddDescriptorsName(dependency->name()));
581 // Call its AddDescriptors function.
582 printer->Print(
583 "$name$();\n",
584 "name", add_desc_name);
585 }
586
587 if (HasDescriptorMethods(file_, options_)) {
588 // Embed the descriptor. We simply serialize the entire FileDescriptorProto
589 // and embed it as a string literal, which is parsed and built into real
590 // descriptors at initialization time.
591 FileDescriptorProto file_proto;
592 file_->CopyTo(&file_proto);
593 string file_data;
594 file_proto.SerializeToString(&file_data);
595
596 #ifdef _MSC_VER
597 bool breakdown_large_file = true;
598 #else
599 bool breakdown_large_file = false;
600 #endif
601 // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
602 // bytes in length". Declare a static array of characters rather than use a
603 // string literal.
604 if (breakdown_large_file && file_data.size() > 65535) {
605 // This has to be explicitly marked as a signed char because the generated
606 // code puts negative values in the array, and sometimes plain char is
607 // unsigned. That implicit narrowing conversion is not allowed in C++11.
608 // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
609 // has details on why.
610 printer->Print(
611 "static const signed char descriptor[] = {\n");
612 printer->Indent();
613
614 // Only write 25 bytes per line.
615 static const int kBytesPerLine = 25;
616 for (int i = 0; i < file_data.size();) {
617 for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
618 printer->Print(
619 "$char$, ",
620 "char", SimpleItoa(file_data[i]));
621 }
622 printer->Print(
623 "\n");
624 }
625
626 printer->Outdent();
627 printer->Print(
628 "};\n");
629
630 printer->Print(
631 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
632 "size", SimpleItoa(file_data.size()));
633
634 } else {
635 printer->Print(
636 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
637
638 // Only write 40 bytes per line.
639 static const int kBytesPerLine = 40;
640 for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
641 printer->Print("\n \"$data$\"",
642 "data",
643 EscapeTrigraphs(
644 CEscape(file_data.substr(i, kBytesPerLine))));
645 }
646 printer->Print(
647 ", $size$);\n",
648 "size", SimpleItoa(file_data.size()));
649 }
650
651 // Call MessageFactory::InternalRegisterGeneratedFile().
652 printer->Print(
653 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
654 " \"$filename$\", &protobuf_RegisterTypes);\n",
655 "filename", file_->name());
656 }
657
658 // Allocate and initialize default instances. This can't be done lazily
659 // since default instances are returned by simple accessors and are used with
660 // extensions. Speaking of which, we also register extensions at this time.
661 for (int i = 0; i < file_->message_type_count(); i++) {
662 message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
663 }
664 for (int i = 0; i < file_->extension_count(); i++) {
665 extension_generators_[i]->GenerateRegistration(printer);
666 }
667 for (int i = 0; i < file_->message_type_count(); i++) {
668 message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
669 }
670
671 printer->Print(
672 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
673 "shutdownfilename", GlobalShutdownFileName(file_->name()));
674
675 printer->Outdent();
676 printer->Print(
677 "}\n"
678 "\n");
679
680 PrintHandlingOptionalStaticInitializers(
681 file_, options_, printer,
682 // With static initializers.
683 "// Force AddDescriptors() to be called at static initialization time.\n"
684 "struct StaticDescriptorInitializer_$filename$ {\n"
685 " StaticDescriptorInitializer_$filename$() {\n"
686 " $adddescriptorsname$();\n"
687 " }\n"
688 "} static_descriptor_initializer_$filename$_;\n",
689 // Without.
690 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
691 "void $adddescriptorsname$() {\n"
692 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
693 " &$adddescriptorsname$_impl);\n"
694 "}\n",
695 // Vars.
696 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
697 FilenameIdentifier(file_->name()));
698 }
699
GenerateNamespaceOpeners(io::Printer * printer)700 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
701 if (package_parts_.size() > 0) printer->Print("\n");
702
703 for (int i = 0; i < package_parts_.size(); i++) {
704 printer->Print("namespace $part$ {\n",
705 "part", package_parts_[i]);
706 }
707 }
708
GenerateNamespaceClosers(io::Printer * printer)709 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
710 if (package_parts_.size() > 0) printer->Print("\n");
711
712 for (int i = package_parts_.size() - 1; i >= 0; i--) {
713 printer->Print("} // namespace $part$\n",
714 "part", package_parts_[i]);
715 }
716 }
717
GenerateForwardDeclarations(io::Printer * printer)718 void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
719 ForwardDeclarations decls;
720 for (int i = 0; i < file_->dependency_count(); i++) {
721 FileGenerator dependency(file_->dependency(i), options_);
722 dependency.FillForwardDeclarations(&decls);
723 }
724 FillForwardDeclarations(&decls);
725 decls.Print(printer);
726 }
727
FillForwardDeclarations(ForwardDeclarations * decls)728 void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
729 for (int i = 0; i < file_->public_dependency_count(); i++) {
730 FileGenerator dependency(file_->public_dependency(i), options_);
731 dependency.FillForwardDeclarations(decls);
732 }
733 for (int i = 0; i < package_parts_.size(); i++) {
734 decls = decls->AddOrGetNamespace(package_parts_[i]);
735 }
736 // Generate enum definitions.
737 for (int i = 0; i < file_->message_type_count(); i++) {
738 message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
739 }
740 for (int i = 0; i < file_->enum_type_count(); i++) {
741 enum_generators_[i]->FillForwardDeclaration(&decls->enums());
742 }
743 // Generate forward declarations of classes.
744 for (int i = 0; i < file_->message_type_count(); i++) {
745 message_generators_[i]->FillMessageForwardDeclarations(
746 &decls->classes());
747 }
748 }
749
GenerateTopHeaderGuard(io::Printer * printer,const string & filename_identifier)750 void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
751 const string& filename_identifier) {
752 // Generate top of header.
753 printer->Print(
754 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
755 "// source: $filename$\n"
756 "\n"
757 "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
758 "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
759 "\n"
760 "#include <string>\n",
761 "filename", file_->name(), "filename_identifier", filename_identifier);
762 printer->Print("\n");
763 }
764
GenerateBottomHeaderGuard(io::Printer * printer,const string & filename_identifier)765 void FileGenerator::GenerateBottomHeaderGuard(
766 io::Printer* printer, const string& filename_identifier) {
767 printer->Print(
768 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
769 "filename_identifier", filename_identifier);
770 }
771
GenerateLibraryIncludes(io::Printer * printer)772 void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
773
774 printer->Print(
775 "#include <google/protobuf/stubs/common.h>\n"
776 "\n");
777
778 // Verify the protobuf library header version is compatible with the protoc
779 // version before going any further.
780 printer->Print(
781 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
782 "#error This file was generated by a newer version of protoc which is\n"
783 "#error incompatible with your Protocol Buffer headers. Please update\n"
784 "#error your headers.\n"
785 "#endif\n"
786 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
787 "#error This file was generated by an older version of protoc which is\n"
788 "#error incompatible with your Protocol Buffer headers. Please\n"
789 "#error regenerate this file with a newer version of protoc.\n"
790 "#endif\n"
791 "\n",
792 "min_header_version",
793 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
794 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
795
796 // OK, it's now safe to #include other files.
797 printer->Print(
798 "#include <google/protobuf/arena.h>\n"
799 "#include <google/protobuf/arenastring.h>\n"
800 "#include <google/protobuf/generated_message_util.h>\n");
801 if (UseUnknownFieldSet(file_, options_)) {
802 printer->Print(
803 "#include <google/protobuf/metadata.h>\n");
804 }
805 if (file_->message_type_count() > 0) {
806 if (HasDescriptorMethods(file_, options_)) {
807 printer->Print(
808 "#include <google/protobuf/message.h>\n");
809 } else {
810 printer->Print(
811 "#include <google/protobuf/message_lite.h>\n");
812 }
813 }
814 printer->Print(
815 "#include <google/protobuf/repeated_field.h>\n"
816 "#include <google/protobuf/extension_set.h>\n");
817 if (HasMapFields(file_)) {
818 printer->Print(
819 "#include <google/protobuf/map.h>\n");
820 if (HasDescriptorMethods(file_, options_)) {
821 printer->Print(
822 "#include <google/protobuf/map_field_inl.h>\n");
823 } else {
824 printer->Print(
825 "#include <google/protobuf/map_field_lite.h>\n");
826 }
827 }
828
829 if (HasEnumDefinitions(file_)) {
830 if (HasDescriptorMethods(file_, options_)) {
831 printer->Print(
832 "#include <google/protobuf/generated_enum_reflection.h>\n");
833 } else {
834 printer->Print(
835 "#include <google/protobuf/generated_enum_util.h>\n");
836 }
837 }
838
839 if (HasGenericServices(file_, options_)) {
840 printer->Print(
841 "#include <google/protobuf/service.h>\n");
842 }
843
844 if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
845 printer->Print(
846 "#include <google/protobuf/unknown_field_set.h>\n");
847 }
848
849
850 if (IsAnyMessage(file_)) {
851 printer->Print(
852 "#include <google/protobuf/any.h>\n");
853 }
854 }
855
GenerateMetadataPragma(io::Printer * printer,const string & info_path)856 void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
857 const string& info_path) {
858 if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
859 !options_.annotation_guard_name.empty()) {
860 printer->Print(
861 "#ifdef $guard$\n"
862 "#pragma $pragma$ \"$info_path$\"\n"
863 "#endif // $guard$\n",
864 "guard", options_.annotation_guard_name, "pragma",
865 options_.annotation_pragma_name, "info_path", info_path);
866 }
867 }
868
GenerateDependencyIncludes(io::Printer * printer)869 void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
870 set<string> public_import_names;
871 for (int i = 0; i < file_->public_dependency_count(); i++) {
872 public_import_names.insert(file_->public_dependency(i)->name());
873 }
874
875 for (int i = 0; i < file_->dependency_count(); i++) {
876 const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
877 const string& name = file_->dependency(i)->name();
878 bool public_import = (public_import_names.count(name) != 0);
879
880
881 printer->Print(
882 "#include $left$$dependency$.pb.h$right$$iwyu$\n",
883 "dependency", StripProto(name),
884 "iwyu", (public_import) ? " // IWYU pragma: export" : "",
885 "left", use_system_include ? "<" : "\"",
886 "right", use_system_include ? ">" : "\"");
887 }
888 }
889
GenerateGlobalStateFunctionDeclarations(io::Printer * printer)890 void FileGenerator::GenerateGlobalStateFunctionDeclarations(
891 io::Printer* printer) {
892 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
893 // functions, so that we can declare them to be friends of each class.
894 printer->Print(
895 "\n"
896 "// Internal implementation detail -- do not call these.\n"
897 "void $dllexport_decl$$adddescriptorsname$();\n",
898 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
899 "dllexport_decl",
900 options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
901
902 printer->Print(
903 // Note that we don't put dllexport_decl on these because they are only
904 // called by the .pb.cc file in which they are defined.
905 "void $assigndescriptorsname$();\n"
906 "void $shutdownfilename$();\n"
907 "\n",
908 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
909 "shutdownfilename", GlobalShutdownFileName(file_->name()));
910 }
911
GenerateMessageForwardDeclarations(io::Printer * printer)912 void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
913 map<string, const Descriptor*> classes;
914 for (int i = 0; i < file_->message_type_count(); i++) {
915 message_generators_[i]->FillMessageForwardDeclarations(&classes);
916 }
917 for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
918 end = classes.end();
919 it != end; ++it) {
920 printer->Print("class $classname$;\n", "classname", it->first);
921 printer->Annotate("classname", it->second);
922 }
923 }
924
GenerateMessageDefinitions(io::Printer * printer)925 void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
926 // Generate class definitions.
927 for (int i = 0; i < file_->message_type_count(); i++) {
928 if (i > 0) {
929 printer->Print("\n");
930 printer->Print(kThinSeparator);
931 printer->Print("\n");
932 }
933 message_generators_[i]->GenerateClassDefinition(printer);
934 }
935 }
936
GenerateEnumDefinitions(io::Printer * printer)937 void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
938 // Generate enum definitions.
939 for (int i = 0; i < file_->message_type_count(); i++) {
940 message_generators_[i]->GenerateEnumDefinitions(printer);
941 }
942 for (int i = 0; i < file_->enum_type_count(); i++) {
943 enum_generators_[i]->GenerateDefinition(printer);
944 }
945 }
946
GenerateServiceDefinitions(io::Printer * printer)947 void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
948 if (HasGenericServices(file_, options_)) {
949 // Generate service definitions.
950 for (int i = 0; i < file_->service_count(); i++) {
951 if (i > 0) {
952 printer->Print("\n");
953 printer->Print(kThinSeparator);
954 printer->Print("\n");
955 }
956 service_generators_[i]->GenerateDeclarations(printer);
957 }
958
959 printer->Print("\n");
960 printer->Print(kThickSeparator);
961 printer->Print("\n");
962 }
963 }
964
GenerateExtensionIdentifiers(io::Printer * printer)965 void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
966 // Declare extension identifiers.
967 for (int i = 0; i < file_->extension_count(); i++) {
968 extension_generators_[i]->GenerateDeclaration(printer);
969 }
970 }
971
GenerateInlineFunctionDefinitions(io::Printer * printer)972 void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
973 // An aside about inline functions in .proto.h mode:
974 //
975 // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
976 // moving much of the inline functions to the .pb.cc file, which can be a
977 // significant performance benefit for compilation time, at the expense
978 // of non-inline function calls.
979 //
980 // However, in .proto.h mode, the definition of the internal dependent
981 // base class must remain in the header, and can never be out-lined. The
982 // dependent base class also needs access to has-bit manipuation
983 // functions, so the has-bit functions must be unconditionally inlined in
984 // proto_h mode.
985 //
986 // This gives us three flavors of functions:
987 //
988 // 1. Functions on the message not used by the internal dependent base
989 // class: in .proto.h mode, only some functions are defined on the
990 // message class; others are defined on the dependent base class.
991 // These are guarded and can be out-lined. These are generated by
992 // GenerateInlineMethods, and include has_* bit functions in
993 // non-proto_h mode.
994 //
995 // 2. Functions on the internal dependent base class: these functions
996 // are dependent on a template parameter, so they always need to
997 // remain in the header.
998 //
999 // 3. Functions on the message that are used by the dependent base: the
1000 // dependent base class down casts itself to the message
1001 // implementation class to access these functions (the has_* bit
1002 // manipulation functions). Unlike #1, these functions must
1003 // unconditionally remain in the header. These are emitted by
1004 // GenerateDependentInlineMethods, even though they are not actually
1005 // dependent.
1006
1007 printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1008 // Generate class inline methods.
1009 for (int i = 0; i < file_->message_type_count(); i++) {
1010 if (i > 0) {
1011 printer->Print(kThinSeparator);
1012 printer->Print("\n");
1013 }
1014 message_generators_[i]->GenerateInlineMethods(printer,
1015 /* is_inline = */ true);
1016 }
1017 printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1018
1019 for (int i = 0; i < file_->message_type_count(); i++) {
1020 if (i > 0) {
1021 printer->Print(kThinSeparator);
1022 printer->Print("\n");
1023 }
1024 // Methods of the dependent base class must always be inline in the header.
1025 message_generators_[i]->GenerateDependentInlineMethods(printer);
1026 }
1027 }
1028
GenerateProto2NamespaceEnumSpecializations(io::Printer * printer)1029 void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
1030 io::Printer* printer) {
1031 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
1032 if (HasEnumDefinitions(file_)) {
1033 // The SWIG conditional is to avoid a null-pointer dereference
1034 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
1035 // namespace X { void Y<Z::W>(); }
1036 // which appears in GetEnumDescriptor() specializations.
1037 printer->Print(
1038 "\n"
1039 "#ifndef SWIG\n"
1040 "namespace google {\nnamespace protobuf {\n"
1041 "\n");
1042 for (int i = 0; i < file_->message_type_count(); i++) {
1043 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1044 }
1045 for (int i = 0; i < file_->enum_type_count(); i++) {
1046 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1047 }
1048 printer->Print(
1049 "\n"
1050 "} // namespace protobuf\n} // namespace google\n"
1051 "#endif // SWIG\n");
1052 }
1053 }
1054
1055 } // namespace cpp
1056 } // namespace compiler
1057 } // namespace protobuf
1058 } // namespace google
1059