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