PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://decs.googlecode.com/
C++ | 389 lines | 304 code | 42 blank | 43 comment | 21 complexity | 73c013a78947703882c07efc2c28fddc 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_primitive_field.h>
  34. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  35. #include <google/protobuf/io/printer.h>
  36. #include <google/protobuf/wire_format_inl.h>
  37. #include <google/protobuf/stubs/strutil.h>
  38. namespace google {
  39. namespace protobuf {
  40. namespace compiler {
  41. namespace cpp {
  42. using internal::WireFormat;
  43. namespace {
  44. // For encodings with fixed sizes, returns that size in bytes. Otherwise
  45. // returns -1.
  46. int FixedSize(FieldDescriptor::Type type) {
  47. switch (type) {
  48. case FieldDescriptor::TYPE_INT32 : return -1;
  49. case FieldDescriptor::TYPE_INT64 : return -1;
  50. case FieldDescriptor::TYPE_UINT32 : return -1;
  51. case FieldDescriptor::TYPE_UINT64 : return -1;
  52. case FieldDescriptor::TYPE_SINT32 : return -1;
  53. case FieldDescriptor::TYPE_SINT64 : return -1;
  54. case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
  55. case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
  56. case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
  57. case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
  58. case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize;
  59. case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize;
  60. case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize;
  61. case FieldDescriptor::TYPE_ENUM : return -1;
  62. case FieldDescriptor::TYPE_STRING : return -1;
  63. case FieldDescriptor::TYPE_BYTES : return -1;
  64. case FieldDescriptor::TYPE_GROUP : return -1;
  65. case FieldDescriptor::TYPE_MESSAGE : return -1;
  66. // No default because we want the compiler to complain if any new
  67. // types are added.
  68. }
  69. GOOGLE_LOG(FATAL) << "Can't get here.";
  70. return -1;
  71. }
  72. // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
  73. // repeat code between this and the other field types.
  74. void SetPrimitiveVariables(const FieldDescriptor* descriptor,
  75. map<string, string>* variables) {
  76. (*variables)["name"] = FieldName(descriptor);
  77. (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
  78. (*variables)["default"] = DefaultValue(descriptor);
  79. (*variables)["index"] = SimpleItoa(descriptor->index());
  80. (*variables)["number"] = SimpleItoa(descriptor->number());
  81. (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
  82. (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
  83. (*variables)["tag_size"] = SimpleItoa(
  84. WireFormat::TagSize(descriptor->number(), descriptor->type()));
  85. int fixed_size = FixedSize(descriptor->type());
  86. if (fixed_size != -1) {
  87. (*variables)["fixed_size"] = SimpleItoa(fixed_size);
  88. }
  89. }
  90. } // namespace
  91. // ===================================================================
  92. PrimitiveFieldGenerator::
  93. PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
  94. : descriptor_(descriptor) {
  95. SetPrimitiveVariables(descriptor, &variables_);
  96. }
  97. PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
  98. void PrimitiveFieldGenerator::
  99. GeneratePrivateMembers(io::Printer* printer) const {
  100. printer->Print(variables_, "$type$ $name$_;\n");
  101. }
  102. void PrimitiveFieldGenerator::
  103. GenerateAccessorDeclarations(io::Printer* printer) const {
  104. printer->Print(variables_,
  105. "inline $type$ $name$() const;\n"
  106. "inline void set_$name$($type$ value);\n");
  107. }
  108. void PrimitiveFieldGenerator::
  109. GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  110. printer->Print(variables_,
  111. "inline $type$ $classname$::$name$() const {\n"
  112. " return $name$_;\n"
  113. "}\n"
  114. "inline void $classname$::set_$name$($type$ value) {\n"
  115. " _set_bit($index$);\n"
  116. " $name$_ = value;\n"
  117. "}\n");
  118. }
  119. void PrimitiveFieldGenerator::
  120. GenerateClearingCode(io::Printer* printer) const {
  121. printer->Print(variables_, "$name$_ = $default$;\n");
  122. }
  123. void PrimitiveFieldGenerator::
  124. GenerateMergingCode(io::Printer* printer) const {
  125. printer->Print(variables_, "set_$name$(from.$name$());\n");
  126. }
  127. void PrimitiveFieldGenerator::
  128. GenerateSwappingCode(io::Printer* printer) const {
  129. printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
  130. }
  131. void PrimitiveFieldGenerator::
  132. GenerateConstructorCode(io::Printer* printer) const {
  133. printer->Print(variables_, "$name$_ = $default$;\n");
  134. }
  135. void PrimitiveFieldGenerator::
  136. GenerateMergeFromCodedStream(io::Printer* printer) const {
  137. printer->Print(variables_,
  138. "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
  139. " input, &$name$_));\n"
  140. "_set_bit($index$);\n");
  141. }
  142. void PrimitiveFieldGenerator::
  143. GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  144. printer->Print(variables_,
  145. "::google::protobuf::internal::WireFormat::Write$declared_type$("
  146. "$number$, this->$name$(), output);\n");
  147. }
  148. void PrimitiveFieldGenerator::
  149. GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  150. printer->Print(variables_,
  151. "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
  152. "$number$, this->$name$(), target);\n");
  153. }
  154. void PrimitiveFieldGenerator::
  155. GenerateByteSize(io::Printer* printer) const {
  156. int fixed_size = FixedSize(descriptor_->type());
  157. if (fixed_size == -1) {
  158. printer->Print(variables_,
  159. "total_size += $tag_size$ +\n"
  160. " ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
  161. " this->$name$());\n");
  162. } else {
  163. printer->Print(variables_,
  164. "total_size += $tag_size$ + $fixed_size$;\n");
  165. }
  166. }
  167. // ===================================================================
  168. RepeatedPrimitiveFieldGenerator::
  169. RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
  170. : descriptor_(descriptor) {
  171. SetPrimitiveVariables(descriptor, &variables_);
  172. }
  173. RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
  174. void RepeatedPrimitiveFieldGenerator::
  175. GeneratePrivateMembers(io::Printer* printer) const {
  176. printer->Print(variables_,
  177. "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
  178. if (descriptor_->options().packed() &&
  179. descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
  180. printer->Print(variables_,
  181. "mutable int _$name$_cached_byte_size_;\n");
  182. }
  183. }
  184. void RepeatedPrimitiveFieldGenerator::
  185. GenerateAccessorDeclarations(io::Printer* printer) const {
  186. printer->Print(variables_,
  187. "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const;\n"
  188. "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$();\n"
  189. "inline $type$ $name$(int index) const;\n"
  190. "inline void set_$name$(int index, $type$ value);\n"
  191. "inline void add_$name$($type$ value);\n");
  192. }
  193. void RepeatedPrimitiveFieldGenerator::
  194. GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  195. printer->Print(variables_,
  196. "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
  197. "$classname$::$name$() const {\n"
  198. " return $name$_;\n"
  199. "}\n"
  200. "inline ::google::protobuf::RepeatedField< $type$ >*\n"
  201. "$classname$::mutable_$name$() {\n"
  202. " return &$name$_;\n"
  203. "}\n"
  204. "inline $type$ $classname$::$name$(int index) const {\n"
  205. " return $name$_.Get(index);\n"
  206. "}\n"
  207. "inline void $classname$::set_$name$(int index, $type$ value) {\n"
  208. " $name$_.Set(index, value);\n"
  209. "}\n"
  210. "inline void $classname$::add_$name$($type$ value) {\n"
  211. " $name$_.Add(value);\n"
  212. "}\n");
  213. }
  214. void RepeatedPrimitiveFieldGenerator::
  215. GenerateClearingCode(io::Printer* printer) const {
  216. printer->Print(variables_, "$name$_.Clear();\n");
  217. }
  218. void RepeatedPrimitiveFieldGenerator::
  219. GenerateMergingCode(io::Printer* printer) const {
  220. printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
  221. }
  222. void RepeatedPrimitiveFieldGenerator::
  223. GenerateSwappingCode(io::Printer* printer) const {
  224. printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
  225. }
  226. void RepeatedPrimitiveFieldGenerator::
  227. GenerateConstructorCode(io::Printer* printer) const {
  228. // Not needed for repeated fields.
  229. }
  230. void RepeatedPrimitiveFieldGenerator::
  231. GenerateMergeFromCodedStream(io::Printer* printer) const {
  232. if (descriptor_->options().packed()) {
  233. printer->Print("{\n");
  234. printer->Indent();
  235. printer->Print(variables_,
  236. "::google::protobuf::uint32 length;\n"
  237. "DO_(input->ReadVarint32(&length));\n"
  238. "::google::protobuf::io::CodedInputStream::Limit limit = "
  239. "input->PushLimit(length);\n"
  240. "while (input->BytesUntilLimit() > 0) {\n"
  241. " $type$ value;\n"
  242. " DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
  243. "input, &value));\n"
  244. " add_$name$(value);\n"
  245. "}\n"
  246. "input->PopLimit(limit);\n");
  247. printer->Outdent();
  248. printer->Print("}\n");
  249. } else {
  250. printer->Print(variables_,
  251. "$type$ value;\n"
  252. "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
  253. "input, &value));\n"
  254. "add_$name$(value);\n");
  255. }
  256. }
  257. void RepeatedPrimitiveFieldGenerator::
  258. GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  259. if (descriptor_->options().packed()) {
  260. // Write the tag and the size.
  261. printer->Print(variables_,
  262. "if (this->$name$_size() > 0) {\n"
  263. " ::google::protobuf::internal::WireFormat::WriteTag("
  264. "$number$, "
  265. "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
  266. "output);\n"
  267. " output->WriteVarint32(_$name$_cached_byte_size_);\n"
  268. "}\n");
  269. }
  270. printer->Print(variables_,
  271. "for (int i = 0; i < this->$name$_size(); i++) {\n");
  272. if (descriptor_->options().packed()) {
  273. printer->Print(variables_,
  274. " ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
  275. "this->$name$(i), output);\n");
  276. } else {
  277. printer->Print(variables_,
  278. " ::google::protobuf::internal::WireFormat::Write$declared_type$("
  279. "$number$, this->$name$(i), output);\n");
  280. }
  281. printer->Print("}\n");
  282. }
  283. void RepeatedPrimitiveFieldGenerator::
  284. GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  285. if (descriptor_->options().packed()) {
  286. // Write the tag and the size.
  287. printer->Print(variables_,
  288. "if (this->$name$_size() > 0) {\n"
  289. " target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
  290. "$number$, "
  291. "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
  292. "target);\n"
  293. " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
  294. "_$name$_cached_byte_size_, target);\n"
  295. "}\n");
  296. }
  297. printer->Print(variables_,
  298. "for (int i = 0; i < this->$name$_size(); i++) {\n");
  299. if (descriptor_->options().packed()) {
  300. printer->Print(variables_,
  301. " target = ::google::protobuf::internal::WireFormat::"
  302. "Write$declared_type$NoTagToArray("
  303. "this->$name$(i), target);\n");
  304. } else {
  305. printer->Print(variables_,
  306. " target = ::google::protobuf::internal::WireFormat::"
  307. "Write$declared_type$ToArray("
  308. "$number$, this->$name$(i), target);\n");
  309. }
  310. printer->Print("}\n");
  311. }
  312. void RepeatedPrimitiveFieldGenerator::
  313. GenerateByteSize(io::Printer* printer) const {
  314. printer->Print(variables_,
  315. "{\n"
  316. " int data_size = 0;\n");
  317. printer->Indent();
  318. int fixed_size = FixedSize(descriptor_->type());
  319. if (fixed_size == -1) {
  320. printer->Print(variables_,
  321. "for (int i = 0; i < this->$name$_size(); i++) {\n"
  322. " data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
  323. " this->$name$(i));\n"
  324. "}\n");
  325. } else {
  326. printer->Print(variables_,
  327. "data_size = $fixed_size$ * this->$name$_size();\n");
  328. }
  329. if (descriptor_->options().packed()) {
  330. printer->Print(variables_,
  331. "if (data_size > 0) {\n"
  332. " total_size += $tag_size$ + "
  333. "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
  334. "}\n"
  335. "_$name$_cached_byte_size_ = data_size;\n"
  336. "total_size += data_size;\n");
  337. } else {
  338. printer->Print(variables_,
  339. "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
  340. }
  341. printer->Outdent();
  342. printer->Print("}\n");
  343. }
  344. } // namespace cpp
  345. } // namespace compiler
  346. } // namespace protobuf
  347. } // namespace google