PageRenderTime 84ms CodeModel.GetById 20ms RepoModel.GetById 3ms app.codeStats 0ms

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

https://bitbucket.org/Abd4llA/test
C++ | 424 lines | 296 code | 58 blank | 70 comment | 36 complexity | ce54116b991153a095f03bda9d24706d MD5 | raw file
  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 AssignGlobalDescriptors function, so that we can
  127. // declare it to be a friend of each class.
  128. printer->Print(
  129. "\n"
  130. "// Internal implementation detail -- do not call these.\n"
  131. "void $dllexport_decl$ $builddescriptorsname$();\n"
  132. "void $builddescriptorsname$_AssignGlobalDescriptors(\n"
  133. " ::google::protobuf::FileDescriptor* file);\n"
  134. "\n",
  135. "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()),
  136. "dllexport_decl", dllexport_decl_);
  137. // Generate forward declarations of classes.
  138. for (int i = 0; i < file_->message_type_count(); i++) {
  139. message_generators_[i]->GenerateForwardDeclaration(printer);
  140. }
  141. printer->Print("\n");
  142. // Generate enum definitions.
  143. for (int i = 0; i < file_->message_type_count(); i++) {
  144. message_generators_[i]->GenerateEnumDefinitions(printer);
  145. }
  146. for (int i = 0; i < file_->enum_type_count(); i++) {
  147. enum_generators_[i]->GenerateDefinition(printer);
  148. }
  149. printer->Print(kThickSeparator);
  150. printer->Print("\n");
  151. // Generate class definitions.
  152. for (int i = 0; i < file_->message_type_count(); i++) {
  153. if (i > 0) {
  154. printer->Print("\n");
  155. printer->Print(kThinSeparator);
  156. printer->Print("\n");
  157. }
  158. message_generators_[i]->GenerateClassDefinition(printer);
  159. }
  160. printer->Print("\n");
  161. printer->Print(kThickSeparator);
  162. printer->Print("\n");
  163. // Generate service definitions.
  164. for (int i = 0; i < file_->service_count(); i++) {
  165. if (i > 0) {
  166. printer->Print("\n");
  167. printer->Print(kThinSeparator);
  168. printer->Print("\n");
  169. }
  170. service_generators_[i]->GenerateDeclarations(printer);
  171. }
  172. printer->Print("\n");
  173. printer->Print(kThickSeparator);
  174. printer->Print("\n");
  175. // Declare extension identifiers.
  176. for (int i = 0; i < file_->extension_count(); i++) {
  177. extension_generators_[i]->GenerateDeclaration(printer);
  178. }
  179. printer->Print("\n");
  180. printer->Print(kThickSeparator);
  181. printer->Print("\n");
  182. // Generate class inline methods.
  183. for (int i = 0; i < file_->message_type_count(); i++) {
  184. if (i > 0) {
  185. printer->Print(kThinSeparator);
  186. printer->Print("\n");
  187. }
  188. message_generators_[i]->GenerateInlineMethods(printer);
  189. }
  190. // Close up namespace.
  191. GenerateNamespaceClosers(printer);
  192. printer->Print(
  193. "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
  194. "filename_identifier", filename_identifier);
  195. }
  196. void FileGenerator::GenerateSource(io::Printer* printer) {
  197. printer->Print(
  198. "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
  199. "\n"
  200. "#include \"$basename$.pb.h\"\n"
  201. "#include <google/protobuf/descriptor.h>\n"
  202. "#include <google/protobuf/io/coded_stream.h>\n"
  203. "#include <google/protobuf/reflection_ops.h>\n"
  204. "#include <google/protobuf/wire_format_inl.h>\n",
  205. "basename", StripProto(file_->name()));
  206. GenerateNamespaceOpeners(printer);
  207. printer->Print(
  208. "\n"
  209. "namespace {\n"
  210. "\n");
  211. for (int i = 0; i < file_->message_type_count(); i++) {
  212. message_generators_[i]->GenerateDescriptorDeclarations(printer);
  213. }
  214. for (int i = 0; i < file_->enum_type_count(); i++) {
  215. printer->Print(
  216. "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
  217. "name", ClassName(file_->enum_type(i), false));
  218. }
  219. for (int i = 0; i < file_->service_count(); i++) {
  220. printer->Print(
  221. "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
  222. "name", file_->service(i)->name());
  223. }
  224. printer->Print(
  225. "\n"
  226. "} // namespace\n"
  227. "\n");
  228. // Define our externally-visible BuildDescriptors() function.
  229. GenerateBuildDescriptors(printer);
  230. // Generate enums.
  231. for (int i = 0; i < file_->enum_type_count(); i++) {
  232. enum_generators_[i]->GenerateMethods(printer);
  233. }
  234. // Generate classes.
  235. for (int i = 0; i < file_->message_type_count(); i++) {
  236. printer->Print("\n");
  237. printer->Print(kThickSeparator);
  238. printer->Print("\n");
  239. message_generators_[i]->GenerateClassMethods(printer);
  240. }
  241. // Generate services.
  242. for (int i = 0; i < file_->service_count(); i++) {
  243. if (i == 0) printer->Print("\n");
  244. printer->Print(kThickSeparator);
  245. printer->Print("\n");
  246. service_generators_[i]->GenerateImplementation(printer);
  247. }
  248. // Define extensions.
  249. for (int i = 0; i < file_->extension_count(); i++) {
  250. extension_generators_[i]->GenerateDefinition(printer);
  251. }
  252. GenerateNamespaceClosers(printer);
  253. }
  254. void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
  255. // BuildDescriptors() is a file-level procedure which initializes all of
  256. // the Descriptor objects for this file. It runs the first time one of the
  257. // descriptors is accessed. This will always be at static initialization
  258. // time, because every message has a statically-initialized default instance,
  259. // and the constructor for a message class accesses its descriptor. See the
  260. // constructor and the descriptor() method of message classes.
  261. //
  262. // We also construct the reflection object for each class inside
  263. // BuildDescriptors().
  264. // First we generate a method to assign the global descriptors.
  265. printer->Print(
  266. "\n"
  267. "void $builddescriptorsname$_AssignGlobalDescriptors("
  268. "const ::google::protobuf::FileDescriptor* file) {\n",
  269. "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
  270. printer->Indent();
  271. for (int i = 0; i < file_->message_type_count(); i++) {
  272. message_generators_[i]->GenerateDescriptorInitializer(printer, i);
  273. }
  274. for (int i = 0; i < file_->enum_type_count(); i++) {
  275. enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
  276. }
  277. for (int i = 0; i < file_->service_count(); i++) {
  278. service_generators_[i]->GenerateDescriptorInitializer(printer, i);
  279. }
  280. for (int i = 0; i < file_->message_type_count(); i++) {
  281. message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
  282. }
  283. printer->Outdent();
  284. printer->Print(
  285. "}\n");
  286. printer->Print(
  287. "\n"
  288. "void $builddescriptorsname$() {\n"
  289. " static bool already_here = false;\n"
  290. " if (already_here) return;\n"
  291. " already_here = true;\n"
  292. " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
  293. " ::google::protobuf::DescriptorPool* pool =\n"
  294. " ::google::protobuf::DescriptorPool::internal_generated_pool();\n"
  295. "\n",
  296. "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
  297. printer->Indent();
  298. // Call the BuildDescriptors() methods for all of our dependencies, to make
  299. // sure they get initialized first.
  300. for (int i = 0; i < file_->dependency_count(); i++) {
  301. const FileDescriptor* dependency = file_->dependency(i);
  302. // Print the namespace prefix for the dependency.
  303. vector<string> dependency_package_parts;
  304. SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
  305. printer->Print("::");
  306. for (int i = 0; i < dependency_package_parts.size(); i++) {
  307. printer->Print("$name$::",
  308. "name", dependency_package_parts[i]);
  309. }
  310. // Call its BuildDescriptors function.
  311. printer->Print(
  312. "$name$();\n",
  313. "name", GlobalBuildDescriptorsName(dependency->name()));
  314. }
  315. // Embed the descriptor. We simply serialize the entire FileDescriptorProto
  316. // and embed it as a string literal, which is parsed and built into real
  317. // descriptors at initialization time.
  318. FileDescriptorProto file_proto;
  319. file_->CopyTo(&file_proto);
  320. string file_data;
  321. file_proto.SerializeToString(&file_data);
  322. printer->Print(
  323. "pool->InternalBuildGeneratedFile(");
  324. // Only write 40 bytes per line.
  325. static const int kBytesPerLine = 40;
  326. for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
  327. printer->Print("\n \"$data$\"",
  328. "data", CEscape(file_data.substr(i, kBytesPerLine)));
  329. }
  330. printer->Print(
  331. ", $size$,\n"
  332. "&$builddescriptorsname$_AssignGlobalDescriptors);\n",
  333. "size", SimpleItoa(file_data.size()),
  334. "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
  335. printer->Outdent();
  336. printer->Print(
  337. "}\n"
  338. "\n"
  339. "// Force BuildDescriptors() to be called at static initialization time.\n"
  340. "struct StaticDescriptorInitializer_$filename$ {\n"
  341. " StaticDescriptorInitializer_$filename$() {\n"
  342. " $builddescriptorsname$();\n"
  343. " }\n"
  344. "} static_descriptor_initializer_$filename$_;\n"
  345. "\n",
  346. "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()),
  347. "filename", FilenameIdentifier(file_->name()));
  348. }
  349. void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
  350. if (package_parts_.size() > 0) printer->Print("\n");
  351. for (int i = 0; i < package_parts_.size(); i++) {
  352. printer->Print("namespace $part$ {\n",
  353. "part", package_parts_[i]);
  354. }
  355. }
  356. void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
  357. if (package_parts_.size() > 0) printer->Print("\n");
  358. for (int i = package_parts_.size() - 1; i >= 0; i--) {
  359. printer->Print("} // namespace $part$\n",
  360. "part", package_parts_[i]);
  361. }
  362. }
  363. } // namespace cpp
  364. } // namespace compiler
  365. } // namespace protobuf
  366. } // namespace google