PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc

http://decs.googlecode.com/
C++ | 526 lines | 351 code | 75 blank | 100 comment | 40 complexity | a336abbc9d4756f546392c2d587a1846 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/compiler/cpp/cpp_file.h>
  34. #include <google/protobuf/compiler/cpp/cpp_enum.h>
  35. #include <google/protobuf/compiler/cpp/cpp_service.h>
  36. #include <google/protobuf/compiler/cpp/cpp_extension.h>
  37. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  38. #include <google/protobuf/compiler/cpp/cpp_message.h>
  39. #include <google/protobuf/io/printer.h>
  40. #include <google/protobuf/descriptor.pb.h>
  41. #include <google/protobuf/stubs/strutil.h>
  42. namespace google {
  43. namespace protobuf {
  44. namespace compiler {
  45. namespace cpp {
  46. // ===================================================================
  47. FileGenerator::FileGenerator(const FileDescriptor* file,
  48. const string& dllexport_decl)
  49. : file_(file),
  50. message_generators_(
  51. new scoped_ptr<MessageGenerator>[file->message_type_count()]),
  52. enum_generators_(
  53. new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
  54. service_generators_(
  55. new scoped_ptr<ServiceGenerator>[file->service_count()]),
  56. extension_generators_(
  57. new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
  58. dllexport_decl_(dllexport_decl) {
  59. for (int i = 0; i < file->message_type_count(); i++) {
  60. message_generators_[i].reset(
  61. new MessageGenerator(file->message_type(i), dllexport_decl));
  62. }
  63. for (int i = 0; i < file->enum_type_count(); i++) {
  64. enum_generators_[i].reset(
  65. new EnumGenerator(file->enum_type(i), dllexport_decl));
  66. }
  67. for (int i = 0; i < file->service_count(); i++) {
  68. service_generators_[i].reset(
  69. new ServiceGenerator(file->service(i), dllexport_decl));
  70. }
  71. for (int i = 0; i < file->extension_count(); i++) {
  72. extension_generators_[i].reset(
  73. new ExtensionGenerator(file->extension(i), dllexport_decl));
  74. }
  75. SplitStringUsing(file_->package(), ".", &package_parts_);
  76. }
  77. FileGenerator::~FileGenerator() {}
  78. void FileGenerator::GenerateHeader(io::Printer* printer) {
  79. string filename_identifier = FilenameIdentifier(file_->name());
  80. // Generate top of header.
  81. printer->Print(
  82. "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
  83. "\n"
  84. "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
  85. "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
  86. "\n"
  87. "#include <string>\n"
  88. "\n",
  89. "filename_identifier", filename_identifier);
  90. printer->Print(
  91. "#include <google/protobuf/stubs/common.h>\n"
  92. "\n");
  93. // Verify the protobuf library header version is compatible with the protoc
  94. // version before going any further.
  95. printer->Print(
  96. "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
  97. "#error This file was generated by a newer version of protoc which is\n"
  98. "#error incompatible with your Protocol Buffer headers. Please update\n"
  99. "#error your headers.\n"
  100. "#endif\n"
  101. "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
  102. "#error This file was generated by an older version of protoc which is\n"
  103. "#error incompatible with your Protocol Buffer headers. Please\n"
  104. "#error regenerate this file with a newer version of protoc.\n"
  105. "#endif\n"
  106. "\n",
  107. "min_header_version",
  108. SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
  109. "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
  110. // OK, it's now safe to #include other files.
  111. printer->Print(
  112. "#include <google/protobuf/generated_message_reflection.h>\n"
  113. "#include <google/protobuf/repeated_field.h>\n"
  114. "#include <google/protobuf/extension_set.h>\n");
  115. if (file_->service_count() > 0) {
  116. printer->Print(
  117. "#include <google/protobuf/service.h>\n");
  118. }
  119. for (int i = 0; i < file_->dependency_count(); i++) {
  120. printer->Print(
  121. "#include \"$dependency$.pb.h\"\n",
  122. "dependency", StripProto(file_->dependency(i)->name()));
  123. }
  124. // Open namespace.
  125. GenerateNamespaceOpeners(printer);
  126. // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
  127. // functions, so that we can declare them to be friends of each class.
  128. printer->Print(
  129. "\n"
  130. "// Internal implementation detail -- do not call these.\n"
  131. "void $dllexport_decl$ $adddescriptorsname$();\n",
  132. "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
  133. "dllexport_decl", dllexport_decl_);
  134. printer->Print(
  135. // Note that we don't put dllexport_decl on these because they are only
  136. // called by the .pb.cc file in which they are defined.
  137. "void $assigndescriptorsname$();\n"
  138. "void $shutdownfilename$();\n"
  139. "\n",
  140. "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
  141. "shutdownfilename", GlobalShutdownFileName(file_->name()));
  142. // Generate forward declarations of classes.
  143. for (int i = 0; i < file_->message_type_count(); i++) {
  144. message_generators_[i]->GenerateForwardDeclaration(printer);
  145. }
  146. printer->Print("\n");
  147. // Generate enum definitions.
  148. for (int i = 0; i < file_->message_type_count(); i++) {
  149. message_generators_[i]->GenerateEnumDefinitions(printer);
  150. }
  151. for (int i = 0; i < file_->enum_type_count(); i++) {
  152. enum_generators_[i]->GenerateDefinition(printer);
  153. }
  154. printer->Print(kThickSeparator);
  155. printer->Print("\n");
  156. // Generate class definitions.
  157. for (int i = 0; i < file_->message_type_count(); i++) {
  158. if (i > 0) {
  159. printer->Print("\n");
  160. printer->Print(kThinSeparator);
  161. printer->Print("\n");
  162. }
  163. message_generators_[i]->GenerateClassDefinition(printer);
  164. }
  165. printer->Print("\n");
  166. printer->Print(kThickSeparator);
  167. printer->Print("\n");
  168. // Generate service definitions.
  169. for (int i = 0; i < file_->service_count(); i++) {
  170. if (i > 0) {
  171. printer->Print("\n");
  172. printer->Print(kThinSeparator);
  173. printer->Print("\n");
  174. }
  175. service_generators_[i]->GenerateDeclarations(printer);
  176. }
  177. printer->Print("\n");
  178. printer->Print(kThickSeparator);
  179. printer->Print("\n");
  180. // Declare extension identifiers.
  181. for (int i = 0; i < file_->extension_count(); i++) {
  182. extension_generators_[i]->GenerateDeclaration(printer);
  183. }
  184. printer->Print("\n");
  185. printer->Print(kThickSeparator);
  186. printer->Print("\n");
  187. // Generate class inline methods.
  188. for (int i = 0; i < file_->message_type_count(); i++) {
  189. if (i > 0) {
  190. printer->Print(kThinSeparator);
  191. printer->Print("\n");
  192. }
  193. message_generators_[i]->GenerateInlineMethods(printer);
  194. }
  195. // Close up namespace.
  196. GenerateNamespaceClosers(printer);
  197. printer->Print(
  198. "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
  199. "filename_identifier", filename_identifier);
  200. }
  201. void FileGenerator::GenerateSource(io::Printer* printer) {
  202. printer->Print(
  203. "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
  204. "\n"
  205. "#include \"$basename$.pb.h\"\n"
  206. "#include <google/protobuf/stubs/once.h>\n"
  207. "#include <google/protobuf/descriptor.h>\n"
  208. "#include <google/protobuf/io/coded_stream.h>\n"
  209. "#include <google/protobuf/reflection_ops.h>\n"
  210. "#include <google/protobuf/wire_format_inl.h>\n",
  211. "basename", StripProto(file_->name()));
  212. GenerateNamespaceOpeners(printer);
  213. printer->Print(
  214. "\n"
  215. "namespace {\n"
  216. "\n");
  217. for (int i = 0; i < file_->message_type_count(); i++) {
  218. message_generators_[i]->GenerateDescriptorDeclarations(printer);
  219. }
  220. for (int i = 0; i < file_->enum_type_count(); i++) {
  221. printer->Print(
  222. "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
  223. "name", ClassName(file_->enum_type(i), false));
  224. }
  225. for (int i = 0; i < file_->service_count(); i++) {
  226. printer->Print(
  227. "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
  228. "name", file_->service(i)->name());
  229. }
  230. printer->Print(
  231. "\n"
  232. "} // namespace\n"
  233. "\n");
  234. // Define our externally-visible BuildDescriptors() function.
  235. GenerateBuildDescriptors(printer);
  236. // Generate enums.
  237. for (int i = 0; i < file_->enum_type_count(); i++) {
  238. enum_generators_[i]->GenerateMethods(printer);
  239. }
  240. // Generate classes.
  241. for (int i = 0; i < file_->message_type_count(); i++) {
  242. printer->Print("\n");
  243. printer->Print(kThickSeparator);
  244. printer->Print("\n");
  245. message_generators_[i]->GenerateClassMethods(printer);
  246. }
  247. // Generate services.
  248. for (int i = 0; i < file_->service_count(); i++) {
  249. if (i == 0) printer->Print("\n");
  250. printer->Print(kThickSeparator);
  251. printer->Print("\n");
  252. service_generators_[i]->GenerateImplementation(printer);
  253. }
  254. // Define extensions.
  255. for (int i = 0; i < file_->extension_count(); i++) {
  256. extension_generators_[i]->GenerateDefinition(printer);
  257. }
  258. GenerateNamespaceClosers(printer);
  259. }
  260. void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
  261. // AddDescriptors() is a file-level procedure which adds the encoded
  262. // FileDescriptorProto for this .proto file to the global DescriptorPool
  263. // for generated files (DescriptorPool::generated_pool()). It always runs
  264. // at static initialization time, so all files will be registered before
  265. // main() starts. This procedure also constructs default instances and
  266. // registers extensions.
  267. //
  268. // Its sibling, AssignDescriptors(), actually pulls the compiled
  269. // FileDescriptor from the DescriptorPool and uses it to populate all of
  270. // the global variables which store pointers to the descriptor objects.
  271. // It also constructs the reflection objects. It is called the first time
  272. // anyone calls descriptor() or GetReflection() on one of the types defined
  273. // in the file.
  274. printer->Print(
  275. "\n"
  276. "void $assigndescriptorsname$() {\n",
  277. "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
  278. printer->Indent();
  279. // Make sure the file has found its way into the pool. If a descriptor
  280. // is requested *during* static init then AddDescriptors() may not have
  281. // been called yet, so we call it manually. Note that it's fine if
  282. // AddDescriptors() is called multiple times.
  283. printer->Print(
  284. "$adddescriptorsname$();\n",
  285. "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
  286. // Get the file's descriptor from the pool.
  287. printer->Print(
  288. "const ::google::protobuf::FileDescriptor* file =\n"
  289. " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
  290. " \"$filename$\");\n"
  291. // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
  292. // being unused when compiling an empty .proto file.
  293. "GOOGLE_CHECK(file != NULL);\n",
  294. "filename", file_->name());
  295. // Go through all the stuff defined in this file and generated code to
  296. // assign the global descriptor pointers based on the file descriptor.
  297. for (int i = 0; i < file_->message_type_count(); i++) {
  298. message_generators_[i]->GenerateDescriptorInitializer(printer, i);
  299. }
  300. for (int i = 0; i < file_->enum_type_count(); i++) {
  301. enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
  302. }
  303. for (int i = 0; i < file_->service_count(); i++) {
  304. service_generators_[i]->GenerateDescriptorInitializer(printer, i);
  305. }
  306. printer->Outdent();
  307. printer->Print(
  308. "}\n"
  309. "\n");
  310. // -----------------------------------------------------------------
  311. // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
  312. // AssignDescriptors(). All later times, waits for the first call to
  313. // complete and then returns.
  314. printer->Print(
  315. "namespace {\n"
  316. "\n"
  317. "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
  318. "inline void protobuf_AssignDescriptorsOnce() {\n"
  319. " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
  320. " &$assigndescriptorsname$);\n"
  321. "}\n"
  322. "\n",
  323. "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
  324. // protobuf_RegisterTypes(): Calls
  325. // MessageFactory::InternalRegisterGeneratedType() for each message type.
  326. printer->Print(
  327. "void protobuf_RegisterTypes() {\n"
  328. " protobuf_AssignDescriptorsOnce();\n");
  329. printer->Indent();
  330. for (int i = 0; i < file_->message_type_count(); i++) {
  331. message_generators_[i]->GenerateTypeRegistrations(printer);
  332. }
  333. printer->Outdent();
  334. printer->Print(
  335. "}\n"
  336. "\n"
  337. "} // namespace\n");
  338. // -----------------------------------------------------------------
  339. // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
  340. printer->Print(
  341. "\n"
  342. "void $shutdownfilename$() {\n",
  343. "shutdownfilename", GlobalShutdownFileName(file_->name()));
  344. printer->Indent();
  345. for (int i = 0; i < file_->message_type_count(); i++) {
  346. message_generators_[i]->GenerateShutdownCode(printer);
  347. }
  348. printer->Outdent();
  349. printer->Print(
  350. "}\n");
  351. // -----------------------------------------------------------------
  352. // Now generate the AddDescriptors() function.
  353. printer->Print(
  354. "\n"
  355. "void $adddescriptorsname$() {\n"
  356. // We don't need any special synchronization here because this code is
  357. // called at static init time before any threads exist.
  358. " static bool already_here = false;\n"
  359. " if (already_here) return;\n"
  360. " already_here = true;\n"
  361. " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
  362. "\n",
  363. "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
  364. printer->Indent();
  365. // Call the AddDescriptors() methods for all of our dependencies, to make
  366. // sure they get added first.
  367. for (int i = 0; i < file_->dependency_count(); i++) {
  368. const FileDescriptor* dependency = file_->dependency(i);
  369. // Print the namespace prefix for the dependency.
  370. vector<string> dependency_package_parts;
  371. SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
  372. printer->Print("::");
  373. for (int i = 0; i < dependency_package_parts.size(); i++) {
  374. printer->Print("$name$::",
  375. "name", dependency_package_parts[i]);
  376. }
  377. // Call its AddDescriptors function.
  378. printer->Print(
  379. "$name$();\n",
  380. "name", GlobalAddDescriptorsName(dependency->name()));
  381. }
  382. // Embed the descriptor. We simply serialize the entire FileDescriptorProto
  383. // and embed it as a string literal, which is parsed and built into real
  384. // descriptors at initialization time.
  385. FileDescriptorProto file_proto;
  386. file_->CopyTo(&file_proto);
  387. string file_data;
  388. file_proto.SerializeToString(&file_data);
  389. printer->Print(
  390. "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
  391. // Only write 40 bytes per line.
  392. static const int kBytesPerLine = 40;
  393. for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
  394. printer->Print("\n \"$data$\"",
  395. "data", CEscape(file_data.substr(i, kBytesPerLine)));
  396. }
  397. printer->Print(
  398. ", $size$);\n",
  399. "size", SimpleItoa(file_data.size()));
  400. // Call MessageFactory::InternalRegisterGeneratedFile().
  401. printer->Print(
  402. "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
  403. " \"$filename$\", &protobuf_RegisterTypes);\n",
  404. "filename", file_->name());
  405. // Allocate and initialize default instances. This can't be done lazily
  406. // since default instances are returned by simple accessors and are used with
  407. // extensions. Speaking of which, we also register extensions at this time.
  408. for (int i = 0; i < file_->message_type_count(); i++) {
  409. message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
  410. }
  411. for (int i = 0; i < file_->extension_count(); i++) {
  412. extension_generators_[i]->GenerateRegistration(printer);
  413. }
  414. for (int i = 0; i < file_->message_type_count(); i++) {
  415. message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
  416. }
  417. printer->Print(
  418. "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
  419. "shutdownfilename", GlobalShutdownFileName(file_->name()));
  420. printer->Outdent();
  421. printer->Print(
  422. "}\n"
  423. "\n"
  424. "// Force AddDescriptors() to be called at static initialization time.\n"
  425. "struct StaticDescriptorInitializer_$filename$ {\n"
  426. " StaticDescriptorInitializer_$filename$() {\n"
  427. " $adddescriptorsname$();\n"
  428. " }\n"
  429. "} static_descriptor_initializer_$filename$_;\n"
  430. "\n",
  431. "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
  432. "filename", FilenameIdentifier(file_->name()));
  433. }
  434. void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
  435. if (package_parts_.size() > 0) printer->Print("\n");
  436. for (int i = 0; i < package_parts_.size(); i++) {
  437. printer->Print("namespace $part$ {\n",
  438. "part", package_parts_[i]);
  439. }
  440. }
  441. void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
  442. if (package_parts_.size() > 0) printer->Print("\n");
  443. for (int i = package_parts_.size() - 1; i >= 0; i--) {
  444. printer->Print("} // namespace $part$\n",
  445. "part", package_parts_[i]);
  446. }
  447. }
  448. } // namespace cpp
  449. } // namespace compiler
  450. } // namespace protobuf
  451. } // namespace google