javanano_message_field.cc revision 5cc242074f189837b38e7768b57ccfb0bca258df
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/javanano/javanano_message_field.h>
39#include <google/protobuf/compiler/javanano/javanano_helpers.h>
40#include <google/protobuf/io/printer.h>
41#include <google/protobuf/wire_format.h>
42#include <google/protobuf/stubs/strutil.h>
43
44namespace google {
45namespace protobuf {
46namespace compiler {
47namespace javanano {
48
49using internal::WireFormat;
50using internal::WireFormatLite;
51
52namespace {
53
54// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
55//   repeat code between this and the other field types.
56void SetMessageVariables(const Params& params,
57    const FieldDescriptor* descriptor, map<string, string>* variables) {
58  (*variables)["name"] =
59    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
60  (*variables)["capitalized_name"] =
61    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
62  (*variables)["number"] = SimpleItoa(descriptor->number());
63  (*variables)["type"] = ClassName(params, descriptor->message_type());
64  (*variables)["group_or_message"] =
65    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
66    "Group" : "Message";
67  (*variables)["message_name"] = descriptor->containing_type()->name();
68  //(*variables)["message_type"] = descriptor->message_type()->name();
69  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
70}
71
72}  // namespace
73
74// ===================================================================
75
76MessageFieldGenerator::
77MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
78  : FieldGenerator(params), descriptor_(descriptor) {
79  SetMessageVariables(params, descriptor, &variables_);
80}
81
82MessageFieldGenerator::~MessageFieldGenerator() {}
83
84void MessageFieldGenerator::
85GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
86  printer->Print(variables_,
87    "public $type$ $name$;\n");
88}
89
90void MessageFieldGenerator::
91GenerateClearCode(io::Printer* printer) const {
92  printer->Print(variables_,
93    "$name$ = null;\n");
94}
95
96void MessageFieldGenerator::
97GenerateMergingCode(io::Printer* printer) const {
98  printer->Print(variables_,
99    "if (this.$name$ == null) {\n"
100    "  this.$name$ = new $type$();\n"
101    "}\n");
102
103  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
104    printer->Print(variables_,
105      "input.readGroup(this.$name$, $number$);\n");
106  } else {
107    printer->Print(variables_,
108      "input.readMessage(this.$name$);\n");
109  }
110}
111
112void MessageFieldGenerator::
113GenerateSerializationCode(io::Printer* printer) const {
114  printer->Print(variables_,
115    "if (this.$name$ != null) {\n"
116    "  output.write$group_or_message$($number$, this.$name$);\n"
117    "}\n");
118}
119
120void MessageFieldGenerator::
121GenerateSerializedSizeCode(io::Printer* printer) const {
122  printer->Print(variables_,
123    "if (this.$name$ != null) {\n"
124    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
125    "    .compute$group_or_message$Size($number$, this.$name$);\n"
126    "}\n");
127}
128
129void MessageFieldGenerator::
130GenerateEqualsCode(io::Printer* printer) const {
131  printer->Print(variables_,
132    "if (this.$name$ == null) { \n"
133    "  if (other.$name$ != null) {\n"
134    "    return false;\n"
135    "  }\n"
136    "} else {\n"
137    "  if (!this.$name$.equals(other.$name$)) {\n"
138    "    return false;\n"
139    "  }\n"
140    "}\n");
141}
142
143void MessageFieldGenerator::
144GenerateHashCodeCode(io::Printer* printer) const {
145  printer->Print(variables_,
146    "result = 31 * result +\n"
147    "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
148}
149
150// ===================================================================
151
152RepeatedMessageFieldGenerator::
153RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
154  : FieldGenerator(params), descriptor_(descriptor) {
155  SetMessageVariables(params, descriptor, &variables_);
156}
157
158RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
159
160void RepeatedMessageFieldGenerator::
161GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
162  printer->Print(variables_,
163    "public $type$[] $name$;\n");
164}
165
166void RepeatedMessageFieldGenerator::
167GenerateClearCode(io::Printer* printer) const {
168  printer->Print(variables_,
169    "$name$ = $type$.emptyArray();\n");
170}
171
172void RepeatedMessageFieldGenerator::
173GenerateMergingCode(io::Printer* printer) const {
174  // First, figure out the length of the array, then parse.
175  printer->Print(variables_,
176    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
177    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
178    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
179    "$type$[] newArray =\n"
180    "    new $type$[i + arrayLength];\n"
181    "if (i != 0) {\n"
182    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
183    "}\n"
184    "for (; i < newArray.length - 1; i++) {\n"
185    "  newArray[i] = new $type$();\n");
186
187  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
188    printer->Print(variables_,
189      "  input.readGroup(newArray[i], $number$);\n");
190  } else {
191    printer->Print(variables_,
192      "  input.readMessage(newArray[i]);\n");
193  }
194
195  printer->Print(variables_,
196    "  input.readTag();\n"
197    "}\n"
198    "// Last one without readTag.\n"
199    "newArray[i] = new $type$();\n");
200
201  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
202    printer->Print(variables_,
203      "input.readGroup(newArray[i], $number$);\n");
204  } else {
205    printer->Print(variables_,
206      "input.readMessage(newArray[i]);\n");
207  }
208
209  printer->Print(variables_,
210    "this.$name$ = newArray;\n");
211}
212
213void RepeatedMessageFieldGenerator::
214GenerateSerializationCode(io::Printer* printer) const {
215  printer->Print(variables_,
216    "if (this.$name$ != null && this.$name$.length > 0) {\n"
217    "  for (int i = 0; i < this.$name$.length; i++) {\n"
218    "    $type$ element = this.$name$[i];\n"
219    "    if (element != null) {\n"
220    "      output.write$group_or_message$($number$, element);\n"
221    "    }\n"
222    "  }\n"
223    "}\n");
224}
225
226void RepeatedMessageFieldGenerator::
227GenerateSerializedSizeCode(io::Printer* printer) const {
228  printer->Print(variables_,
229    "if (this.$name$ != null && this.$name$.length > 0) {\n"
230    "  for (int i = 0; i < this.$name$.length; i++) {\n"
231    "    $type$ element = this.$name$[i];\n"
232    "    if (element != null) {\n"
233    "      size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
234    "        .compute$group_or_message$Size($number$, element);\n"
235    "    }\n"
236    "  }\n"
237    "}\n");
238}
239
240void RepeatedMessageFieldGenerator::
241GenerateEqualsCode(io::Printer* printer) const {
242  printer->Print(variables_,
243    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
244    "    this.$name$, other.$name$)) {\n"
245    "  return false;\n"
246    "}\n");
247}
248
249void RepeatedMessageFieldGenerator::
250GenerateHashCodeCode(io::Printer* printer) const {
251  printer->Print(variables_,
252    "result = 31 * result\n"
253    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
254}
255
256}  // namespace javanano
257}  // namespace compiler
258}  // namespace protobuf
259}  // namespace google
260