1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
35 #include <google/protobuf/compiler/cpp/cpp_file.h>
36 #include <google/protobuf/compiler/cpp/cpp_enum.h>
37 #include <google/protobuf/compiler/cpp/cpp_service.h>
38 #include <google/protobuf/compiler/cpp/cpp_extension.h>
39 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
40 #include <google/protobuf/compiler/cpp/cpp_message.h>
41 #include <google/protobuf/compiler/cpp/cpp_field.h>
42 #include <google/protobuf/io/printer.h>
43 #include <google/protobuf/descriptor.pb.h>
44 #include <google/protobuf/stubs/strutil.h>
51 // ===================================================================
53 FileGenerator::FileGenerator(const FileDescriptor* file,
54 const Options& options)
57 new scoped_ptr<MessageGenerator>[file->message_type_count()]),
59 new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
61 new scoped_ptr<ServiceGenerator>[file->service_count()]),
62 extension_generators_(
63 new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
66 for (int i = 0; i < file->message_type_count(); i++) {
67 message_generators_[i].reset(
68 new MessageGenerator(file->message_type(i), options));
71 for (int i = 0; i < file->enum_type_count(); i++) {
72 enum_generators_[i].reset(
73 new EnumGenerator(file->enum_type(i), options));
76 for (int i = 0; i < file->service_count(); i++) {
77 service_generators_[i].reset(
78 new ServiceGenerator(file->service(i), options));
81 for (int i = 0; i < file->extension_count(); i++) {
82 extension_generators_[i].reset(
83 new ExtensionGenerator(file->extension(i), options));
86 SplitStringUsing(file_->package(), ".", &package_parts_);
89 FileGenerator::~FileGenerator() {}
91 void FileGenerator::GenerateHeader(io::Printer* printer) {
92 string filename_identifier = FilenameIdentifier(file_->name());
94 // Generate top of header.
96 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
97 "// source: $filename$\n"
99 "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
100 "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
102 "#include <string>\n"
104 "filename", file_->name(),
105 "filename_identifier", filename_identifier);
109 "#include <google/protobuf/stubs/common.h>\n"
112 // Verify the protobuf library header version is compatible with the protoc
113 // version before going any further.
115 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
116 "#error This file was generated by a newer version of protoc which is\n"
117 "#error incompatible with your Protocol Buffer headers. Please update\n"
118 "#error your headers.\n"
120 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
121 "#error This file was generated by an older version of protoc which is\n"
122 "#error incompatible with your Protocol Buffer headers. Please\n"
123 "#error regenerate this file with a newer version of protoc.\n"
126 "min_header_version",
127 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
128 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
130 // OK, it's now safe to #include other files.
132 "#include <google/protobuf/generated_message_util.h>\n");
133 if (file_->message_type_count() > 0) {
134 if (HasDescriptorMethods(file_)) {
136 "#include <google/protobuf/message.h>\n");
139 "#include <google/protobuf/message_lite.h>\n");
143 "#include <google/protobuf/repeated_field.h>\n"
144 "#include <google/protobuf/extension_set.h>\n");
146 if (HasUnknownFields(file_)) {
148 "#include <google/protobuf/unknown_field_set.h>\n");
151 if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
153 "#include <google/protobuf/generated_enum_reflection.h>\n");
156 if (HasGenericServices(file_)) {
158 "#include <google/protobuf/service.h>\n");
161 if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
163 "#include <google/protobuf/unknown_field_set.h>\n");
167 for (int i = 0; i < file_->dependency_count(); i++) {
169 "#include \"$dependency$.pb.h\"\n",
170 "dependency", StripProto(file_->dependency(i)->name()));
175 "// @@protoc_insertion_point(includes)\n");
179 GenerateNamespaceOpeners(printer);
181 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
182 // functions, so that we can declare them to be friends of each class.
185 "// Internal implementation detail -- do not call these.\n"
186 "void $dllexport_decl$ $adddescriptorsname$();\n",
187 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
188 "dllexport_decl", options_.dllexport_decl);
191 // Note that we don't put dllexport_decl on these because they are only
192 // called by the .pb.cc file in which they are defined.
193 "void $assigndescriptorsname$();\n"
194 "void $shutdownfilename$();\n"
196 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
197 "shutdownfilename", GlobalShutdownFileName(file_->name()));
199 // Generate forward declarations of classes.
200 for (int i = 0; i < file_->message_type_count(); i++) {
201 message_generators_[i]->GenerateForwardDeclaration(printer);
204 printer->Print("\n");
206 // Generate enum definitions.
207 for (int i = 0; i < file_->message_type_count(); i++) {
208 message_generators_[i]->GenerateEnumDefinitions(printer);
210 for (int i = 0; i < file_->enum_type_count(); i++) {
211 enum_generators_[i]->GenerateDefinition(printer);
214 printer->Print(kThickSeparator);
215 printer->Print("\n");
217 // Generate class definitions.
218 for (int i = 0; i < file_->message_type_count(); i++) {
220 printer->Print("\n");
221 printer->Print(kThinSeparator);
222 printer->Print("\n");
224 message_generators_[i]->GenerateClassDefinition(printer);
227 printer->Print("\n");
228 printer->Print(kThickSeparator);
229 printer->Print("\n");
231 if (HasGenericServices(file_)) {
232 // Generate service definitions.
233 for (int i = 0; i < file_->service_count(); i++) {
235 printer->Print("\n");
236 printer->Print(kThinSeparator);
237 printer->Print("\n");
239 service_generators_[i]->GenerateDeclarations(printer);
242 printer->Print("\n");
243 printer->Print(kThickSeparator);
244 printer->Print("\n");
247 // Declare extension identifiers.
248 for (int i = 0; i < file_->extension_count(); i++) {
249 extension_generators_[i]->GenerateDeclaration(printer);
252 printer->Print("\n");
253 printer->Print(kThickSeparator);
254 printer->Print("\n");
256 // Generate class inline methods.
257 for (int i = 0; i < file_->message_type_count(); i++) {
259 printer->Print(kThinSeparator);
260 printer->Print("\n");
262 message_generators_[i]->GenerateInlineMethods(printer);
267 "// @@protoc_insertion_point(namespace_scope)\n");
269 // Close up namespace.
270 GenerateNamespaceClosers(printer);
272 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
273 if (HasDescriptorMethods(file_)) {
274 // The SWIG conditional is to avoid a null-pointer dereference
275 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
276 // namespace X { void Y<Z::W>(); }
277 // which appears in GetEnumDescriptor() specializations.
281 "namespace google {\nnamespace protobuf {\n"
283 for (int i = 0; i < file_->message_type_count(); i++) {
284 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
286 for (int i = 0; i < file_->enum_type_count(); i++) {
287 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
291 "} // namespace google\n} // namespace protobuf\n"
297 "// @@protoc_insertion_point(global_scope)\n"
301 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
302 "filename_identifier", filename_identifier);
305 void FileGenerator::GenerateSource(io::Printer* printer) {
307 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
308 "// source: $filename$\n"
311 // The generated code calls accessors that might be deprecated. We don't
312 // want the compiler to warn in generated code.
313 "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
314 "#include \"$basename$.pb.h\"\n"
316 "#include <algorithm>\n" // for swap()
318 "#include <google/protobuf/stubs/common.h>\n"
319 "#include <google/protobuf/stubs/once.h>\n"
320 "#include <google/protobuf/io/coded_stream.h>\n"
321 "#include <google/protobuf/wire_format_lite_inl.h>\n",
322 "filename", file_->name(),
323 "basename", StripProto(file_->name()));
325 if (HasDescriptorMethods(file_)) {
327 "#include <google/protobuf/descriptor.h>\n"
328 "#include <google/protobuf/generated_message_reflection.h>\n"
329 "#include <google/protobuf/reflection_ops.h>\n"
330 "#include <google/protobuf/wire_format.h>\n");
334 "// @@protoc_insertion_point(includes)\n");
336 GenerateNamespaceOpeners(printer);
338 if (HasDescriptorMethods(file_)) {
343 for (int i = 0; i < file_->message_type_count(); i++) {
344 message_generators_[i]->GenerateDescriptorDeclarations(printer);
346 for (int i = 0; i < file_->enum_type_count(); i++) {
348 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
349 "name", ClassName(file_->enum_type(i), false));
352 if (HasGenericServices(file_)) {
353 for (int i = 0; i < file_->service_count(); i++) {
355 "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
356 "name", file_->service(i)->name());
366 // Define our externally-visible BuildDescriptors() function. (For the lite
367 // library, all this does is initialize default instances.)
368 GenerateBuildDescriptors(printer);
371 for (int i = 0; i < file_->enum_type_count(); i++) {
372 enum_generators_[i]->GenerateMethods(printer);
376 for (int i = 0; i < file_->message_type_count(); i++) {
377 printer->Print("\n");
378 printer->Print(kThickSeparator);
379 printer->Print("\n");
380 message_generators_[i]->GenerateClassMethods(printer);
383 if (HasGenericServices(file_)) {
384 // Generate services.
385 for (int i = 0; i < file_->service_count(); i++) {
386 if (i == 0) printer->Print("\n");
387 printer->Print(kThickSeparator);
388 printer->Print("\n");
389 service_generators_[i]->GenerateImplementation(printer);
393 // Define extensions.
394 for (int i = 0; i < file_->extension_count(); i++) {
395 extension_generators_[i]->GenerateDefinition(printer);
400 "// @@protoc_insertion_point(namespace_scope)\n");
402 GenerateNamespaceClosers(printer);
406 "// @@protoc_insertion_point(global_scope)\n");
409 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
410 // AddDescriptors() is a file-level procedure which adds the encoded
411 // FileDescriptorProto for this .proto file to the global DescriptorPool for
412 // generated files (DescriptorPool::generated_pool()). It either runs at
413 // static initialization time (by default) or when default_instance() is
414 // called for the first time (in LITE_RUNTIME mode with
415 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
416 // constructs default instances and registers extensions.
418 // Its sibling, AssignDescriptors(), actually pulls the compiled
419 // FileDescriptor from the DescriptorPool and uses it to populate all of
420 // the global variables which store pointers to the descriptor objects.
421 // It also constructs the reflection objects. It is called the first time
422 // anyone calls descriptor() or GetReflection() on one of the types defined
425 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
426 // and we only use AddDescriptors() to allocate default instances.
427 if (HasDescriptorMethods(file_)) {
430 "void $assigndescriptorsname$() {\n",
431 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
434 // Make sure the file has found its way into the pool. If a descriptor
435 // is requested *during* static init then AddDescriptors() may not have
436 // been called yet, so we call it manually. Note that it's fine if
437 // AddDescriptors() is called multiple times.
439 "$adddescriptorsname$();\n",
440 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
442 // Get the file's descriptor from the pool.
444 "const ::google::protobuf::FileDescriptor* file =\n"
445 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
446 " \"$filename$\");\n"
447 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
448 // being unused when compiling an empty .proto file.
449 "GOOGLE_CHECK(file != NULL);\n",
450 "filename", file_->name());
452 // Go through all the stuff defined in this file and generated code to
453 // assign the global descriptor pointers based on the file descriptor.
454 for (int i = 0; i < file_->message_type_count(); i++) {
455 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
457 for (int i = 0; i < file_->enum_type_count(); i++) {
458 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
460 if (HasGenericServices(file_)) {
461 for (int i = 0; i < file_->service_count(); i++) {
462 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
471 // ---------------------------------------------------------------
473 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
474 // AssignDescriptors(). All later times, waits for the first call to
475 // complete and then returns.
479 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
480 "inline void protobuf_AssignDescriptorsOnce() {\n"
481 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
482 " &$assigndescriptorsname$);\n"
485 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
487 // protobuf_RegisterTypes(): Calls
488 // MessageFactory::InternalRegisterGeneratedType() for each message type.
490 "void protobuf_RegisterTypes(const ::std::string&) {\n"
491 " protobuf_AssignDescriptorsOnce();\n");
494 for (int i = 0; i < file_->message_type_count(); i++) {
495 message_generators_[i]->GenerateTypeRegistrations(printer);
505 // -----------------------------------------------------------------
507 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
510 "void $shutdownfilename$() {\n",
511 "shutdownfilename", GlobalShutdownFileName(file_->name()));
514 for (int i = 0; i < file_->message_type_count(); i++) {
515 message_generators_[i]->GenerateShutdownCode(printer);
522 // -----------------------------------------------------------------
524 // Now generate the AddDescriptors() function.
525 PrintHandlingOptionalStaticInitializers(
527 // With static initializers.
528 // Note that we don't need any special synchronization in the following code
529 // because it is called at static init time before any threads exist.
530 "void $adddescriptorsname$() {\n"
531 " static bool already_here = false;\n"
532 " if (already_here) return;\n"
533 " already_here = true;\n"
534 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
537 "void $adddescriptorsname$_impl() {\n"
538 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
541 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
545 // Call the AddDescriptors() methods for all of our dependencies, to make
546 // sure they get added first.
547 for (int i = 0; i < file_->dependency_count(); i++) {
548 const FileDescriptor* dependency = file_->dependency(i);
549 // Print the namespace prefix for the dependency.
550 vector<string> dependency_package_parts;
551 SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
552 printer->Print("::");
553 for (int j = 0; j < dependency_package_parts.size(); j++) {
554 printer->Print("$name$::",
555 "name", dependency_package_parts[j]);
557 // Call its AddDescriptors function.
560 "name", GlobalAddDescriptorsName(dependency->name()));
563 if (HasDescriptorMethods(file_)) {
564 // Embed the descriptor. We simply serialize the entire FileDescriptorProto
565 // and embed it as a string literal, which is parsed and built into real
566 // descriptors at initialization time.
567 FileDescriptorProto file_proto;
568 file_->CopyTo(&file_proto);
570 file_proto.SerializeToString(&file_data);
573 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
575 // Only write 40 bytes per line.
576 static const int kBytesPerLine = 40;
577 for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
578 printer->Print("\n \"$data$\"",
581 CEscape(file_data.substr(i, kBytesPerLine))));
585 "size", SimpleItoa(file_data.size()));
587 // Call MessageFactory::InternalRegisterGeneratedFile().
589 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
590 " \"$filename$\", &protobuf_RegisterTypes);\n",
591 "filename", file_->name());
594 // Allocate and initialize default instances. This can't be done lazily
595 // since default instances are returned by simple accessors and are used with
596 // extensions. Speaking of which, we also register extensions at this time.
597 for (int i = 0; i < file_->message_type_count(); i++) {
598 message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
600 for (int i = 0; i < file_->extension_count(); i++) {
601 extension_generators_[i]->GenerateRegistration(printer);
603 for (int i = 0; i < file_->message_type_count(); i++) {
604 message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
608 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
609 "shutdownfilename", GlobalShutdownFileName(file_->name()));
616 PrintHandlingOptionalStaticInitializers(
618 // With static initializers.
619 "// Force AddDescriptors() to be called at static initialization time.\n"
620 "struct StaticDescriptorInitializer_$filename$ {\n"
621 " StaticDescriptorInitializer_$filename$() {\n"
622 " $adddescriptorsname$();\n"
624 "} static_descriptor_initializer_$filename$_;\n",
626 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
627 "void $adddescriptorsname$() {\n"
628 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
629 " &$adddescriptorsname$_impl);\n"
632 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
633 "filename", FilenameIdentifier(file_->name()));
636 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
637 if (package_parts_.size() > 0) printer->Print("\n");
639 for (int i = 0; i < package_parts_.size(); i++) {
640 printer->Print("namespace $part$ {\n",
641 "part", package_parts_[i]);
645 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
646 if (package_parts_.size() > 0) printer->Print("\n");
648 for (int i = package_parts_.size() - 1; i >= 0; i--) {
649 printer->Print("} // namespace $part$\n",
650 "part", package_parts_[i]);
655 } // namespace compiler
656 } // namespace protobuf
657 } // namespace google