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

/src/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc

http://decs.googlecode.com/
C++ | 352 lines | 270 code | 38 blank | 44 comment | 9 complexity | 92971c84e398fcdf9fdd6b3975f1460c 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 <map>
  34. #include <string>
  35. #include <google/protobuf/compiler/java/java_enum_field.h>
  36. #include <google/protobuf/stubs/common.h>
  37. #include <google/protobuf/compiler/java/java_helpers.h>
  38. #include <google/protobuf/io/printer.h>
  39. #include <google/protobuf/wire_format_inl.h>
  40. #include <google/protobuf/stubs/strutil.h>
  41. namespace google {
  42. namespace protobuf {
  43. namespace compiler {
  44. namespace java {
  45. namespace {
  46. // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
  47. // repeat code between this and the other field types.
  48. void SetEnumVariables(const FieldDescriptor* descriptor,
  49. map<string, string>* variables) {
  50. const EnumValueDescriptor* default_value;
  51. default_value = descriptor->default_value_enum();
  52. string type = ClassName(descriptor->enum_type());
  53. (*variables)["name"] =
  54. UnderscoresToCamelCase(descriptor);
  55. (*variables)["capitalized_name"] =
  56. UnderscoresToCapitalizedCamelCase(descriptor);
  57. (*variables)["number"] = SimpleItoa(descriptor->number());
  58. (*variables)["type"] = type;
  59. (*variables)["default"] = type + "." + default_value->name();
  60. (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
  61. (*variables)["tag_size"] = SimpleItoa(
  62. internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
  63. }
  64. } // namespace
  65. // ===================================================================
  66. EnumFieldGenerator::
  67. EnumFieldGenerator(const FieldDescriptor* descriptor)
  68. : descriptor_(descriptor) {
  69. SetEnumVariables(descriptor, &variables_);
  70. }
  71. EnumFieldGenerator::~EnumFieldGenerator() {}
  72. void EnumFieldGenerator::
  73. GenerateMembers(io::Printer* printer) const {
  74. printer->Print(variables_,
  75. "private boolean has$capitalized_name$;\n"
  76. "private $type$ $name$_ = $default$;\n"
  77. "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
  78. "public $type$ get$capitalized_name$() { return $name$_; }\n");
  79. }
  80. void EnumFieldGenerator::
  81. GenerateBuilderMembers(io::Printer* printer) const {
  82. printer->Print(variables_,
  83. "public boolean has$capitalized_name$() {\n"
  84. " return result.has$capitalized_name$();\n"
  85. "}\n"
  86. "public $type$ get$capitalized_name$() {\n"
  87. " return result.get$capitalized_name$();\n"
  88. "}\n"
  89. "public Builder set$capitalized_name$($type$ value) {\n"
  90. " if (value == null) {\n"
  91. " throw new NullPointerException();\n"
  92. " }\n"
  93. " result.has$capitalized_name$ = true;\n"
  94. " result.$name$_ = value;\n"
  95. " return this;\n"
  96. "}\n"
  97. "public Builder clear$capitalized_name$() {\n"
  98. " result.has$capitalized_name$ = false;\n"
  99. " result.$name$_ = $default$;\n"
  100. " return this;\n"
  101. "}\n");
  102. }
  103. void EnumFieldGenerator::
  104. GenerateMergingCode(io::Printer* printer) const {
  105. printer->Print(variables_,
  106. "if (other.has$capitalized_name$()) {\n"
  107. " set$capitalized_name$(other.get$capitalized_name$());\n"
  108. "}\n");
  109. }
  110. void EnumFieldGenerator::
  111. GenerateBuildingCode(io::Printer* printer) const {
  112. // Nothing to do here for enum types.
  113. }
  114. void EnumFieldGenerator::
  115. GenerateParsingCode(io::Printer* printer) const {
  116. printer->Print(variables_,
  117. "int rawValue = input.readEnum();\n"
  118. "$type$ value = $type$.valueOf(rawValue);\n"
  119. "if (value == null) {\n"
  120. " unknownFields.mergeVarintField($number$, rawValue);\n"
  121. "} else {\n"
  122. " set$capitalized_name$(value);\n"
  123. "}\n");
  124. }
  125. void EnumFieldGenerator::
  126. GenerateSerializationCode(io::Printer* printer) const {
  127. printer->Print(variables_,
  128. "if (has$capitalized_name$()) {\n"
  129. " output.writeEnum($number$, get$capitalized_name$().getNumber());\n"
  130. "}\n");
  131. }
  132. void EnumFieldGenerator::
  133. GenerateSerializedSizeCode(io::Printer* printer) const {
  134. printer->Print(variables_,
  135. "if (has$capitalized_name$()) {\n"
  136. " size += com.google.protobuf.CodedOutputStream\n"
  137. " .computeEnumSize($number$, get$capitalized_name$().getNumber());\n"
  138. "}\n");
  139. }
  140. string EnumFieldGenerator::GetBoxedType() const {
  141. return ClassName(descriptor_->enum_type());
  142. }
  143. // ===================================================================
  144. RepeatedEnumFieldGenerator::
  145. RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
  146. : descriptor_(descriptor) {
  147. SetEnumVariables(descriptor, &variables_);
  148. }
  149. RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
  150. void RepeatedEnumFieldGenerator::
  151. GenerateMembers(io::Printer* printer) const {
  152. printer->Print(variables_,
  153. "private java.util.List<$type$> $name$_ =\n"
  154. " java.util.Collections.emptyList();\n"
  155. "public java.util.List<$type$> get$capitalized_name$List() {\n"
  156. " return $name$_;\n" // note: unmodifiable list
  157. "}\n"
  158. "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
  159. "public $type$ get$capitalized_name$(int index) {\n"
  160. " return $name$_.get(index);\n"
  161. "}\n");
  162. if (descriptor_->options().packed() &&
  163. descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
  164. printer->Print(variables_,
  165. "private int $name$MemoizedSerializedSize;\n");
  166. }
  167. }
  168. void RepeatedEnumFieldGenerator::
  169. GenerateBuilderMembers(io::Printer* printer) const {
  170. printer->Print(variables_,
  171. // Note: We return an unmodifiable list because otherwise the caller
  172. // could hold on to the returned list and modify it after the message
  173. // has been built, thus mutating the message which is supposed to be
  174. // immutable.
  175. "public java.util.List<$type$> get$capitalized_name$List() {\n"
  176. " return java.util.Collections.unmodifiableList(result.$name$_);\n"
  177. "}\n"
  178. "public int get$capitalized_name$Count() {\n"
  179. " return result.get$capitalized_name$Count();\n"
  180. "}\n"
  181. "public $type$ get$capitalized_name$(int index) {\n"
  182. " return result.get$capitalized_name$(index);\n"
  183. "}\n"
  184. "public Builder set$capitalized_name$(int index, $type$ value) {\n"
  185. " if (value == null) {\n"
  186. " throw new NullPointerException();\n"
  187. " }\n"
  188. " result.$name$_.set(index, value);\n"
  189. " return this;\n"
  190. "}\n"
  191. "public Builder add$capitalized_name$($type$ value) {\n"
  192. " if (value == null) {\n"
  193. " throw new NullPointerException();\n"
  194. " }\n"
  195. " if (result.$name$_.isEmpty()) {\n"
  196. " result.$name$_ = new java.util.ArrayList<$type$>();\n"
  197. " }\n"
  198. " result.$name$_.add(value);\n"
  199. " return this;\n"
  200. "}\n"
  201. "public Builder addAll$capitalized_name$(\n"
  202. " java.lang.Iterable<? extends $type$> values) {\n"
  203. " if (result.$name$_.isEmpty()) {\n"
  204. " result.$name$_ = new java.util.ArrayList<$type$>();\n"
  205. " }\n"
  206. " super.addAll(values, result.$name$_);\n"
  207. " return this;\n"
  208. "}\n"
  209. "public Builder clear$capitalized_name$() {\n"
  210. " result.$name$_ = java.util.Collections.emptyList();\n"
  211. " return this;\n"
  212. "}\n");
  213. }
  214. void RepeatedEnumFieldGenerator::
  215. GenerateMergingCode(io::Printer* printer) const {
  216. printer->Print(variables_,
  217. "if (!other.$name$_.isEmpty()) {\n"
  218. " if (result.$name$_.isEmpty()) {\n"
  219. " result.$name$_ = new java.util.ArrayList<$type$>();\n"
  220. " }\n"
  221. " result.$name$_.addAll(other.$name$_);\n"
  222. "}\n");
  223. }
  224. void RepeatedEnumFieldGenerator::
  225. GenerateBuildingCode(io::Printer* printer) const {
  226. printer->Print(variables_,
  227. "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
  228. " result.$name$_ =\n"
  229. " java.util.Collections.unmodifiableList(result.$name$_);\n"
  230. "}\n");
  231. }
  232. void RepeatedEnumFieldGenerator::
  233. GenerateParsingCode(io::Printer* printer) const {
  234. // If packed, set up the while loop
  235. if (descriptor_->options().packed()) {
  236. printer->Print(variables_,
  237. "int length = input.readRawVarint32();\n"
  238. "int oldLimit = input.pushLimit(length);\n"
  239. "while(input.getBytesUntilLimit() > 0) {\n");
  240. printer->Indent();
  241. }
  242. // Read and store the enum
  243. printer->Print(variables_,
  244. "int rawValue = input.readEnum();\n"
  245. "$type$ value = $type$.valueOf(rawValue);\n"
  246. "if (value == null) {\n"
  247. " unknownFields.mergeVarintField($number$, rawValue);\n"
  248. "} else {\n"
  249. " add$capitalized_name$(value);\n"
  250. "}\n");
  251. if (descriptor_->options().packed()) {
  252. printer->Outdent();
  253. printer->Print(variables_,
  254. "}\n"
  255. "input.popLimit(oldLimit);\n");
  256. }
  257. }
  258. void RepeatedEnumFieldGenerator::
  259. GenerateSerializationCode(io::Printer* printer) const {
  260. if (descriptor_->options().packed()) {
  261. printer->Print(variables_,
  262. "if (get$capitalized_name$List().size() > 0) {\n"
  263. " output.writeRawVarint32($tag$);\n"
  264. " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
  265. "}\n"
  266. "for ($type$ element : get$capitalized_name$List()) {\n"
  267. " output.writeEnumNoTag(element.getNumber());\n"
  268. "}\n");
  269. } else {
  270. printer->Print(variables_,
  271. "for ($type$ element : get$capitalized_name$List()) {\n"
  272. " output.writeEnum($number$, element.getNumber());\n"
  273. "}\n");
  274. }
  275. }
  276. void RepeatedEnumFieldGenerator::
  277. GenerateSerializedSizeCode(io::Printer* printer) const {
  278. printer->Print(variables_,
  279. "{\n"
  280. " int dataSize = 0;\n");
  281. printer->Indent();
  282. printer->Print(variables_,
  283. "for ($type$ element : get$capitalized_name$List()) {\n"
  284. " dataSize += com.google.protobuf.CodedOutputStream\n"
  285. " .computeEnumSizeNoTag(element.getNumber());\n"
  286. "}\n");
  287. printer->Print(
  288. "size += dataSize;\n");
  289. if (descriptor_->options().packed()) {
  290. printer->Print(variables_,
  291. "if (!get$capitalized_name$List().isEmpty()) {"
  292. " size += $tag_size$;\n"
  293. " size += com.google.protobuf.CodedOutputStream\n"
  294. " .computeRawVarint32Size(dataSize);\n"
  295. "}");
  296. } else {
  297. printer->Print(variables_,
  298. "size += $tag_size$ * get$capitalized_name$List().size();\n");
  299. }
  300. // cache the data size for packed fields.
  301. if (descriptor_->options().packed()) {
  302. printer->Print(variables_,
  303. "$name$MemoizedSerializedSize = dataSize;\n");
  304. }
  305. printer->Outdent();
  306. printer->Print("}\n");
  307. }
  308. string RepeatedEnumFieldGenerator::GetBoxedType() const {
  309. return ClassName(descriptor_->enum_type());
  310. }
  311. } // namespace java
  312. } // namespace compiler
  313. } // namespace protobuf
  314. } // namespace google