javanano_message_field.cc revision 64d8d8f89050c5ada85341f967af391f4716a7cb
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    UnderscoresToCamelCase(descriptor);
60  (*variables)["capitalized_name"] =
61    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) const {
86  printer->Print(variables_,
87    "public $type$ $name$ = null;\n");
88}
89
90void MessageFieldGenerator::
91GenerateMergingCode(io::Printer* printer) const {
92  printer->Print(variables_,
93    "if (other.$name$ != null) {\n"
94    "  merge$capitalized_name$(other.$name$);\n"
95    "}\n");
96}
97
98void MessageFieldGenerator::
99GenerateParsingCode(io::Printer* printer) const {
100  printer->Print(variables_,
101    "$name$ = new $type$();\n");
102
103  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
104    printer->Print(variables_,
105      "input.readGroup($name$, $number$);\n");
106  } else {
107    printer->Print(variables_,
108      "input.readMessage($name$);\n");
109  }
110}
111
112void MessageFieldGenerator::
113GenerateSerializationCode(io::Printer* printer) const {
114  printer->Print(variables_,
115    "if ($name$ != null) {\n"
116    "  output.write$group_or_message$($number$, $name$);\n"
117    "}\n");
118}
119
120void MessageFieldGenerator::
121GenerateSerializedSizeCode(io::Printer* printer) const {
122  printer->Print(variables_,
123    "if ($name$ != null) {\n"
124    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
125    "    .compute$group_or_message$Size($number$, $name$);\n"
126    "}\n");
127}
128
129string MessageFieldGenerator::GetBoxedType() const {
130  return ClassName(params_, descriptor_->message_type());
131}
132
133// ===================================================================
134
135RepeatedMessageFieldGenerator::
136RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
137  : FieldGenerator(params), descriptor_(descriptor) {
138  SetMessageVariables(params, descriptor, &variables_);
139}
140
141RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
142
143void RepeatedMessageFieldGenerator::
144GenerateMembers(io::Printer* printer) const {
145  printer->Print(variables_,
146    "public $type$[] $name$ = $type$.EMPTY_ARRAY;\n");
147}
148
149void RepeatedMessageFieldGenerator::
150GenerateMergingCode(io::Printer* printer) const {
151  printer->Print(variables_,
152    "if (other.$name$.length > 0) {\n"
153    "  $type$[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n"
154    "  java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n"
155    "  result.$name$ = merged;\n"
156    "}\n");
157}
158
159void RepeatedMessageFieldGenerator::
160GenerateParsingCode(io::Printer* printer) const {
161  // First, figure out the length of the array, then parse.
162  printer->Print(variables_,
163    "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n"
164    "int i = $name$.length;\n"
165    "$name$ = java.util.Arrays.copyOf($name$, i + arrayLength);\n"
166    "for (; i < $name$.length - 1; i++) {\n"
167    "  $name$[i] = new $type$();\n");
168
169  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
170    printer->Print(variables_,
171      "  input.readGroup($name$[i], $number$);\n");
172  } else {
173    printer->Print(variables_,
174      "  input.readMessage($name$[i]);\n");
175  }
176
177  printer->Print(variables_,
178    "  input.readTag();\n"
179    "}\n"
180    "// Last one without readTag.\n"
181    "$name$[i] = new $type$();\n");
182
183  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
184    printer->Print(variables_,
185      "input.readGroup($name$[i], $number$);\n");
186  } else {
187    printer->Print(variables_,
188      "input.readMessage($name$[i]);\n");
189  }
190}
191
192void RepeatedMessageFieldGenerator::
193GenerateSerializationCode(io::Printer* printer) const {
194  printer->Print(variables_,
195    "for ($type$ element : $name$) {\n"
196    "  output.write$group_or_message$($number$, element);\n"
197    "}\n");
198}
199
200void RepeatedMessageFieldGenerator::
201GenerateSerializedSizeCode(io::Printer* printer) const {
202  printer->Print(variables_,
203    "for ($type$ element : $name$) {\n"
204    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
205    "    .compute$group_or_message$Size($number$, element);\n"
206    "}\n");
207}
208
209string RepeatedMessageFieldGenerator::GetBoxedType() const {
210  return ClassName(params_, descriptor_->message_type());
211}
212
213}  // namespace javanano
214}  // namespace compiler
215}  // namespace protobuf
216}  // namespace google
217