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 <memory>
37 #include <set>
38
39 #include <google/protobuf/compiler/cpp/cpp_enum.h>
40 #include <google/protobuf/compiler/cpp/cpp_service.h>
41 #include <google/protobuf/compiler/cpp/cpp_extension.h>
42 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
43 #include <google/protobuf/compiler/cpp/cpp_message.h>
44 #include <google/protobuf/compiler/cpp/cpp_field.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/descriptor.pb.h>
47 #include <google/protobuf/stubs/strutil.h>
48
49 namespace google {
50 namespace protobuf {
51 namespace compiler {
52 namespace cpp {
53
54 // ===================================================================
55
FileGenerator(const FileDescriptor * file,const Options & options)56 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
57 : file_(file),
58 message_generators_(
59 new scoped_ptr<MessageGenerator>[file->message_type_count()]),
60 enum_generators_(
61 new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
62 service_generators_(
63 new scoped_ptr<ServiceGenerator>[file->service_count()]),
64 extension_generators_(
65 new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
66 options_(options) {
67
68 for (int i = 0; i < file->message_type_count(); i++) {
69 message_generators_[i].reset(
70 new MessageGenerator(file->message_type(i), options));
71 }
72
73 for (int i = 0; i < file->enum_type_count(); i++) {
74 enum_generators_[i].reset(
75 new EnumGenerator(file->enum_type(i), options));
76 }
77
78 for (int i = 0; i < file->service_count(); i++) {
79 service_generators_[i].reset(
80 new ServiceGenerator(file->service(i), options));
81 }
82
83 for (int i = 0; i < file->extension_count(); i++) {
84 extension_generators_[i].reset(
85 new ExtensionGenerator(file->extension(i), options));
86 }
87
88 SplitStringUsing(file_->package(), ".", &package_parts_);
89 }
90
~FileGenerator()91 FileGenerator::~FileGenerator() {}
92
GenerateHeader(io::Printer * printer)93 void FileGenerator::GenerateHeader(io::Printer* printer) {
94 string filename_identifier = FilenameIdentifier(file_->name());
95
96 // Generate top of header.
97 printer->Print(
98 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
99 "// source: $filename$\n"
100 "\n"
101 "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
102 "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
103 "\n"
104 "#include <string>\n"
105 "\n",
106 "filename", file_->name(),
107 "filename_identifier", filename_identifier);
108
109
110 printer->Print(
111 "#include <google/protobuf/stubs/common.h>\n"
112 "\n");
113
114 // Verify the protobuf library header version is compatible with the protoc
115 // version before going any further.
116 printer->Print(
117 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
118 "#error This file was generated by a newer version of protoc which is\n"
119 "#error incompatible with your Protocol Buffer headers. Please update\n"
120 "#error your headers.\n"
121 "#endif\n"
122 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
123 "#error This file was generated by an older version of protoc which is\n"
124 "#error incompatible with your Protocol Buffer headers. Please\n"
125 "#error regenerate this file with a newer version of protoc.\n"
126 "#endif\n"
127 "\n",
128 "min_header_version",
129 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
130 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
131
132 // OK, it's now safe to #include other files.
133 printer->Print(
134 "#include <google/protobuf/generated_message_util.h>\n");
135 if (file_->message_type_count() > 0) {
136 if (HasDescriptorMethods(file_)) {
137 printer->Print(
138 "#include <google/protobuf/message.h>\n");
139 } else {
140 printer->Print(
141 "#include <google/protobuf/message_lite.h>\n");
142 }
143 }
144 printer->Print(
145 "#include <google/protobuf/repeated_field.h>\n"
146 "#include <google/protobuf/extension_set.h>\n");
147
148 if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
149 printer->Print(
150 "#include <google/protobuf/generated_enum_reflection.h>\n");
151 }
152
153 if (HasGenericServices(file_)) {
154 printer->Print(
155 "#include <google/protobuf/service.h>\n");
156 }
157
158 if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
159 printer->Print(
160 "#include <google/protobuf/unknown_field_set.h>\n");
161 }
162
163
164 set<string> public_import_names;
165 for (int i = 0; i < file_->public_dependency_count(); i++) {
166 public_import_names.insert(file_->public_dependency(i)->name());
167 }
168
169 for (int i = 0; i < file_->dependency_count(); i++) {
170 const string& name = file_->dependency(i)->name();
171 bool public_import = (public_import_names.count(name) != 0);
172
173
174 printer->Print(
175 "#include \"$dependency$.pb.h\"$iwyu$\n",
176 "dependency", StripProto(name),
177 "iwyu", (public_import) ? " // IWYU pragma: export" : "");
178 }
179
180 printer->Print(
181 "// @@protoc_insertion_point(includes)\n");
182
183
184 // Open namespace.
185 GenerateNamespaceOpeners(printer);
186
187 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
188 // functions, so that we can declare them to be friends of each class.
189 printer->Print(
190 "\n"
191 "// Internal implementation detail -- do not call these.\n"
192 "void $dllexport_decl$ $adddescriptorsname$();\n",
193 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
194 "dllexport_decl", options_.dllexport_decl);
195
196 printer->Print(
197 // Note that we don't put dllexport_decl on these because they are only
198 // called by the .pb.cc file in which they are defined.
199 "void $assigndescriptorsname$();\n"
200 "void $shutdownfilename$();\n"
201 "\n",
202 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
203 "shutdownfilename", GlobalShutdownFileName(file_->name()));
204
205 // Generate forward declarations of classes.
206 for (int i = 0; i < file_->message_type_count(); i++) {
207 message_generators_[i]->GenerateForwardDeclaration(printer);
208 }
209
210 printer->Print("\n");
211
212 // Generate enum definitions.
213 for (int i = 0; i < file_->message_type_count(); i++) {
214 message_generators_[i]->GenerateEnumDefinitions(printer);
215 }
216 for (int i = 0; i < file_->enum_type_count(); i++) {
217 enum_generators_[i]->GenerateDefinition(printer);
218 }
219
220 printer->Print(kThickSeparator);
221 printer->Print("\n");
222
223 // Generate class definitions.
224 for (int i = 0; i < file_->message_type_count(); i++) {
225 if (i > 0) {
226 printer->Print("\n");
227 printer->Print(kThinSeparator);
228 printer->Print("\n");
229 }
230 message_generators_[i]->GenerateClassDefinition(printer);
231 }
232
233 printer->Print("\n");
234 printer->Print(kThickSeparator);
235 printer->Print("\n");
236
237 if (HasGenericServices(file_)) {
238 // Generate service definitions.
239 for (int i = 0; i < file_->service_count(); i++) {
240 if (i > 0) {
241 printer->Print("\n");
242 printer->Print(kThinSeparator);
243 printer->Print("\n");
244 }
245 service_generators_[i]->GenerateDeclarations(printer);
246 }
247
248 printer->Print("\n");
249 printer->Print(kThickSeparator);
250 printer->Print("\n");
251 }
252
253 // Declare extension identifiers.
254 for (int i = 0; i < file_->extension_count(); i++) {
255 extension_generators_[i]->GenerateDeclaration(printer);
256 }
257
258 printer->Print("\n");
259 printer->Print(kThickSeparator);
260 printer->Print("\n");
261
262
263 // Generate class inline methods.
264 for (int i = 0; i < file_->message_type_count(); i++) {
265 if (i > 0) {
266 printer->Print(kThinSeparator);
267 printer->Print("\n");
268 }
269 message_generators_[i]->GenerateInlineMethods(printer);
270 }
271
272 printer->Print(
273 "\n"
274 "// @@protoc_insertion_point(namespace_scope)\n");
275
276 // Close up namespace.
277 GenerateNamespaceClosers(printer);
278
279 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
280 if (HasDescriptorMethods(file_)) {
281 // The SWIG conditional is to avoid a null-pointer dereference
282 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
283 // namespace X { void Y<Z::W>(); }
284 // which appears in GetEnumDescriptor() specializations.
285 printer->Print(
286 "\n"
287 "#ifndef SWIG\n"
288 "namespace google {\nnamespace protobuf {\n"
289 "\n");
290 for (int i = 0; i < file_->message_type_count(); i++) {
291 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
292 }
293 for (int i = 0; i < file_->enum_type_count(); i++) {
294 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
295 }
296 printer->Print(
297 "\n"
298 "} // namespace google\n} // namespace protobuf\n"
299 "#endif // SWIG\n");
300 }
301
302 printer->Print(
303 "\n"
304 "// @@protoc_insertion_point(global_scope)\n"
305 "\n");
306
307 printer->Print(
308 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
309 "filename_identifier", filename_identifier);
310 }
311
GenerateSource(io::Printer * printer)312 void FileGenerator::GenerateSource(io::Printer* printer) {
313 printer->Print(
314 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
315 "// source: $filename$\n"
316 "\n"
317
318 // The generated code calls accessors that might be deprecated. We don't
319 // want the compiler to warn in generated code.
320 "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
321 "#include \"$basename$.pb.h\"\n"
322 "\n"
323 "#include <algorithm>\n" // for swap()
324 "\n"
325 "#include <google/protobuf/stubs/common.h>\n"
326 "#include <google/protobuf/stubs/once.h>\n"
327 "#include <google/protobuf/io/coded_stream.h>\n"
328 "#include <google/protobuf/wire_format_lite_inl.h>\n",
329 "filename", file_->name(),
330 "basename", StripProto(file_->name()));
331
332 // Unknown fields implementation in lite mode uses StringOutputStream
333 if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
334 printer->Print(
335 "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
336 }
337
338 if (HasDescriptorMethods(file_)) {
339 printer->Print(
340 "#include <google/protobuf/descriptor.h>\n"
341 "#include <google/protobuf/generated_message_reflection.h>\n"
342 "#include <google/protobuf/reflection_ops.h>\n"
343 "#include <google/protobuf/wire_format.h>\n");
344 }
345
346 printer->Print(
347 "// @@protoc_insertion_point(includes)\n");
348
349 GenerateNamespaceOpeners(printer);
350
351 if (HasDescriptorMethods(file_)) {
352 printer->Print(
353 "\n"
354 "namespace {\n"
355 "\n");
356 for (int i = 0; i < file_->message_type_count(); i++) {
357 message_generators_[i]->GenerateDescriptorDeclarations(printer);
358 }
359 for (int i = 0; i < file_->enum_type_count(); i++) {
360 printer->Print(
361 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
362 "name", ClassName(file_->enum_type(i), false));
363 }
364
365 if (HasGenericServices(file_)) {
366 for (int i = 0; i < file_->service_count(); i++) {
367 printer->Print(
368 "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
369 "name", file_->service(i)->name());
370 }
371 }
372
373 printer->Print(
374 "\n"
375 "} // namespace\n"
376 "\n");
377 }
378
379 // Define our externally-visible BuildDescriptors() function. (For the lite
380 // library, all this does is initialize default instances.)
381 GenerateBuildDescriptors(printer);
382
383 // Generate enums.
384 for (int i = 0; i < file_->enum_type_count(); i++) {
385 enum_generators_[i]->GenerateMethods(printer);
386 }
387
388 // Generate classes.
389 for (int i = 0; i < file_->message_type_count(); i++) {
390 printer->Print("\n");
391 printer->Print(kThickSeparator);
392 printer->Print("\n");
393 message_generators_[i]->GenerateClassMethods(printer);
394 }
395
396 if (HasGenericServices(file_)) {
397 // Generate services.
398 for (int i = 0; i < file_->service_count(); i++) {
399 if (i == 0) printer->Print("\n");
400 printer->Print(kThickSeparator);
401 printer->Print("\n");
402 service_generators_[i]->GenerateImplementation(printer);
403 }
404 }
405
406 // Define extensions.
407 for (int i = 0; i < file_->extension_count(); i++) {
408 extension_generators_[i]->GenerateDefinition(printer);
409 }
410
411 printer->Print(
412 "\n"
413 "// @@protoc_insertion_point(namespace_scope)\n");
414
415 GenerateNamespaceClosers(printer);
416
417 printer->Print(
418 "\n"
419 "// @@protoc_insertion_point(global_scope)\n");
420 }
421
GenerateBuildDescriptors(io::Printer * printer)422 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
423 // AddDescriptors() is a file-level procedure which adds the encoded
424 // FileDescriptorProto for this .proto file to the global DescriptorPool for
425 // generated files (DescriptorPool::generated_pool()). It either runs at
426 // static initialization time (by default) or when default_instance() is
427 // called for the first time (in LITE_RUNTIME mode with
428 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
429 // constructs default instances and registers extensions.
430 //
431 // Its sibling, AssignDescriptors(), actually pulls the compiled
432 // FileDescriptor from the DescriptorPool and uses it to populate all of
433 // the global variables which store pointers to the descriptor objects.
434 // It also constructs the reflection objects. It is called the first time
435 // anyone calls descriptor() or GetReflection() on one of the types defined
436 // in the file.
437
438 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
439 // and we only use AddDescriptors() to allocate default instances.
440 if (HasDescriptorMethods(file_)) {
441 printer->Print(
442 "\n"
443 "void $assigndescriptorsname$() {\n",
444 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
445 printer->Indent();
446
447 // Make sure the file has found its way into the pool. If a descriptor
448 // is requested *during* static init then AddDescriptors() may not have
449 // been called yet, so we call it manually. Note that it's fine if
450 // AddDescriptors() is called multiple times.
451 printer->Print(
452 "$adddescriptorsname$();\n",
453 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
454
455 // Get the file's descriptor from the pool.
456 printer->Print(
457 "const ::google::protobuf::FileDescriptor* file =\n"
458 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
459 " \"$filename$\");\n"
460 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
461 // being unused when compiling an empty .proto file.
462 "GOOGLE_CHECK(file != NULL);\n",
463 "filename", file_->name());
464
465 // Go through all the stuff defined in this file and generated code to
466 // assign the global descriptor pointers based on the file descriptor.
467 for (int i = 0; i < file_->message_type_count(); i++) {
468 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
469 }
470 for (int i = 0; i < file_->enum_type_count(); i++) {
471 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
472 }
473 if (HasGenericServices(file_)) {
474 for (int i = 0; i < file_->service_count(); i++) {
475 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
476 }
477 }
478
479 printer->Outdent();
480 printer->Print(
481 "}\n"
482 "\n");
483
484 // ---------------------------------------------------------------
485
486 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
487 // AssignDescriptors(). All later times, waits for the first call to
488 // complete and then returns.
489 printer->Print(
490 "namespace {\n"
491 "\n"
492 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
493 "inline void protobuf_AssignDescriptorsOnce() {\n"
494 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
495 " &$assigndescriptorsname$);\n"
496 "}\n"
497 "\n",
498 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
499
500 // protobuf_RegisterTypes(): Calls
501 // MessageFactory::InternalRegisterGeneratedType() for each message type.
502 printer->Print(
503 "void protobuf_RegisterTypes(const ::std::string&) {\n"
504 " protobuf_AssignDescriptorsOnce();\n");
505 printer->Indent();
506
507 for (int i = 0; i < file_->message_type_count(); i++) {
508 message_generators_[i]->GenerateTypeRegistrations(printer);
509 }
510
511 printer->Outdent();
512 printer->Print(
513 "}\n"
514 "\n"
515 "} // namespace\n");
516 }
517
518 // -----------------------------------------------------------------
519
520 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
521 printer->Print(
522 "\n"
523 "void $shutdownfilename$() {\n",
524 "shutdownfilename", GlobalShutdownFileName(file_->name()));
525 printer->Indent();
526
527 for (int i = 0; i < file_->message_type_count(); i++) {
528 message_generators_[i]->GenerateShutdownCode(printer);
529 }
530
531 printer->Outdent();
532 printer->Print(
533 "}\n\n");
534
535 // -----------------------------------------------------------------
536
537 // Now generate the AddDescriptors() function.
538 PrintHandlingOptionalStaticInitializers(
539 file_, printer,
540 // With static initializers.
541 // Note that we don't need any special synchronization in the following code
542 // because it is called at static init time before any threads exist.
543 "void $adddescriptorsname$() {\n"
544 " static bool already_here = false;\n"
545 " if (already_here) return;\n"
546 " already_here = true;\n"
547 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
548 "\n",
549 // Without.
550 "void $adddescriptorsname$_impl() {\n"
551 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
552 "\n",
553 // Vars.
554 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
555
556 printer->Indent();
557
558 // Call the AddDescriptors() methods for all of our dependencies, to make
559 // sure they get added first.
560 for (int i = 0; i < file_->dependency_count(); i++) {
561 const FileDescriptor* dependency = file_->dependency(i);
562 // Print the namespace prefix for the dependency.
563 string add_desc_name = QualifiedFileLevelSymbol(
564 dependency->package(), GlobalAddDescriptorsName(dependency->name()));
565 // Call its AddDescriptors function.
566 printer->Print(
567 "$name$();\n",
568 "name", add_desc_name);
569 }
570
571 if (HasDescriptorMethods(file_)) {
572 // Embed the descriptor. We simply serialize the entire FileDescriptorProto
573 // and embed it as a string literal, which is parsed and built into real
574 // descriptors at initialization time.
575 FileDescriptorProto file_proto;
576 file_->CopyTo(&file_proto);
577 string file_data;
578 file_proto.SerializeToString(&file_data);
579
580 printer->Print(
581 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
582
583 // Only write 40 bytes per line.
584 static const int kBytesPerLine = 40;
585 for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
586 printer->Print("\n \"$data$\"",
587 "data",
588 EscapeTrigraphs(
589 CEscape(file_data.substr(i, kBytesPerLine))));
590 }
591 printer->Print(
592 ", $size$);\n",
593 "size", SimpleItoa(file_data.size()));
594
595 // Call MessageFactory::InternalRegisterGeneratedFile().
596 printer->Print(
597 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
598 " \"$filename$\", &protobuf_RegisterTypes);\n",
599 "filename", file_->name());
600 }
601
602 // Allocate and initialize default instances. This can't be done lazily
603 // since default instances are returned by simple accessors and are used with
604 // extensions. Speaking of which, we also register extensions at this time.
605 for (int i = 0; i < file_->message_type_count(); i++) {
606 message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
607 }
608 for (int i = 0; i < file_->extension_count(); i++) {
609 extension_generators_[i]->GenerateRegistration(printer);
610 }
611 for (int i = 0; i < file_->message_type_count(); i++) {
612 message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
613 }
614
615 printer->Print(
616 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
617 "shutdownfilename", GlobalShutdownFileName(file_->name()));
618
619 printer->Outdent();
620 printer->Print(
621 "}\n"
622 "\n");
623
624 PrintHandlingOptionalStaticInitializers(
625 file_, printer,
626 // With static initializers.
627 "// Force AddDescriptors() to be called at static initialization time.\n"
628 "struct StaticDescriptorInitializer_$filename$ {\n"
629 " StaticDescriptorInitializer_$filename$() {\n"
630 " $adddescriptorsname$();\n"
631 " }\n"
632 "} static_descriptor_initializer_$filename$_;\n",
633 // Without.
634 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
635 "void $adddescriptorsname$() {\n"
636 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
637 " &$adddescriptorsname$_impl);\n"
638 "}\n",
639 // Vars.
640 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
641 "filename", FilenameIdentifier(file_->name()));
642 }
643
GenerateNamespaceOpeners(io::Printer * printer)644 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
645 if (package_parts_.size() > 0) printer->Print("\n");
646
647 for (int i = 0; i < package_parts_.size(); i++) {
648 printer->Print("namespace $part$ {\n",
649 "part", package_parts_[i]);
650 }
651 }
652
GenerateNamespaceClosers(io::Printer * printer)653 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
654 if (package_parts_.size() > 0) printer->Print("\n");
655
656 for (int i = package_parts_.size() - 1; i >= 0; i--) {
657 printer->Print("} // namespace $part$\n",
658 "part", package_parts_[i]);
659 }
660 }
661
662 } // namespace cpp
663 } // namespace compiler
664 } // namespace protobuf
665 } // namespace google
666