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
44 namespace google {
45 namespace protobuf {
46 namespace compiler {
47 namespace javanano {
48
49 using internal::WireFormat;
50 using internal::WireFormatLite;
51
52 namespace {
53
54 // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
55 // repeat code between this and the other field types.
SetMessageVariables(const Params & params,const FieldDescriptor * descriptor,map<string,string> * variables)56 void 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
76 MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor * descriptor,const Params & params)77 MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
78 : FieldGenerator(params), descriptor_(descriptor) {
79 SetMessageVariables(params, descriptor, &variables_);
80 }
81
~MessageFieldGenerator()82 MessageFieldGenerator::~MessageFieldGenerator() {}
83
84 void MessageFieldGenerator::
GenerateMembers(io::Printer * printer) const85 GenerateMembers(io::Printer* printer) const {
86 printer->Print(variables_,
87 "public $type$ $name$ = null;\n");
88 }
89
90 void MessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const91 GenerateParsingCode(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
104 void MessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const105 GenerateSerializationCode(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
112 void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const113 GenerateSerializedSizeCode(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
GetBoxedType() const121 string MessageFieldGenerator::GetBoxedType() const {
122 return ClassName(params_, descriptor_->message_type());
123 }
124
125 // ===================================================================
126
127 RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Params & params)128 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
129 : FieldGenerator(params), descriptor_(descriptor) {
130 SetMessageVariables(params, descriptor, &variables_);
131 }
132
~RepeatedMessageFieldGenerator()133 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
134
135 void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer * printer) const136 GenerateMembers(io::Printer* printer) const {
137 printer->Print(variables_,
138 "public $type$[] $name$ = $type$.EMPTY_ARRAY;\n");
139 }
140
141 void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const142 GenerateParsingCode(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
174 void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const175 GenerateSerializationCode(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
182 void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const183 GenerateSerializedSizeCode(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
GetBoxedType() const191 string 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