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

/src/google/protobuf/compiler/c/c_message.cc

http://protobuf-c.googlecode.com/
C++ | 448 lines | 378 code | 44 blank | 26 comment | 40 complexity | 980ec8679f8d4f67ef2d16b4a87ab462 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. // Author: kenton@google.com (Kenton Varda)
  17. // Based on original Protocol Buffers design by
  18. // Sanjay Ghemawat, Jeff Dean, and others.
  19. // Modified to implement C code by Dave Benson.
  20. #include <algorithm>
  21. #include <map>
  22. #include <google/protobuf/compiler/c/c_message.h>
  23. #include <google/protobuf/compiler/c/c_enum.h>
  24. #include <google/protobuf/compiler/c/c_extension.h>
  25. #include <google/protobuf/compiler/c/c_helpers.h>
  26. #include <google/protobuf/io/printer.h>
  27. #include <google/protobuf/io/coded_stream.h>
  28. #include <google/protobuf/wire_format.h>
  29. #include <google/protobuf/descriptor.pb.h>
  30. namespace google {
  31. namespace protobuf {
  32. namespace compiler {
  33. namespace c {
  34. // ===================================================================
  35. MessageGenerator::MessageGenerator(const Descriptor* descriptor,
  36. const string& dllexport_decl)
  37. : descriptor_(descriptor),
  38. dllexport_decl_(dllexport_decl),
  39. field_generators_(descriptor),
  40. nested_generators_(new scoped_ptr<MessageGenerator>[
  41. descriptor->nested_type_count()]),
  42. enum_generators_(new scoped_ptr<EnumGenerator>[
  43. descriptor->enum_type_count()]),
  44. extension_generators_(new scoped_ptr<ExtensionGenerator>[
  45. descriptor->extension_count()]) {
  46. for (int i = 0; i < descriptor->nested_type_count(); i++) {
  47. nested_generators_[i].reset(
  48. new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
  49. }
  50. for (int i = 0; i < descriptor->enum_type_count(); i++) {
  51. enum_generators_[i].reset(
  52. new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
  53. }
  54. for (int i = 0; i < descriptor->extension_count(); i++) {
  55. extension_generators_[i].reset(
  56. new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
  57. }
  58. }
  59. MessageGenerator::~MessageGenerator() {}
  60. void MessageGenerator::
  61. GenerateStructTypedef(io::Printer* printer) {
  62. printer->Print("typedef struct _$classname$ $classname$;\n",
  63. "classname", FullNameToC(descriptor_->full_name()));
  64. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  65. nested_generators_[i]->GenerateStructTypedef(printer);
  66. }
  67. }
  68. void MessageGenerator::
  69. GenerateEnumDefinitions(io::Printer* printer) {
  70. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  71. nested_generators_[i]->GenerateEnumDefinitions(printer);
  72. }
  73. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  74. enum_generators_[i]->GenerateDefinition(printer);
  75. }
  76. }
  77. void MessageGenerator::
  78. GenerateStructDefinition(io::Printer* printer) {
  79. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  80. nested_generators_[i]->GenerateStructDefinition(printer);
  81. }
  82. std::map<string, string> vars;
  83. vars["classname"] = FullNameToC(descriptor_->full_name());
  84. vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
  85. vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
  86. vars["field_count"] = SimpleItoa(descriptor_->field_count());
  87. if (dllexport_decl_.empty()) {
  88. vars["dllexport"] = "";
  89. } else {
  90. vars["dllexport"] = dllexport_decl_ + " ";
  91. }
  92. printer->Print(vars,
  93. "struct $dllexport$ _$classname$\n"
  94. "{\n"
  95. " ProtobufCMessage base;\n");
  96. // Generate fields.
  97. printer->Indent();
  98. for (int i = 0; i < descriptor_->field_count(); i++) {
  99. const FieldDescriptor *field = descriptor_->field(i);
  100. field_generators_.get(field).GenerateStructMembers(printer);
  101. }
  102. printer->Outdent();
  103. printer->Print(vars, "};\n");
  104. for (int i = 0; i < descriptor_->field_count(); i++) {
  105. const FieldDescriptor *field = descriptor_->field(i);
  106. if (field->has_default_value()) {
  107. field_generators_.get(field).GenerateDefaultValueDeclarations(printer);
  108. }
  109. }
  110. printer->Print(vars, "#define $ucclassname$__INIT \\\n"
  111. " { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor) \\\n ");
  112. for (int i = 0; i < descriptor_->field_count(); i++) {
  113. const FieldDescriptor *field = descriptor_->field(i);
  114. printer->Print(", ");
  115. field_generators_.get(field).GenerateStaticInit(printer);
  116. }
  117. printer->Print(" }\n\n\n");
  118. }
  119. void MessageGenerator::
  120. GenerateHelperFunctionDeclarations(io::Printer* printer, bool is_submessage)
  121. {
  122. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  123. nested_generators_[i]->GenerateHelperFunctionDeclarations(printer, true);
  124. }
  125. std::map<string, string> vars;
  126. vars["classname"] = FullNameToC(descriptor_->full_name());
  127. vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
  128. printer->Print(vars,
  129. "/* $classname$ methods */\n"
  130. "void $lcclassname$__init\n"
  131. " ($classname$ *message);\n"
  132. );
  133. if (!is_submessage) {
  134. printer->Print(vars,
  135. "size_t $lcclassname$__get_packed_size\n"
  136. " (const $classname$ *message);\n"
  137. "size_t $lcclassname$__pack\n"
  138. " (const $classname$ *message,\n"
  139. " uint8_t *out);\n"
  140. "size_t $lcclassname$__pack_to_buffer\n"
  141. " (const $classname$ *message,\n"
  142. " ProtobufCBuffer *buffer);\n"
  143. "$classname$ *\n"
  144. " $lcclassname$__unpack\n"
  145. " (ProtobufCAllocator *allocator,\n"
  146. " size_t len,\n"
  147. " const uint8_t *data);\n"
  148. "void $lcclassname$__free_unpacked\n"
  149. " ($classname$ *message,\n"
  150. " ProtobufCAllocator *allocator);\n"
  151. );
  152. }
  153. }
  154. void MessageGenerator::
  155. GenerateDescriptorDeclarations(io::Printer* printer) {
  156. printer->Print("extern const ProtobufCMessageDescriptor $name$__descriptor;\n",
  157. "name", FullNameToLower(descriptor_->full_name()));
  158. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  159. nested_generators_[i]->GenerateDescriptorDeclarations(printer);
  160. }
  161. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  162. enum_generators_[i]->GenerateDescriptorDeclarations(printer);
  163. }
  164. }
  165. void MessageGenerator::GenerateClosureTypedef(io::Printer* printer)
  166. {
  167. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  168. nested_generators_[i]->GenerateClosureTypedef(printer);
  169. }
  170. std::map<string, string> vars;
  171. vars["name"] = FullNameToC(descriptor_->full_name());
  172. printer->Print(vars,
  173. "typedef void (*$name$_Closure)\n"
  174. " (const $name$ *message,\n"
  175. " void *closure_data);\n");
  176. }
  177. static int
  178. compare_pfields_by_number (const void *a, const void *b)
  179. {
  180. const FieldDescriptor *pa = *(const FieldDescriptor **)a;
  181. const FieldDescriptor *pb = *(const FieldDescriptor **)b;
  182. if (pa->number() < pb->number()) return -1;
  183. if (pa->number() > pb->number()) return +1;
  184. return 0;
  185. }
  186. void MessageGenerator::
  187. GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage)
  188. {
  189. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  190. nested_generators_[i]->GenerateHelperFunctionDefinitions(printer, true);
  191. }
  192. std::map<string, string> vars;
  193. vars["classname"] = FullNameToC(descriptor_->full_name());
  194. vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
  195. vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
  196. printer->Print(vars,
  197. "void $lcclassname$__init\n"
  198. " ($classname$ *message)\n"
  199. "{\n"
  200. " static $classname$ init_value = $ucclassname$__INIT;\n"
  201. " *message = init_value;\n"
  202. "}\n");
  203. if (!is_submessage) {
  204. printer->Print(vars,
  205. "size_t $lcclassname$__get_packed_size\n"
  206. " (const $classname$ *message)\n"
  207. "{\n"
  208. " PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n"
  209. " return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n"
  210. "}\n"
  211. "size_t $lcclassname$__pack\n"
  212. " (const $classname$ *message,\n"
  213. " uint8_t *out)\n"
  214. "{\n"
  215. " PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n"
  216. " return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n"
  217. "}\n"
  218. "size_t $lcclassname$__pack_to_buffer\n"
  219. " (const $classname$ *message,\n"
  220. " ProtobufCBuffer *buffer)\n"
  221. "{\n"
  222. " PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n"
  223. " return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n"
  224. "}\n"
  225. "$classname$ *\n"
  226. " $lcclassname$__unpack\n"
  227. " (ProtobufCAllocator *allocator,\n"
  228. " size_t len,\n"
  229. " const uint8_t *data)\n"
  230. "{\n"
  231. " return ($classname$ *)\n"
  232. " protobuf_c_message_unpack (&$lcclassname$__descriptor,\n"
  233. " allocator, len, data);\n"
  234. "}\n"
  235. "void $lcclassname$__free_unpacked\n"
  236. " ($classname$ *message,\n"
  237. " ProtobufCAllocator *allocator)\n"
  238. "{\n"
  239. " PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n"
  240. " protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n"
  241. "}\n"
  242. );
  243. }
  244. }
  245. void MessageGenerator::
  246. GenerateMessageDescriptor(io::Printer* printer) {
  247. map<string, string> vars;
  248. vars["fullname"] = descriptor_->full_name();
  249. vars["classname"] = FullNameToC(descriptor_->full_name());
  250. vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
  251. vars["shortname"] = ToCamel(descriptor_->name());
  252. vars["n_fields"] = SimpleItoa(descriptor_->field_count());
  253. vars["packagename"] = descriptor_->file()->package();
  254. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  255. nested_generators_[i]->GenerateMessageDescriptor(printer);
  256. }
  257. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  258. enum_generators_[i]->GenerateEnumDescriptor(printer);
  259. }
  260. for (int i = 0; i < descriptor_->field_count(); i++) {
  261. const FieldDescriptor *fd = descriptor_->field(i);
  262. if (fd->has_default_value()) {
  263. field_generators_.get(fd).GenerateDefaultValueImplementations(printer);
  264. }
  265. }
  266. for (int i = 0; i < descriptor_->field_count(); i++) {
  267. const FieldDescriptor *fd = descriptor_->field(i);
  268. if (fd->has_default_value()) {
  269. bool already_defined = false;
  270. vars["name"] = fd->name();
  271. vars["lcname"] = CamelToLower(fd->name());
  272. vars["maybe_static"] = "static ";
  273. vars["field_dv_ctype_suffix"] = "";
  274. vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
  275. switch (fd->cpp_type()) {
  276. case FieldDescriptor::CPPTYPE_INT32:
  277. vars["field_dv_ctype"] = "int32_t";
  278. break;
  279. case FieldDescriptor::CPPTYPE_INT64:
  280. vars["field_dv_ctype"] = "int64_t";
  281. break;
  282. case FieldDescriptor::CPPTYPE_UINT32:
  283. vars["field_dv_ctype"] = "uint32_t";
  284. break;
  285. case FieldDescriptor::CPPTYPE_UINT64:
  286. vars["field_dv_ctype"] = "uint64_t";
  287. break;
  288. case FieldDescriptor::CPPTYPE_FLOAT:
  289. vars["field_dv_ctype"] = "float";
  290. break;
  291. case FieldDescriptor::CPPTYPE_DOUBLE:
  292. vars["field_dv_ctype"] = "double";
  293. break;
  294. case FieldDescriptor::CPPTYPE_BOOL:
  295. vars["field_dv_ctype"] = "protobuf_c_boolean";
  296. break;
  297. case FieldDescriptor::CPPTYPE_MESSAGE:
  298. // NOTE: not supported by protobuf
  299. vars["maybe_static"] = "";
  300. vars["field_dv_ctype"] = "{ ... }";
  301. GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
  302. break;
  303. case FieldDescriptor::CPPTYPE_STRING:
  304. if (fd->type() == FieldDescriptor::TYPE_BYTES)
  305. {
  306. vars["field_dv_ctype"] = "ProtobufCBinaryData";
  307. }
  308. else /* STRING type */
  309. {
  310. already_defined = true;
  311. vars["maybe_static"] = "";
  312. vars["field_dv_ctype"] = "char";
  313. vars["field_dv_ctype_suffix"] = "[]";
  314. }
  315. break;
  316. case FieldDescriptor::CPPTYPE_ENUM:
  317. {
  318. const EnumValueDescriptor *vd = fd->default_value_enum();
  319. vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name());
  320. break;
  321. }
  322. default:
  323. GOOGLE_LOG(DFATAL) << "Unknown CPPTYPE";
  324. break;
  325. }
  326. if (!already_defined)
  327. printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
  328. }
  329. }
  330. if ( descriptor_->field_count() ) {
  331. printer->Print(vars,
  332. "static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
  333. "{\n");
  334. printer->Indent();
  335. const FieldDescriptor **sorted_fields = new const FieldDescriptor *[descriptor_->field_count()];
  336. for (int i = 0; i < descriptor_->field_count(); i++) {
  337. sorted_fields[i] = descriptor_->field(i);
  338. }
  339. qsort (sorted_fields, descriptor_->field_count(),
  340. sizeof (const FieldDescriptor *),
  341. compare_pfields_by_number);
  342. for (int i = 0; i < descriptor_->field_count(); i++) {
  343. const FieldDescriptor *field = sorted_fields[i];
  344. field_generators_.get(field).GenerateDescriptorInitializer(printer);
  345. }
  346. printer->Outdent();
  347. printer->Print(vars, "};\n");
  348. NameIndex *field_indices = new NameIndex [descriptor_->field_count()];
  349. for (int i = 0; i < descriptor_->field_count(); i++) {
  350. field_indices[i].name = sorted_fields[i]->name().c_str();
  351. field_indices[i].index = i;
  352. }
  353. qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex),
  354. compare_name_indices_by_name);
  355. printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
  356. for (int i = 0; i < descriptor_->field_count(); i++) {
  357. vars["index"] = SimpleItoa(field_indices[i].index);
  358. vars["name"] = field_indices[i].name;
  359. printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
  360. }
  361. printer->Print("};\n");
  362. // create range initializers
  363. int *values = new int[descriptor_->field_count()];
  364. for (int i = 0; i < descriptor_->field_count(); i++) {
  365. values[i] = sorted_fields[i]->number();
  366. }
  367. int n_ranges = WriteIntRanges(printer,
  368. descriptor_->field_count(), values,
  369. vars["lcclassname"] + "__number_ranges");
  370. delete [] values;
  371. delete [] sorted_fields;
  372. vars["n_ranges"] = SimpleItoa(n_ranges);
  373. } else {
  374. /* MS compiler can't handle arrays with zero size and empty
  375. * initialization list. Furthermore it is an extension of GCC only but
  376. * not a standard. */
  377. vars["n_ranges"] = "0";
  378. printer->Print(vars,
  379. "#define $lcclassname$__field_descriptors NULL\n"
  380. "#define $lcclassname$__field_indices_by_name NULL\n"
  381. "#define $lcclassname$__number_ranges NULL\n");
  382. }
  383. printer->Print(vars,
  384. "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
  385. "{\n"
  386. " PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,\n"
  387. " \"$fullname$\",\n"
  388. " \"$shortname$\",\n"
  389. " \"$classname$\",\n"
  390. " \"$packagename$\",\n"
  391. " sizeof($classname$),\n"
  392. " $n_fields$,\n"
  393. " $lcclassname$__field_descriptors,\n"
  394. " $lcclassname$__field_indices_by_name,\n"
  395. " $n_ranges$,"
  396. " $lcclassname$__number_ranges,\n"
  397. " (ProtobufCMessageInit) $lcclassname$__init,\n"
  398. " NULL,NULL,NULL /* reserved[123] */\n"
  399. "};\n");
  400. }
  401. } // namespace c
  402. } // namespace compiler
  403. } // namespace protobuf
  404. } // namespace google