javamicro_enum_field.cc revision e2d542951c059563a3b7f74c257dac4f222d9dc5
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
31// Author: kenton@google.com (Kenton Varda)
32//  Based on original Protocol Buffers design by
33//  Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <map>
36#include <string>
37
38#include <google/protobuf/compiler/javamicro/javamicro_enum_field.h>
39#include <google/protobuf/stubs/common.h>
40#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
41#include <google/protobuf/io/printer.h>
42#include <google/protobuf/wire_format.h>
43#include <google/protobuf/stubs/strutil.h>
44
45namespace google {
46namespace protobuf {
47namespace compiler {
48namespace javamicro {
49
50namespace {
51
52// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
53//   repeat code between this and the other field types.
54void SetEnumVariables(const Params& params,
55    const FieldDescriptor* descriptor, map<string, string>* variables) {
56  (*variables)["name"] =
57    UnderscoresToCamelCase(descriptor);
58  (*variables)["capitalized_name"] =
59    UnderscoresToCapitalizedCamelCase(descriptor);
60  (*variables)["number"] = SimpleItoa(descriptor->number());
61  (*variables)["type"] = "int";
62  (*variables)["default"] = DefaultValue(params, descriptor);
63  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
64  (*variables)["tag_size"] = SimpleItoa(
65      internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
66  (*variables)["message_name"] = descriptor->containing_type()->name();
67}
68
69}  // namespace
70
71// ===================================================================
72
73EnumFieldGenerator::
74EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
75  : FieldGenerator(params), descriptor_(descriptor) {
76  SetEnumVariables(params, descriptor, &variables_);
77}
78
79EnumFieldGenerator::~EnumFieldGenerator() {}
80
81void EnumFieldGenerator::
82GenerateMembers(io::Printer* printer) const {
83  printer->Print(variables_,
84    "private boolean has$capitalized_name$;\n"
85    "private int $name$_ = $default$;\n"
86    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
87    "public int get$capitalized_name$() { return $name$_; }\n"
88    "public $message_name$ set$capitalized_name$(int value) {\n"
89    "  has$capitalized_name$ = true;\n"
90    "  $name$_ = value;\n"
91    "  return this;\n"
92    "}\n"
93    "public $message_name$ clear$capitalized_name$() {\n"
94    "  has$capitalized_name$ = false;\n"
95    "  $name$_ = $default$;\n"
96    "  return this;\n"
97    "}\n");
98}
99
100void EnumFieldGenerator::
101GenerateMergingCode(io::Printer* printer) const {
102  printer->Print(variables_,
103    "what is other??"
104    "if (other.has$capitalized_name$()) {\n"
105    "  set$capitalized_name$(other.get$capitalized_name$());\n"
106    "}\n");
107}
108
109void EnumFieldGenerator::
110GenerateParsingCode(io::Printer* printer) const {
111  printer->Print(variables_,
112    "  set$capitalized_name$(input.readInt32());\n");
113}
114
115void EnumFieldGenerator::
116GenerateSerializationCode(io::Printer* printer) const {
117  printer->Print(variables_,
118    "if (has$capitalized_name$()) {\n"
119    "  output.writeInt32($number$, get$capitalized_name$());\n"
120    "}\n");
121}
122
123void EnumFieldGenerator::
124GenerateSerializedSizeCode(io::Printer* printer) const {
125  printer->Print(variables_,
126    "if (has$capitalized_name$()) {\n"
127    "  size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
128    "    .computeInt32Size($number$, get$capitalized_name$());\n"
129    "}\n");
130}
131
132string EnumFieldGenerator::GetBoxedType() const {
133  return ClassName(params_, descriptor_->enum_type());
134}
135
136// ===================================================================
137
138RepeatedEnumFieldGenerator::
139RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
140  : FieldGenerator(params), descriptor_(descriptor) {
141  SetEnumVariables(params, descriptor, &variables_);
142  if (descriptor_->options().packed()) {
143    GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
144  }
145}
146
147RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
148
149void RepeatedEnumFieldGenerator::
150GenerateMembers(io::Printer* printer) const {
151  if (params_.java_use_vector()) {
152    printer->Print(variables_,
153      "private java.util.Vector $name$_ = new java.util.Vector();\n"
154      "public java.util.Vector get$capitalized_name$List() {\n"
155      "  return $name$_;\n"
156      "}\n"
157      "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
158      "public int get$capitalized_name$(int index) {\n"
159      "  return ((Integer)$name$_.elementAt(index)).intValue();\n"
160      "}\n"
161      "public $message_name$ set$capitalized_name$(int index, int value) {\n"
162      "  $name$_.setElementAt(new Integer(value), index);\n"
163      "  return this;\n"
164      "}\n"
165      "public $message_name$ add$capitalized_name$(int value) {\n"
166      "  $name$_.addElement(new Integer(value));\n"
167      "  return this;\n"
168      "}\n"
169      "public $message_name$ clear$capitalized_name$() {\n"
170      "  $name$_.removeAllElements();\n"
171      "  return this;\n"
172      "}\n");
173  } else {
174    printer->Print(variables_,
175      "private java.util.List<Integer> $name$_ =\n"
176      "  java.util.Collections.emptyList();\n"
177      "public java.util.List<Integer> get$capitalized_name$List() {\n"
178      "  return $name$_;\n"   // note:  unmodifiable list
179      "}\n"
180      "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
181      "public int get$capitalized_name$(int index) {\n"
182      "  return $name$_.get(index);\n"
183      "}\n"
184      "public $message_name$ set$capitalized_name$(int index, int value) {\n"
185      "  $name$_.set(index, value);\n"
186      "  return this;\n"
187      "}\n"
188      "public $message_name$ add$capitalized_name$(int value) {\n"
189      "  if ($name$_.isEmpty()) {\n"
190      "    $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
191      "  }\n"
192      "  $name$_.add(value);\n"
193      "  return this;\n"
194      "}\n"
195      "public $message_name$ clear$capitalized_name$() {\n"
196      "  $name$_ = java.util.Collections.emptyList();\n"
197      "  return this;\n"
198      "}\n");
199  }
200  if (descriptor_->options().packed()) {
201    printer->Print(variables_,
202      "private int $name$MemoizedSerializedSize;\n");
203  }
204}
205
206void RepeatedEnumFieldGenerator::
207GenerateMergingCode(io::Printer* printer) const {
208  if (params_.java_use_vector()) {
209    printer->Print(variables_,
210      "if (other.$name$_.size() != 0) {\n"
211      "  for (int i = 0; i < other.$name$_.size(); i++)) {\n"
212      "    result.$name$_.addElement(other.$name$_.elementAt(i));\n"
213      "  }\n"
214      "}\n");
215  } else {
216    printer->Print(variables_,
217      "if (!other.$name$_.isEmpty()) {\n"
218      "  if (result.$name$_.isEmpty()) {\n"
219      "    result.$name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
220      "  }\n"
221      "  result.$name$_.addAll(other.$name$_);\n"
222      "}\n");
223  }
224}
225
226void RepeatedEnumFieldGenerator::
227GenerateParsingCode(io::Printer* printer) const {
228  // If packed, set up the while loop
229  if (descriptor_->options().packed()) {
230    printer->Print(variables_,
231      "int length = input.readRawVarint32();\n"
232      "int oldLimit = input.pushLimit(length);\n"
233      "while(input.getBytesUntilLimit() > 0) {\n");
234    printer->Indent();
235  }
236
237  // Read and store the enum
238  printer->Print(variables_,
239    "  add$capitalized_name$(input.readInt32());\n");
240
241  if (descriptor_->options().packed()) {
242    printer->Outdent();
243    printer->Print(variables_,
244      "}\n"
245      "input.popLimit(oldLimit);\n");
246  }
247}
248
249void RepeatedEnumFieldGenerator::
250GenerateSerializationCode(io::Printer* printer) const {
251  if (descriptor_->options().packed()) {
252    printer->Print(variables_,
253        "if (get$capitalized_name$List().size() > 0) {\n"
254        "  output.writeRawVarint32($tag$);\n"
255        "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
256        "}\n");
257    if (params_.java_use_vector()) {
258      printer->Print(variables_,
259        "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
260        "  output.writeRawVarint32(get$capitalized_name$(i));\n"
261        "}\n");
262    } else {
263      printer->Print(variables_,
264        "for ($type$ element : get$capitalized_name$List()) {\n"
265        "  output.writeRawVarint32(element.getNumber());\n"
266        "}\n");
267    }
268  } else {
269    if (params_.java_use_vector()) {
270      printer->Print(variables_,
271        "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
272        "  output.writeInt32($number$, (int)get$capitalized_name$(i));\n"
273        "}\n");
274    } else {
275      printer->Print(variables_,
276        "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
277        "  output.writeInt32($number$, element);\n"
278        "}\n");
279    }
280  }
281}
282
283void RepeatedEnumFieldGenerator::
284GenerateSerializedSizeCode(io::Printer* printer) const {
285  printer->Print(variables_,
286    "{\n"
287    "  int dataSize = 0;\n");
288    printer->Indent();
289  if (params_.java_use_vector()) {
290    printer->Print(variables_,
291      "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
292      "  dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
293      "    .computeInt32SizeNoTag(get$capitalized_name$(i));\n"
294      "}\n");
295  } else {
296    printer->Print(variables_,
297      "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
298      "  dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
299      "    .computeInt32SizeNoTag(element);\n"
300      "}\n");
301  }
302  printer->Print(
303      "size += dataSize;\n");
304  if (descriptor_->options().packed()) {
305      printer->Print(variables_,
306        "if (get$capitalized_name$List().size() != 0) {"
307        "  size += $tag_size$;\n"
308        "  size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
309        "    .computeRawVarint32Size(dataSize);\n"
310        "}");
311  } else {
312    printer->Print(variables_,
313        "size += $tag_size$ * get$capitalized_name$List().size();\n");
314  }
315
316  // cache the data size for packed fields.
317  if (descriptor_->options().packed()) {
318    printer->Print(variables_,
319      "$name$MemoizedSerializedSize = dataSize;\n");
320  }
321
322  printer->Outdent();
323  printer->Print("}\n");
324}
325
326string RepeatedEnumFieldGenerator::GetBoxedType() const {
327  return ClassName(params_, descriptor_->enum_type());
328}
329
330}  // namespace javamicro
331}  // namespace compiler
332}  // namespace protobuf
333}  // namespace google
334