cpp_enum_field.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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. // 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_enum_field.h>
  34. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  35. #include <google/protobuf/io/printer.h>
  36. #include <google/protobuf/wire_format.h>
  37. #include <google/protobuf/stubs/strutil.h>
  38. namespace google {
  39. namespace protobuf {
  40. namespace compiler {
  41. namespace cpp {
  42. namespace {
  43. void SetEnumVariables(const FieldDescriptor* descriptor,
  44. std::map<string, string>* variables,
  45. const Options& options) {
  46. SetCommonFieldVariables(descriptor, variables, options);
  47. const EnumValueDescriptor* default_value = descriptor->default_value_enum();
  48. (*variables)["type"] = ClassName(descriptor->enum_type(), true);
  49. (*variables)["default"] = Int32ToString(default_value->number());
  50. (*variables)["full_name"] = descriptor->full_name();
  51. }
  52. } // namespace
  53. // ===================================================================
  54. EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
  55. const Options& options)
  56. : FieldGenerator(options), descriptor_(descriptor) {
  57. SetEnumVariables(descriptor, &variables_, options);
  58. }
  59. EnumFieldGenerator::~EnumFieldGenerator() {}
  60. void EnumFieldGenerator::
  61. GeneratePrivateMembers(io::Printer* printer) const {
  62. printer->Print(variables_, "int $name$_;\n");
  63. }
  64. void EnumFieldGenerator::
  65. GenerateAccessorDeclarations(io::Printer* printer) const {
  66. printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
  67. printer->Annotate("name", descriptor_);
  68. printer->Print(variables_,
  69. "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
  70. printer->Annotate("{", "}", descriptor_);
  71. }
  72. void EnumFieldGenerator::
  73. GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  74. printer->Print(variables_,
  75. "inline $type$ $classname$::$name$() const {\n"
  76. " // @@protoc_insertion_point(field_get:$full_name$)\n"
  77. " return static_cast< $type$ >($name$_);\n"
  78. "}\n"
  79. "inline void $classname$::set_$name$($type$ value) {\n");
  80. if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  81. printer->Print(variables_,
  82. " assert($type$_IsValid(value));\n");
  83. }
  84. printer->Print(variables_,
  85. " $set_hasbit$\n"
  86. " $name$_ = value;\n"
  87. " // @@protoc_insertion_point(field_set:$full_name$)\n"
  88. "}\n");
  89. }
  90. void EnumFieldGenerator::
  91. GenerateClearingCode(io::Printer* printer) const {
  92. printer->Print(variables_, "$name$_ = $default$;\n");
  93. }
  94. void EnumFieldGenerator::
  95. GenerateMergingCode(io::Printer* printer) const {
  96. printer->Print(variables_, "set_$name$(from.$name$());\n");
  97. }
  98. void EnumFieldGenerator::
  99. GenerateSwappingCode(io::Printer* printer) const {
  100. printer->Print(variables_, "swap($name$_, other->$name$_);\n");
  101. }
  102. void EnumFieldGenerator::
  103. GenerateConstructorCode(io::Printer* printer) const {
  104. printer->Print(variables_, "$name$_ = $default$;\n");
  105. }
  106. void EnumFieldGenerator::
  107. GenerateCopyConstructorCode(io::Printer* printer) const {
  108. printer->Print(variables_, "$name$_ = from.$name$_;\n");
  109. }
  110. void EnumFieldGenerator::
  111. GenerateMergeFromCodedStream(io::Printer* printer) const {
  112. printer->Print(variables_,
  113. "int value;\n"
  114. "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
  115. " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
  116. " input, &value)));\n");
  117. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  118. printer->Print(variables_,
  119. "set_$name$(static_cast< $type$ >(value));\n");
  120. } else {
  121. printer->Print(variables_,
  122. "if ($type$_IsValid(value)) {\n"
  123. " set_$name$(static_cast< $type$ >(value));\n");
  124. if (UseUnknownFieldSet(descriptor_->file(), options_)) {
  125. printer->Print(variables_,
  126. "} else {\n"
  127. " mutable_unknown_fields()->AddVarint(\n"
  128. " $number$, static_cast< ::google::protobuf::uint64>(value));\n");
  129. } else {
  130. printer->Print(
  131. "} else {\n"
  132. " unknown_fields_stream.WriteVarint32($tag$u);\n"
  133. " unknown_fields_stream.WriteVarint32(\n"
  134. " static_cast< ::google::protobuf::uint32>(value));\n",
  135. "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
  136. }
  137. printer->Print(variables_,
  138. "}\n");
  139. }
  140. }
  141. void EnumFieldGenerator::
  142. GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  143. printer->Print(variables_,
  144. "::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
  145. " $number$, this->$name$(), output);\n");
  146. }
  147. void EnumFieldGenerator::
  148. GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  149. printer->Print(variables_,
  150. "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
  151. " $number$, this->$name$(), target);\n");
  152. }
  153. void EnumFieldGenerator::
  154. GenerateByteSize(io::Printer* printer) const {
  155. printer->Print(variables_,
  156. "total_size += $tag_size$ +\n"
  157. " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
  158. }
  159. // ===================================================================
  160. EnumOneofFieldGenerator::
  161. EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
  162. const Options& options)
  163. : EnumFieldGenerator(descriptor, options) {
  164. SetCommonOneofFieldVariables(descriptor, &variables_);
  165. }
  166. EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
  167. void EnumOneofFieldGenerator::
  168. GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  169. printer->Print(variables_,
  170. "inline $type$ $classname$::$name$() const {\n"
  171. " // @@protoc_insertion_point(field_get:$full_name$)\n"
  172. " if (has_$name$()) {\n"
  173. " return static_cast< $type$ >($field_member$);\n"
  174. " }\n"
  175. " return static_cast< $type$ >($default$);\n"
  176. "}\n"
  177. "inline void $classname$::set_$name$($type$ value) {\n");
  178. if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  179. printer->Print(variables_,
  180. " assert($type$_IsValid(value));\n");
  181. }
  182. printer->Print(variables_,
  183. " if (!has_$name$()) {\n"
  184. " clear_$oneof_name$();\n"
  185. " set_has_$name$();\n"
  186. " }\n"
  187. " $field_member$ = value;\n"
  188. " // @@protoc_insertion_point(field_set:$full_name$)\n"
  189. "}\n");
  190. }
  191. void EnumOneofFieldGenerator::
  192. GenerateClearingCode(io::Printer* printer) const {
  193. printer->Print(variables_, "$field_member$ = $default$;\n");
  194. }
  195. void EnumOneofFieldGenerator::
  196. GenerateSwappingCode(io::Printer* printer) const {
  197. // Don't print any swapping code. Swapping the union will swap this field.
  198. }
  199. void EnumOneofFieldGenerator::
  200. GenerateConstructorCode(io::Printer* printer) const {
  201. printer->Print(variables_,
  202. "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
  203. }
  204. // ===================================================================
  205. RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
  206. const FieldDescriptor* descriptor, const Options& options)
  207. : FieldGenerator(options), descriptor_(descriptor) {
  208. SetEnumVariables(descriptor, &variables_, options);
  209. }
  210. RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
  211. void RepeatedEnumFieldGenerator::
  212. GeneratePrivateMembers(io::Printer* printer) const {
  213. printer->Print(variables_,
  214. "::google::protobuf::RepeatedField<int> $name$_;\n");
  215. if (descriptor_->is_packed() &&
  216. HasGeneratedMethods(descriptor_->file(), options_)) {
  217. printer->Print(variables_,
  218. "mutable int _$name$_cached_byte_size_;\n");
  219. }
  220. }
  221. void RepeatedEnumFieldGenerator::
  222. GenerateAccessorDeclarations(io::Printer* printer) const {
  223. printer->Print(variables_,
  224. "$deprecated_attr$$type$ $name$(int index) const;\n");
  225. printer->Annotate("name", descriptor_);
  226. printer->Print(
  227. variables_,
  228. "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
  229. printer->Annotate("{", "}", descriptor_);
  230. printer->Print(variables_,
  231. "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
  232. printer->Annotate("{", "}", descriptor_);
  233. printer->Print(
  234. variables_,
  235. "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n");
  236. printer->Annotate("name", descriptor_);
  237. printer->Print(variables_,
  238. "$deprecated_attr$::google::protobuf::RepeatedField<int>* "
  239. "${$mutable_$name$$}$();\n");
  240. printer->Annotate("{", "}", descriptor_);
  241. }
  242. void RepeatedEnumFieldGenerator::
  243. GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  244. printer->Print(variables_,
  245. "inline $type$ $classname$::$name$(int index) const {\n"
  246. " // @@protoc_insertion_point(field_get:$full_name$)\n"
  247. " return static_cast< $type$ >($name$_.Get(index));\n"
  248. "}\n"
  249. "inline void $classname$::set_$name$(int index, $type$ value) {\n");
  250. if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  251. printer->Print(variables_,
  252. " assert($type$_IsValid(value));\n");
  253. }
  254. printer->Print(variables_,
  255. " $name$_.Set(index, value);\n"
  256. " // @@protoc_insertion_point(field_set:$full_name$)\n"
  257. "}\n"
  258. "inline void $classname$::add_$name$($type$ value) {\n");
  259. if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  260. printer->Print(variables_,
  261. " assert($type$_IsValid(value));\n");
  262. }
  263. printer->Print(variables_,
  264. " $name$_.Add(value);\n"
  265. " // @@protoc_insertion_point(field_add:$full_name$)\n"
  266. "}\n"
  267. "inline const ::google::protobuf::RepeatedField<int>&\n"
  268. "$classname$::$name$() const {\n"
  269. " // @@protoc_insertion_point(field_list:$full_name$)\n"
  270. " return $name$_;\n"
  271. "}\n"
  272. "inline ::google::protobuf::RepeatedField<int>*\n"
  273. "$classname$::mutable_$name$() {\n"
  274. " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
  275. " return &$name$_;\n"
  276. "}\n");
  277. }
  278. void RepeatedEnumFieldGenerator::
  279. GenerateClearingCode(io::Printer* printer) const {
  280. printer->Print(variables_, "$name$_.Clear();\n");
  281. }
  282. void RepeatedEnumFieldGenerator::
  283. GenerateMergingCode(io::Printer* printer) const {
  284. printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
  285. }
  286. void RepeatedEnumFieldGenerator::
  287. GenerateSwappingCode(io::Printer* printer) const {
  288. printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
  289. }
  290. void RepeatedEnumFieldGenerator::
  291. GenerateConstructorCode(io::Printer* printer) const {
  292. // Not needed for repeated fields.
  293. }
  294. void RepeatedEnumFieldGenerator::
  295. GenerateMergeFromCodedStream(io::Printer* printer) const {
  296. // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
  297. printer->Print(variables_,
  298. "int value;\n"
  299. "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
  300. " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
  301. " input, &value)));\n");
  302. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  303. printer->Print(variables_,
  304. "add_$name$(static_cast< $type$ >(value));\n");
  305. } else {
  306. printer->Print(variables_,
  307. "if ($type$_IsValid(value)) {\n"
  308. " add_$name$(static_cast< $type$ >(value));\n");
  309. if (UseUnknownFieldSet(descriptor_->file(), options_)) {
  310. printer->Print(variables_,
  311. "} else {\n"
  312. " mutable_unknown_fields()->AddVarint(\n"
  313. " $number$, static_cast< ::google::protobuf::uint64>(value));\n");
  314. } else {
  315. printer->Print(
  316. "} else {\n"
  317. " unknown_fields_stream.WriteVarint32(tag);\n"
  318. " unknown_fields_stream.WriteVarint32(\n"
  319. " static_cast< ::google::protobuf::uint32>(value));\n");
  320. }
  321. printer->Print("}\n");
  322. }
  323. }
  324. void RepeatedEnumFieldGenerator::
  325. GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
  326. if (!descriptor_->is_packed()) {
  327. // This path is rarely executed, so we use a non-inlined implementation.
  328. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  329. printer->Print(variables_,
  330. "DO_((::google::protobuf::internal::"
  331. "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
  332. " input,\n"
  333. " $number$,\n"
  334. " NULL,\n"
  335. " NULL,\n"
  336. " this->mutable_$name$())));\n");
  337. } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
  338. printer->Print(variables_,
  339. "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
  340. " input,\n"
  341. " $number$,\n"
  342. " $type$_IsValid,\n"
  343. " mutable_unknown_fields(),\n"
  344. " this->mutable_$name$())));\n");
  345. } else {
  346. printer->Print(variables_,
  347. "DO_((::google::protobuf::internal::"
  348. "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
  349. " input,\n"
  350. " $number$,\n"
  351. " $type$_IsValid,\n"
  352. " &unknown_fields_stream,\n"
  353. " this->mutable_$name$())));\n");
  354. }
  355. } else {
  356. printer->Print(variables_,
  357. "::google::protobuf::uint32 length;\n"
  358. "DO_(input->ReadVarint32(&length));\n"
  359. "::google::protobuf::io::CodedInputStream::Limit limit = "
  360. "input->PushLimit(static_cast<int>(length));\n"
  361. "while (input->BytesUntilLimit() > 0) {\n"
  362. " int value;\n"
  363. " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
  364. " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
  365. " input, &value)));\n");
  366. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
  367. printer->Print(variables_,
  368. " add_$name$(static_cast< $type$ >(value));\n");
  369. } else {
  370. printer->Print(variables_,
  371. " if ($type$_IsValid(value)) {\n"
  372. " add_$name$(static_cast< $type$ >(value));\n"
  373. " } else {\n");
  374. if (UseUnknownFieldSet(descriptor_->file(), options_)) {
  375. printer->Print(variables_,
  376. " mutable_unknown_fields()->AddVarint(\n"
  377. " $number$, static_cast< ::google::protobuf::uint64>(value));\n");
  378. } else {
  379. printer->Print(variables_,
  380. " unknown_fields_stream.WriteVarint32(tag);\n"
  381. " unknown_fields_stream.WriteVarint32(\n"
  382. " static_cast< ::google::protobuf::uint32>(value));\n");
  383. }
  384. printer->Print(
  385. " }\n");
  386. }
  387. printer->Print(variables_,
  388. "}\n"
  389. "input->PopLimit(limit);\n");
  390. }
  391. }
  392. void RepeatedEnumFieldGenerator::
  393. GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  394. if (descriptor_->is_packed()) {
  395. // Write the tag and the size.
  396. printer->Print(variables_,
  397. "if (this->$name$_size() > 0) {\n"
  398. " ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
  399. " $number$,\n"
  400. " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
  401. " output);\n"
  402. " output->WriteVarint32(\n"
  403. " static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n"
  404. "}\n");
  405. }
  406. printer->Print(variables_,
  407. "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
  408. if (descriptor_->is_packed()) {
  409. printer->Print(variables_,
  410. " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
  411. " this->$name$(i), output);\n");
  412. } else {
  413. printer->Print(variables_,
  414. " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
  415. " $number$, this->$name$(i), output);\n");
  416. }
  417. printer->Print("}\n");
  418. }
  419. void RepeatedEnumFieldGenerator::
  420. GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  421. if (descriptor_->is_packed()) {
  422. // Write the tag and the size.
  423. printer->Print(variables_,
  424. "if (this->$name$_size() > 0) {\n"
  425. " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
  426. " $number$,\n"
  427. " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
  428. " target);\n"
  429. " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
  430. " static_cast< ::google::protobuf::uint32>(\n"
  431. " _$name$_cached_byte_size_), target);\n"
  432. " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
  433. " this->$name$_, target);\n"
  434. "}\n");
  435. } else {
  436. printer->Print(variables_,
  437. "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
  438. " $number$, this->$name$_, target);\n");
  439. }
  440. }
  441. void RepeatedEnumFieldGenerator::
  442. GenerateByteSize(io::Printer* printer) const {
  443. printer->Print(variables_,
  444. "{\n"
  445. " size_t data_size = 0;\n"
  446. " unsigned int count = static_cast<unsigned int>(this->$name$_size());");
  447. printer->Indent();
  448. printer->Print(variables_,
  449. "for (unsigned int i = 0; i < count; i++) {\n"
  450. " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
  451. " this->$name$(static_cast<int>(i)));\n"
  452. "}\n");
  453. if (descriptor_->is_packed()) {
  454. printer->Print(variables_,
  455. "if (data_size > 0) {\n"
  456. " total_size += $tag_size$ +\n"
  457. " ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
  458. " static_cast< ::google::protobuf::int32>(data_size));\n"
  459. "}\n"
  460. "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
  461. "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
  462. "_$name$_cached_byte_size_ = cached_size;\n"
  463. "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
  464. "total_size += data_size;\n");
  465. } else {
  466. printer->Print(variables_,
  467. "total_size += ($tag_size$UL * count) + data_size;\n");
  468. }
  469. printer->Outdent();
  470. printer->Print("}\n");
  471. }
  472. } // namespace cpp
  473. } // namespace compiler
  474. } // namespace protobuf
  475. } // namespace google