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 (at) 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 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 91 FileGenerator::~FileGenerator() {} 92 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 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 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 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 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