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