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_primitive_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
45 namespace google {
46 namespace protobuf {
47 namespace compiler {
48 namespace javamicro {
49
50 using internal::WireFormat;
51 using internal::WireFormatLite;
52
53 namespace {
54
PrimitiveTypeName(JavaType type)55 const char* PrimitiveTypeName(JavaType type) {
56 switch (type) {
57 case JAVATYPE_INT : return "int";
58 case JAVATYPE_LONG : return "long";
59 case JAVATYPE_FLOAT : return "float";
60 case JAVATYPE_DOUBLE : return "double";
61 case JAVATYPE_BOOLEAN: return "boolean";
62 case JAVATYPE_STRING : return "java.lang.String";
63 case JAVATYPE_BYTES : return "com.google.protobuf.micro.ByteStringMicro";
64 case JAVATYPE_ENUM : return NULL;
65 case JAVATYPE_MESSAGE: return NULL;
66
67 // No default because we want the compiler to complain if any new
68 // JavaTypes are added.
69 }
70
71 GOOGLE_LOG(FATAL) << "Can't get here.";
72 return NULL;
73 }
74
IsReferenceType(JavaType type)75 bool IsReferenceType(JavaType type) {
76 switch (type) {
77 case JAVATYPE_INT : return false;
78 case JAVATYPE_LONG : return false;
79 case JAVATYPE_FLOAT : return false;
80 case JAVATYPE_DOUBLE : return false;
81 case JAVATYPE_BOOLEAN: return false;
82 case JAVATYPE_STRING : return true;
83 case JAVATYPE_BYTES : return true;
84 case JAVATYPE_ENUM : return false;
85 case JAVATYPE_MESSAGE: return true;
86
87 // No default because we want the compiler to complain if any new
88 // JavaTypes are added.
89 }
90
91 GOOGLE_LOG(FATAL) << "Can't get here.";
92 return false;
93 }
94
GetCapitalizedType(const FieldDescriptor * field)95 const char* GetCapitalizedType(const FieldDescriptor* field) {
96 switch (field->type()) {
97 case FieldDescriptor::TYPE_INT32 : return "Int32" ;
98 case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
99 case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
100 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
101 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
102 case FieldDescriptor::TYPE_INT64 : return "Int64" ;
103 case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
104 case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
105 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
106 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
107 case FieldDescriptor::TYPE_FLOAT : return "Float" ;
108 case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
109 case FieldDescriptor::TYPE_BOOL : return "Bool" ;
110 case FieldDescriptor::TYPE_STRING : return "String" ;
111 case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
112 case FieldDescriptor::TYPE_ENUM : return "Enum" ;
113 case FieldDescriptor::TYPE_GROUP : return "Group" ;
114 case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
115
116 // No default because we want the compiler to complain if any new
117 // types are added.
118 }
119
120 GOOGLE_LOG(FATAL) << "Can't get here.";
121 return NULL;
122 }
123
124 // For encodings with fixed sizes, returns that size in bytes. Otherwise
125 // returns -1.
FixedSize(FieldDescriptor::Type type)126 int FixedSize(FieldDescriptor::Type type) {
127 switch (type) {
128 case FieldDescriptor::TYPE_INT32 : return -1;
129 case FieldDescriptor::TYPE_INT64 : return -1;
130 case FieldDescriptor::TYPE_UINT32 : return -1;
131 case FieldDescriptor::TYPE_UINT64 : return -1;
132 case FieldDescriptor::TYPE_SINT32 : return -1;
133 case FieldDescriptor::TYPE_SINT64 : return -1;
134 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
135 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
136 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
137 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
138 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
139 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
140
141 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
142 case FieldDescriptor::TYPE_ENUM : return -1;
143
144 case FieldDescriptor::TYPE_STRING : return -1;
145 case FieldDescriptor::TYPE_BYTES : return -1;
146 case FieldDescriptor::TYPE_GROUP : return -1;
147 case FieldDescriptor::TYPE_MESSAGE : return -1;
148
149 // No default because we want the compiler to complain if any new
150 // types are added.
151 }
152 GOOGLE_LOG(FATAL) << "Can't get here.";
153 return -1;
154 }
155
156 // Return true if the type is a that has variable length
157 // for instance String's.
IsVariableLenType(JavaType type)158 bool IsVariableLenType(JavaType type) {
159 switch (type) {
160 case JAVATYPE_INT : return false;
161 case JAVATYPE_LONG : return false;
162 case JAVATYPE_FLOAT : return false;
163 case JAVATYPE_DOUBLE : return false;
164 case JAVATYPE_BOOLEAN: return false;
165 case JAVATYPE_STRING : return true;
166 case JAVATYPE_BYTES : return true;
167 case JAVATYPE_ENUM : return false;
168 case JAVATYPE_MESSAGE: return true;
169
170 // No default because we want the compiler to complain if any new
171 // JavaTypes are added.
172 }
173
174 GOOGLE_LOG(FATAL) << "Can't get here.";
175 return false;
176 }
177
IsFastStringHandling(const FieldDescriptor * descriptor,const Params params)178 bool IsFastStringHandling(const FieldDescriptor* descriptor,
179 const Params params) {
180 return ((params.optimization() == JAVAMICRO_OPT_SPEED)
181 && (GetJavaType(descriptor) == JAVATYPE_STRING));
182 }
183
SetPrimitiveVariables(const FieldDescriptor * descriptor,const Params params,map<string,string> * variables)184 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
185 map<string, string>* variables) {
186 (*variables)["name"] =
187 UnderscoresToCamelCase(descriptor);
188 (*variables)["capitalized_name"] =
189 UnderscoresToCapitalizedCamelCase(descriptor);
190 (*variables)["number"] = SimpleItoa(descriptor->number());
191 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
192 (*variables)["default"] = DefaultValue(params, descriptor);
193 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
194 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
195 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
196 (*variables)["tag_size"] = SimpleItoa(
197 WireFormat::TagSize(descriptor->number(), descriptor->type()));
198 if (IsReferenceType(GetJavaType(descriptor))) {
199 (*variables)["null_check"] =
200 " if (value == null) {\n"
201 " throw new NullPointerException();\n"
202 " }\n";
203 } else {
204 (*variables)["null_check"] = "";
205 }
206 int fixed_size = FixedSize(descriptor->type());
207 if (fixed_size != -1) {
208 (*variables)["fixed_size"] = SimpleItoa(fixed_size);
209 }
210 (*variables)["message_name"] = descriptor->containing_type()->name();
211 }
212 } // namespace
213
214 // ===================================================================
215
216 PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)217 PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
218 : FieldGenerator(params), descriptor_(descriptor) {
219 SetPrimitiveVariables(descriptor, params, &variables_);
220 }
221
~PrimitiveFieldGenerator()222 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
223
224 void PrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer) const225 GenerateMembers(io::Printer* printer) const {
226 printer->Print(variables_,
227 "private boolean has$capitalized_name$;\n"
228 "private $type$ $name$_ = $default$;\n"
229 "public $type$ get$capitalized_name$() { return $name$_; }\n"
230 "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n");
231 if (IsFastStringHandling(descriptor_, params_)) {
232 printer->Print(variables_,
233 "private byte [] $name$Utf8_ = null;\n"
234 "public $message_name$ set$capitalized_name$($type$ value) {\n"
235 " has$capitalized_name$ = true;\n"
236 " $name$_ = value;\n"
237 " $name$Utf8_ = null;\n"
238 " return this;\n"
239 "}\n"
240 "public $message_name$ clear$capitalized_name$() {\n"
241 " has$capitalized_name$ = false;\n"
242 " $name$_ = $default$;\n"
243 " $name$Utf8_ = null;\n"
244 " return this;\n"
245 "}\n");
246 } else {
247 if (IsVariableLenType(GetJavaType(descriptor_))) {
248 printer->Print(variables_,
249 "public $message_name$ set$capitalized_name$($type$ value) {\n"
250 " has$capitalized_name$ = true;\n"
251 " $name$_ = value;\n"
252 " return this;\n"
253 "}\n"
254 "public $message_name$ clear$capitalized_name$() {\n"
255 " has$capitalized_name$ = false;\n"
256 " $name$_ = $default$;\n"
257 " return this;\n"
258 "}\n");
259 } else {
260 printer->Print(variables_,
261 "public $message_name$ set$capitalized_name$($type$ value) {\n"
262 " has$capitalized_name$ = true;\n"
263 " $name$_ = value;\n"
264 " return this;\n"
265 "}\n"
266 "public $message_name$ clear$capitalized_name$() {\n"
267 " has$capitalized_name$ = false;\n"
268 " $name$_ = $default$;\n"
269 " return this;\n"
270 "}\n");
271 }
272 }
273 }
274
275 void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const276 GenerateMergingCode(io::Printer* printer) const {
277 printer->Print(variables_,
278 "if (other.has$capitalized_name$()) {\n"
279 " set$capitalized_name$(other.get$capitalized_name$());\n"
280 "}\n");
281 }
282
283 void PrimitiveFieldGenerator::
GenerateParsingCode(io::Printer * printer) const284 GenerateParsingCode(io::Printer* printer) const {
285 printer->Print(variables_,
286 "set$capitalized_name$(input.read$capitalized_type$());\n");
287 }
288
289 void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const290 GenerateSerializationCode(io::Printer* printer) const {
291 if (IsFastStringHandling(descriptor_, params_)) {
292 printer->Print(variables_,
293 "if (has$capitalized_name$()) {\n"
294 " output.writeByteArray($number$, $name$Utf8_);\n"
295 "}\n");
296 } else {
297 printer->Print(variables_,
298 "if (has$capitalized_name$()) {\n"
299 " output.write$capitalized_type$($number$, get$capitalized_name$());\n"
300 "}\n");
301 }
302 }
303
304 void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const305 GenerateSerializedSizeCode(io::Printer* printer) const {
306 if (IsFastStringHandling(descriptor_, params_)) {
307 printer->Print(variables_,
308 "if (has$capitalized_name$()) {\n"
309 " try {\n"
310 " $name$Utf8_ = $name$_.getBytes(\"UTF-8\");\n"
311 " } catch (java.io.UnsupportedEncodingException e) {\n"
312 " throw new RuntimeException(\"UTF-8 not supported.\");\n"
313 " }\n"
314 " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
315 " .computeByteArraySize($number$, $name$Utf8_);\n"
316 "}\n");
317 } else {
318 printer->Print(variables_,
319 "if (has$capitalized_name$()) {\n"
320 " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
321 " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n"
322 "}\n");
323 }
324 }
325
GetBoxedType() const326 string PrimitiveFieldGenerator::GetBoxedType() const {
327 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
328 }
329
330 // ===================================================================
331
332 RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)333 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
334 : FieldGenerator(params), descriptor_(descriptor) {
335 SetPrimitiveVariables(descriptor, params, &variables_);
336 if (descriptor_->options().packed()) {
337 GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
338 }
339 }
340
~RepeatedPrimitiveFieldGenerator()341 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
342
343 void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer) const344 GenerateMembers(io::Printer* printer) const {
345 if (IsFastStringHandling(descriptor_, params_)) {
346 if (params_.java_use_vector()) {
347 printer->Print(variables_,
348 "private java.util.Vector $name$_ = new java.util.Vector();\n"
349 "public java.util.Vector get$capitalized_name$List() {\n"
350 " return $name$_;\n"
351 "}\n"
352 "private java.util.Vector $name$Utf8_ = new java.util.Vector();\n"
353 "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
354 "public $type$ get$capitalized_name$(int index) {\n"
355 " return (($type$)$name$_.elementAt(index));\n"
356 "}\n"
357 "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
358 "$null_check$"
359 " $name$_.setElementAt(value, index);\n"
360 " $name$Utf8_ = null;\n"
361 " return this;\n"
362 "}\n"
363 "public $message_name$ add$capitalized_name$($type$ value) {\n"
364 "$null_check$"
365 " $name$_.addElement(value);\n"
366 " $name$Utf8_ = null;\n"
367 " return this;\n"
368 "}\n"
369 "public $message_name$ clear$capitalized_name$() {\n"
370 " $name$_.removeAllElements();\n"
371 " $name$Utf8_ = null;\n"
372 " return this;\n"
373 "}\n");
374 } else {
375 printer->Print(variables_,
376 "private java.util.List<$type$> $name$_ =\n"
377 " java.util.Collections.emptyList();\n"
378 "public java.util.List<$type$> get$capitalized_name$List() {\n"
379 " return $name$_;\n" // note: unmodifiable list
380 "}\n"
381 "private java.util.List<byte []> $name$Utf8_ = null;\n"
382 "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
383 "public $type$ get$capitalized_name$(int index) {\n"
384 " return $name$_.get(index);\n"
385 "}\n"
386 "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
387 "$null_check$"
388 " $name$_.set(index, value);\n"
389 " $name$Utf8_ = null;\n"
390 " return this;\n"
391 "}\n"
392 "public $message_name$ add$capitalized_name$($type$ value) {\n"
393 "$null_check$"
394 " if ($name$_.isEmpty()) {\n"
395 " $name$_ = new java.util.ArrayList<$type$>();\n"
396 " }\n"
397 " $name$_.add(value);\n"
398 " $name$Utf8_ = null;\n"
399 " return this;\n"
400 "}\n"
401 "public $message_name$ clear$capitalized_name$() {\n"
402 " $name$_ = java.util.Collections.emptyList();\n"
403 " $name$Utf8_ = null;\n"
404 " return this;\n"
405 "}\n");
406 }
407 } else if (params_.java_use_vector()) {
408 if (IsReferenceType(GetJavaType(descriptor_))) {
409 printer->Print(variables_,
410 "private java.util.Vector $name$_ = new java.util.Vector();\n"
411 "public java.util.Vector get$capitalized_name$List() {\n"
412 " return $name$_;\n"
413 "}\n"
414 "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
415 "public $type$ get$capitalized_name$(int index) {\n"
416 " return ($type$) $name$_.elementAt(index);\n"
417 "}\n"
418 "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
419 "$null_check$"
420 " $name$_.setElementAt(value, index);\n"
421 " return this;\n"
422 "}\n"
423 "public $message_name$ add$capitalized_name$($type$ value) {\n"
424 "$null_check$"
425 " $name$_.addElement(value);\n"
426 " return this;\n"
427 "}\n"
428 "public $message_name$ clear$capitalized_name$() {\n"
429 " $name$_.removeAllElements();\n"
430 " return this;\n"
431 "}\n");
432 } else {
433 printer->Print(variables_,
434 "private java.util.Vector $name$_ = new java.util.Vector();\n"
435 "public java.util.Vector get$capitalized_name$List() {\n"
436 " return $name$_;\n"
437 "}\n"
438 "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
439 "public $type$ get$capitalized_name$(int index) {\n"
440 " return (($boxed_type$)$name$_.elementAt(index)).$type$Value();\n"
441 "}\n"
442 "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
443 "$null_check$"
444 " $name$_.setElementAt(new $boxed_type$(value), index);\n"
445 " return this;\n"
446 "}\n"
447 "public $message_name$ add$capitalized_name$($type$ value) {\n"
448 "$null_check$"
449 " $name$_.addElement(new $boxed_type$(value));\n"
450 " return this;\n"
451 "}\n"
452 "public $message_name$ clear$capitalized_name$() {\n"
453 " $name$_.removeAllElements();\n"
454 " return this;\n"
455 "}\n");
456 }
457 } else {
458 printer->Print(variables_,
459 "private java.util.List<$boxed_type$> $name$_ =\n"
460 " java.util.Collections.emptyList();\n"
461 "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
462 " return $name$_;\n" // note: unmodifiable list
463 "}\n"
464 "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
465 "public $type$ get$capitalized_name$(int index) {\n"
466 " return $name$_.get(index);\n"
467 "}\n"
468 "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
469 "$null_check$"
470 " $name$_.set(index, value);\n"
471 " return this;\n"
472 "}\n"
473 "public $message_name$ add$capitalized_name$($type$ value) {\n"
474 "$null_check$"
475 " if ($name$_.isEmpty()) {\n"
476 " $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
477 " }\n"
478 " $name$_.add(value);\n"
479 " return this;\n"
480 "}\n"
481 "public $message_name$ clear$capitalized_name$() {\n"
482 " $name$_ = java.util.Collections.emptyList();\n"
483 " return this;\n"
484 "}\n");
485 }
486 if (descriptor_->options().packed()) {
487 printer->Print(variables_,
488 "private int $name$MemoizedSerializedSize;\n");
489 }
490 }
491
492 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const493 GenerateMergingCode(io::Printer* printer) const {
494 if (params_.java_use_vector()) {
495 printer->Print(variables_,
496 "if (other.$name$_.size() != 0) {\n"
497 " for (int i = 0; i < other.$name$_.size(); i++)) {\n"
498 " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
499 " }\n"
500 "}\n");
501 } else {
502 printer->Print(variables_,
503 "if (!other.$name$_.isEmpty()) {\n"
504 " if (result.$name$_.isEmpty()) {\n"
505 " result.$name$_ = new java.util.ArrayList<$type$>();\n"
506 " }\n"
507 " result.$name$_.addAll(other.$name$_);\n"
508 "}\n");
509 }
510 }
511
512 void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer * printer) const513 GenerateParsingCode(io::Printer* printer) const {
514 if (descriptor_->options().packed()) {
515 printer->Print(variables_,
516 "int length = input.readRawVarint32();\n"
517 "int limit = input.pushLimit(length);\n"
518 "while (input.getBytesUntilLimit() > 0) {\n"
519 " add$capitalized_name$(input.read$capitalized_type$());\n"
520 "}\n"
521 "input.popLimit(limit);\n");
522 } else {
523 printer->Print(variables_,
524 "add$capitalized_name$(input.read$capitalized_type$());\n");
525 }
526 }
527
528 void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const529 GenerateSerializationCode(io::Printer* printer) const {
530 if (descriptor_->options().packed()) {
531 printer->Print(variables_,
532 "if (get$capitalized_name$List().size() > 0) {\n"
533 " output.writeRawVarint32($tag$);\n"
534 " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
535 "}\n");
536 if (params_.java_use_vector()) {
537 printer->Print(variables_,
538 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
539 " output.write$capitalized_type$NoTag(get$capitalized_name$(i));\n"
540 "}\n");
541 } else {
542 printer->Print(variables_,
543 "for ($type$ element : get$capitalized_name$List()) {\n"
544 " output.write$capitalized_type$NoTag(element);\n"
545 "}\n");
546 }
547 } else {
548 if (params_.java_use_vector()) {
549 if (IsFastStringHandling(descriptor_, params_)) {
550 printer->Print(variables_,
551 "for (int i = 0; i < $name$Utf8_.size(); i++) {\n"
552 " output.writeByteArray($number$, (byte []) $name$Utf8_.get(i));\n"
553 "}\n");
554 } else {
555 printer->Print(variables_,
556 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
557 " output.write$capitalized_type$($number$, get$capitalized_name$(i));\n"
558 "}\n");
559 }
560 } else {
561 if (IsFastStringHandling(descriptor_, params_)) {
562 printer->Print(variables_,
563 "for (byte [] element : $name$Utf8_) {\n"
564 " output.writeByteArray($number$, element);\n"
565 "}\n");
566 } else {
567 printer->Print(variables_,
568 "for ($type$ element : get$capitalized_name$List()) {\n"
569 " output.write$capitalized_type$($number$, element);\n"
570 "}\n");
571 }
572 }
573 }
574 }
575
576 void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const577 GenerateSerializedSizeCode(io::Printer* printer) const {
578 printer->Print(variables_,
579 "{\n"
580 " int dataSize = 0;\n");
581 printer->Indent();
582
583 if (FixedSize(descriptor_->type()) == -1) {
584 if (params_.java_use_vector()) {
585 if (IsFastStringHandling(descriptor_, params_)) {
586 printer->Print(variables_,
587 "$name$Utf8_ = new java.util.Vector();\n"
588 "byte[] bytes = null;\n"
589 "int sizeArray = get$capitalized_name$List().size();\n"
590 "for (int i = 0; i < sizeArray; i++) {\n"
591 " $type$ element = ($type$)$name$_.elementAt(i);\n"
592 " try {\n"
593 " bytes = element.getBytes(\"UTF-8\");\n"
594 " } catch (java.io.UnsupportedEncodingException e) {\n"
595 " throw new RuntimeException(\"UTF-8 not supported.\");\n"
596 " }\n"
597 " $name$Utf8_.addElement(bytes);\n"
598 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
599 " .computeByteArraySizeNoTag(bytes);\n"
600 "}\n");
601 } else {
602 printer->Print(variables_,
603 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
604 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
605 " .compute$capitalized_type$SizeNoTag(($type$)get$capitalized_name$(i));\n"
606 "}\n");
607 }
608 } else {
609 if (IsFastStringHandling(descriptor_, params_)) {
610 printer->Print(variables_,
611 "$name$Utf8_ = new java.util.ArrayList<byte[]>();\n"
612 "byte[] bytes = null;\n"
613 "int sizeArray = get$capitalized_name$List().size();\n"
614 "for (int i = 0; i < sizeArray; i++) {\n"
615 " $type$ element = get$capitalized_name$(i);\n"
616 " try {\n"
617 " bytes = element.getBytes(\"UTF-8\");\n"
618 " } catch (java.io.UnsupportedEncodingException e) {\n"
619 " throw new RuntimeException(\"UTF-8 not supported.\");\n"
620 " }\n"
621 " $name$Utf8_.add(bytes);\n"
622 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
623 " .computeByteArraySizeNoTag(bytes);\n"
624 "}\n");
625 } else {
626 printer->Print(variables_,
627 "for ($type$ element : get$capitalized_name$List()) {\n"
628 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
629 " .compute$capitalized_type$SizeNoTag(element);\n"
630 "}\n");
631 }
632 }
633 } else {
634 printer->Print(variables_,
635 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
636 }
637
638 printer->Print(
639 "size += dataSize;\n");
640
641 if (descriptor_->options().packed()) {
642 if (params_.java_use_vector()) {
643 printer->Print(variables_,
644 "if (get$capitalized_name$List().size() != 0) {\n");
645 } else {
646 printer->Print(variables_,
647 "if (!get$capitalized_name$List().isEmpty()) {\n");
648 }
649 printer->Print(variables_,
650 " size += $tag_size$;\n"
651 " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
652 " .computeInt32SizeNoTag(dataSize);\n"
653 "}\n");
654 } else {
655 printer->Print(variables_,
656 "size += $tag_size$ * get$capitalized_name$List().size();\n");
657 }
658
659 // cache the data size for packed fields.
660 if (descriptor_->options().packed()) {
661 printer->Print(variables_,
662 "$name$MemoizedSerializedSize = dataSize;\n");
663 }
664
665 printer->Outdent();
666 printer->Print("}\n");
667 }
668
GetBoxedType() const669 string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
670 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
671 }
672
673 } // namespace javamicro
674 } // namespace compiler
675 } // namespace protobuf
676 } // namespace google
677