javanano_primitive_field.cc revision e03e9f4b5774c0ffe04140d83bbdb532863b1720
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 <math.h> 37#include <string> 38 39#include <google/protobuf/compiler/javanano/javanano_primitive_field.h> 40#include <google/protobuf/stubs/common.h> 41#include <google/protobuf/compiler/javanano/javanano_helpers.h> 42#include <google/protobuf/io/printer.h> 43#include <google/protobuf/wire_format.h> 44#include <google/protobuf/stubs/strutil.h> 45#include <google/protobuf/stubs/substitute.h> 46 47namespace google { 48namespace protobuf { 49namespace compiler { 50namespace javanano { 51 52using internal::WireFormat; 53using internal::WireFormatLite; 54 55namespace { 56 57const char* PrimitiveTypeName(JavaType type) { 58 switch (type) { 59 case JAVATYPE_INT : return "int"; 60 case JAVATYPE_LONG : return "long"; 61 case JAVATYPE_FLOAT : return "float"; 62 case JAVATYPE_DOUBLE : return "double"; 63 case JAVATYPE_BOOLEAN: return "boolean"; 64 case JAVATYPE_STRING : return "java.lang.String"; 65 case JAVATYPE_BYTES : return "byte[]"; 66 case JAVATYPE_ENUM : return NULL; 67 case JAVATYPE_MESSAGE: return NULL; 68 69 // No default because we want the compiler to complain if any new 70 // JavaTypes are added. 71 } 72 73 GOOGLE_LOG(FATAL) << "Can't get here."; 74 return NULL; 75} 76 77bool IsReferenceType(JavaType type) { 78 switch (type) { 79 case JAVATYPE_INT : return false; 80 case JAVATYPE_LONG : return false; 81 case JAVATYPE_FLOAT : return false; 82 case JAVATYPE_DOUBLE : return false; 83 case JAVATYPE_BOOLEAN: return false; 84 case JAVATYPE_STRING : return true; 85 case JAVATYPE_BYTES : return true; 86 case JAVATYPE_ENUM : return false; 87 case JAVATYPE_MESSAGE: return true; 88 89 // No default because we want the compiler to complain if any new 90 // JavaTypes are added. 91 } 92 93 GOOGLE_LOG(FATAL) << "Can't get here."; 94 return false; 95} 96 97bool IsArrayType(JavaType type) { 98 switch (type) { 99 case JAVATYPE_INT : return false; 100 case JAVATYPE_LONG : return false; 101 case JAVATYPE_FLOAT : return false; 102 case JAVATYPE_DOUBLE : return false; 103 case JAVATYPE_BOOLEAN: return false; 104 case JAVATYPE_STRING : return false; 105 case JAVATYPE_BYTES : return true; 106 case JAVATYPE_ENUM : return false; 107 case JAVATYPE_MESSAGE: return false; 108 109 // No default because we want the compiler to complain if any new 110 // JavaTypes are added. 111 } 112 113 GOOGLE_LOG(FATAL) << "Can't get here."; 114 return false; 115} 116 117const char* GetCapitalizedType(const FieldDescriptor* field) { 118 switch (field->type()) { 119 case FieldDescriptor::TYPE_INT32 : return "Int32" ; 120 case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; 121 case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; 122 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; 123 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; 124 case FieldDescriptor::TYPE_INT64 : return "Int64" ; 125 case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; 126 case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; 127 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; 128 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; 129 case FieldDescriptor::TYPE_FLOAT : return "Float" ; 130 case FieldDescriptor::TYPE_DOUBLE : return "Double" ; 131 case FieldDescriptor::TYPE_BOOL : return "Bool" ; 132 case FieldDescriptor::TYPE_STRING : return "String" ; 133 case FieldDescriptor::TYPE_BYTES : return "Bytes" ; 134 case FieldDescriptor::TYPE_ENUM : return "Enum" ; 135 case FieldDescriptor::TYPE_GROUP : return "Group" ; 136 case FieldDescriptor::TYPE_MESSAGE : return "Message" ; 137 138 // No default because we want the compiler to complain if any new 139 // types are added. 140 } 141 142 GOOGLE_LOG(FATAL) << "Can't get here."; 143 return NULL; 144} 145 146// For encodings with fixed sizes, returns that size in bytes. Otherwise 147// returns -1. 148int FixedSize(FieldDescriptor::Type type) { 149 switch (type) { 150 case FieldDescriptor::TYPE_INT32 : return -1; 151 case FieldDescriptor::TYPE_INT64 : return -1; 152 case FieldDescriptor::TYPE_UINT32 : return -1; 153 case FieldDescriptor::TYPE_UINT64 : return -1; 154 case FieldDescriptor::TYPE_SINT32 : return -1; 155 case FieldDescriptor::TYPE_SINT64 : return -1; 156 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; 157 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; 158 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; 159 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; 160 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; 161 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; 162 163 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; 164 case FieldDescriptor::TYPE_ENUM : return -1; 165 166 case FieldDescriptor::TYPE_STRING : return -1; 167 case FieldDescriptor::TYPE_BYTES : return -1; 168 case FieldDescriptor::TYPE_GROUP : return -1; 169 case FieldDescriptor::TYPE_MESSAGE : return -1; 170 171 // No default because we want the compiler to complain if any new 172 // types are added. 173 } 174 GOOGLE_LOG(FATAL) << "Can't get here."; 175 return -1; 176} 177 178// Returns true if the field has a default value equal to NaN. 179bool IsDefaultNaN(const FieldDescriptor* field) { 180 switch (field->type()) { 181 case FieldDescriptor::TYPE_INT32 : return false; 182 case FieldDescriptor::TYPE_UINT32 : return false; 183 case FieldDescriptor::TYPE_SINT32 : return false; 184 case FieldDescriptor::TYPE_FIXED32 : return false; 185 case FieldDescriptor::TYPE_SFIXED32: return false; 186 case FieldDescriptor::TYPE_INT64 : return false; 187 case FieldDescriptor::TYPE_UINT64 : return false; 188 case FieldDescriptor::TYPE_SINT64 : return false; 189 case FieldDescriptor::TYPE_FIXED64 : return false; 190 case FieldDescriptor::TYPE_SFIXED64: return false; 191 case FieldDescriptor::TYPE_FLOAT : 192 return isnan(field->default_value_float()); 193 case FieldDescriptor::TYPE_DOUBLE : 194 return isnan(field->default_value_double()); 195 case FieldDescriptor::TYPE_BOOL : return false; 196 case FieldDescriptor::TYPE_STRING : return false; 197 case FieldDescriptor::TYPE_BYTES : return false; 198 case FieldDescriptor::TYPE_ENUM : return false; 199 case FieldDescriptor::TYPE_GROUP : return false; 200 case FieldDescriptor::TYPE_MESSAGE : return false; 201 202 // No default because we want the compiler to complain if any new 203 // types are added. 204 } 205 206 GOOGLE_LOG(FATAL) << "Can't get here."; 207 return false; 208} 209 210// Return true if the type is a that has variable length 211// for instance String's. 212bool IsVariableLenType(JavaType type) { 213 switch (type) { 214 case JAVATYPE_INT : return false; 215 case JAVATYPE_LONG : return false; 216 case JAVATYPE_FLOAT : return false; 217 case JAVATYPE_DOUBLE : return false; 218 case JAVATYPE_BOOLEAN: return false; 219 case JAVATYPE_STRING : return true; 220 case JAVATYPE_BYTES : return true; 221 case JAVATYPE_ENUM : return false; 222 case JAVATYPE_MESSAGE: return true; 223 224 // No default because we want the compiler to complain if any new 225 // JavaTypes are added. 226 } 227 228 GOOGLE_LOG(FATAL) << "Can't get here."; 229 return false; 230} 231 232bool AllAscii(const string& text) { 233 for (int i = 0; i < text.size(); i++) { 234 if ((text[i] & 0x80) != 0) { 235 return false; 236 } 237 } 238 return true; 239} 240 241void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, 242 map<string, string>* variables) { 243 (*variables)["name"] = 244 RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); 245 (*variables)["capitalized_name"] = 246 RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); 247 (*variables)["number"] = SimpleItoa(descriptor->number()); 248 if (params.use_reference_types_for_primitives() 249 && !descriptor->is_repeated()) { 250 (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 251 } else { 252 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); 253 } 254 (*variables)["default"] = DefaultValue(params, descriptor); 255 (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); 256 // For C++-string types (string and bytes), we might need to have 257 // the generated code do the unicode decoding (see comments in 258 // InternalNano.java for gory details.). We would like to do this 259 // once into a "private static final" field and re-use that from 260 // then on. 261 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && 262 !descriptor->default_value_string().empty() && 263 !params.use_reference_types_for_primitives()) { 264 string default_value; 265 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { 266 default_value = strings::Substitute( 267 "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")", 268 CEscape(descriptor->default_value_string())); 269 (*variables)["default_copy_if_needed"] = (*variables)["default"] + ".clone()"; 270 } else { 271 if (AllAscii(descriptor->default_value_string())) { 272 // All chars are ASCII. In this case CEscape() works fine. 273 default_value = "\"" + CEscape(descriptor->default_value_string()) + "\""; 274 } else { 275 default_value = strings::Substitute( 276 "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", 277 CEscape(descriptor->default_value_string())); 278 } 279 (*variables)["default_copy_if_needed"] = (*variables)["default"]; 280 } 281 (*variables)["default_constant_value"] = default_value; 282 } else { 283 (*variables)["default_copy_if_needed"] = (*variables)["default"]; 284 } 285 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 286 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); 287 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 288 (*variables)["tag_size"] = SimpleItoa( 289 WireFormat::TagSize(descriptor->number(), descriptor->type())); 290 int fixed_size = FixedSize(descriptor->type()); 291 if (fixed_size != -1) { 292 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 293 } 294 (*variables)["message_name"] = descriptor->containing_type()->name(); 295 (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor); 296} 297} // namespace 298 299// =================================================================== 300 301PrimitiveFieldGenerator:: 302PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 303 : FieldGenerator(params), descriptor_(descriptor) { 304 SetPrimitiveVariables(descriptor, params, &variables_); 305} 306 307PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 308 309void PrimitiveFieldGenerator:: 310GenerateMembers(io::Printer* printer) const { 311 if (variables_.find("default_constant_value") != variables_.end()) { 312 // Those primitive types that need a saved default. 313 printer->Print(variables_, 314 "private static final $type$ $default_constant$ = $default_constant_value$;\n"); 315 } 316 317 printer->Print(variables_, 318 "public $type$ $name$;\n"); 319 320 if (params_.generate_has()) { 321 printer->Print(variables_, 322 "public boolean has$capitalized_name$ = false;\n"); 323 } 324} 325 326void PrimitiveFieldGenerator:: 327GenerateClearCode(io::Printer* printer) const { 328 printer->Print(variables_, 329 "$name$ = $default_copy_if_needed$;\n"); 330 331 if (params_.generate_has()) { 332 printer->Print(variables_, 333 "has$capitalized_name$ = false;\n"); 334 } 335} 336 337void PrimitiveFieldGenerator:: 338GenerateMergingCode(io::Printer* printer) const { 339 printer->Print(variables_, 340 "this.$name$ = input.read$capitalized_type$();\n"); 341 342 if (params_.generate_has()) { 343 printer->Print(variables_, 344 "has$capitalized_name$ = true;\n"); 345 } 346} 347 348void PrimitiveFieldGenerator:: 349GenerateSerializationConditional(io::Printer* printer) const { 350 if (params_.use_reference_types_for_primitives()) { 351 // For reference type mode, serialize based on equality 352 // to null. 353 printer->Print(variables_, 354 "if (this.$name$ != null) {\n"); 355 return; 356 } 357 if (params_.generate_has()) { 358 printer->Print(variables_, 359 "if (has$capitalized_name$ || "); 360 } else { 361 printer->Print(variables_, 362 "if ("); 363 } 364 if (IsArrayType(GetJavaType(descriptor_))) { 365 printer->Print(variables_, 366 "!java.util.Arrays.equals(this.$name$, $default$)) {\n"); 367 } else if (IsReferenceType(GetJavaType(descriptor_))) { 368 printer->Print(variables_, 369 "!this.$name$.equals($default$)) {\n"); 370 } else if (IsDefaultNaN(descriptor_)) { 371 printer->Print(variables_, 372 "!$capitalized_type$.isNaN(this.$name$)) {\n"); 373 } else { 374 printer->Print(variables_, 375 "this.$name$ != $default$) {\n"); 376 } 377} 378 379void PrimitiveFieldGenerator:: 380GenerateSerializationCode(io::Printer* printer) const { 381 if (descriptor_->is_required()) { 382 printer->Print(variables_, 383 "output.write$capitalized_type$($number$, this.$name$);\n"); 384 } else { 385 GenerateSerializationConditional(printer); 386 printer->Print(variables_, 387 " output.write$capitalized_type$($number$, this.$name$);\n" 388 "}\n"); 389 } 390} 391 392void PrimitiveFieldGenerator:: 393GenerateSerializedSizeCode(io::Printer* printer) const { 394 if (descriptor_->is_required()) { 395 printer->Print(variables_, 396 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 397 " .compute$capitalized_type$Size($number$, this.$name$);\n"); 398 } else { 399 GenerateSerializationConditional(printer); 400 printer->Print(variables_, 401 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 402 " .compute$capitalized_type$Size($number$, this.$name$);\n" 403 "}\n"); 404 } 405} 406 407string PrimitiveFieldGenerator::GetBoxedType() const { 408 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 409} 410 411// =================================================================== 412 413AccessorPrimitiveFieldGenerator:: 414AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 415 const Params& params, int has_bit_index) 416 : FieldGenerator(params), descriptor_(descriptor) { 417 SetPrimitiveVariables(descriptor, params, &variables_); 418 SetBitOperationVariables("has", has_bit_index, &variables_); 419} 420 421AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} 422 423void AccessorPrimitiveFieldGenerator:: 424GenerateMembers(io::Printer* printer) const { 425 if (variables_.find("default_constant_value") != variables_.end()) { 426 printer->Print(variables_, 427 "private static final $type$ $default_constant$ = $default_constant_value$;\n"); 428 } 429 printer->Print(variables_, 430 "private $type$ $name$_;\n" 431 "public $type$ get$capitalized_name$() {\n" 432 " return $name$_;\n" 433 "}\n" 434 "public void set$capitalized_name$($type$ value) {\n"); 435 if (IsReferenceType(GetJavaType(descriptor_))) { 436 printer->Print(variables_, 437 " if (value == null) throw new java.lang.NullPointerException();\n"); 438 } 439 printer->Print(variables_, 440 " $name$_ = value;\n" 441 " $set_has$;\n" 442 "}\n" 443 "public boolean has$capitalized_name$() {\n" 444 " return $get_has$;\n" 445 "}\n" 446 "public void clear$capitalized_name$() {\n" 447 " $name$_ = $default_copy_if_needed$;\n" 448 " $clear_has$;\n" 449 "}\n"); 450} 451 452void AccessorPrimitiveFieldGenerator:: 453GenerateClearCode(io::Printer* printer) const { 454 printer->Print(variables_, 455 "$name$_ = $default_copy_if_needed$;\n"); 456} 457 458void AccessorPrimitiveFieldGenerator:: 459GenerateMergingCode(io::Printer* printer) const { 460 printer->Print(variables_, 461 "set$capitalized_name$(input.read$capitalized_type$());\n"); 462} 463 464void AccessorPrimitiveFieldGenerator:: 465GenerateSerializationCode(io::Printer* printer) const { 466 printer->Print(variables_, 467 "if (has$capitalized_name$()) {\n" 468 " output.write$capitalized_type$($number$, $name$_);\n" 469 "}\n"); 470} 471 472void AccessorPrimitiveFieldGenerator:: 473GenerateSerializedSizeCode(io::Printer* printer) const { 474 printer->Print(variables_, 475 "if (has$capitalized_name$()) {\n" 476 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 477 " .compute$capitalized_type$Size($number$, $name$_);\n" 478 "}\n"); 479} 480 481string AccessorPrimitiveFieldGenerator::GetBoxedType() const { 482 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 483} 484 485// =================================================================== 486 487RepeatedPrimitiveFieldGenerator:: 488RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 489 : FieldGenerator(params), descriptor_(descriptor) { 490 SetPrimitiveVariables(descriptor, params, &variables_); 491} 492 493RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 494 495void RepeatedPrimitiveFieldGenerator:: 496GenerateMembers(io::Printer* printer) const { 497 printer->Print(variables_, 498 "public $type$[] $name$;\n"); 499} 500 501void RepeatedPrimitiveFieldGenerator:: 502GenerateClearCode(io::Printer* printer) const { 503 printer->Print(variables_, 504 "$name$ = $default$;\n"); 505} 506 507void RepeatedPrimitiveFieldGenerator:: 508GenerateMergingCode(io::Printer* printer) const { 509 // First, figure out the length of the array, then parse. 510 if (descriptor_->options().packed()) { 511 printer->Print(variables_, 512 "int length = input.readRawVarint32();\n" 513 "int limit = input.pushLimit(length);\n" 514 "// First pass to compute array length.\n" 515 "int arrayLength = 0;\n" 516 "int startPos = input.getPosition();\n" 517 "while (input.getBytesUntilLimit() > 0) {\n" 518 " input.read$capitalized_type$();\n" 519 " arrayLength++;\n" 520 "}\n" 521 "input.rewindToPosition(startPos);\n" 522 "this.$name$ = new $type$[arrayLength];\n" 523 "for (int i = 0; i < arrayLength; i++) {\n" 524 " this.$name$[i] = input.read$capitalized_type$();\n" 525 "}\n" 526 "input.popLimit(limit);\n"); 527 } else { 528 printer->Print(variables_, 529 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 530 " .getRepeatedFieldArrayLength(input, $tag$);\n" 531 "int i = this.$name$.length;\n"); 532 533 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { 534 printer->Print(variables_, 535 "byte[][] newArray = new byte[i + arrayLength][];\n" 536 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 537 "this.$name$ = newArray;\n"); 538 } else { 539 printer->Print(variables_, 540 "$type$[] newArray = new $type$[i + arrayLength];\n" 541 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 542 "this.$name$ = newArray;\n"); 543 } 544 printer->Print(variables_, 545 "for (; i < this.$name$.length - 1; i++) {\n" 546 " this.$name$[i] = input.read$capitalized_type$();\n" 547 " input.readTag();\n" 548 "}\n" 549 "// Last one without readTag.\n" 550 "this.$name$[i] = input.read$capitalized_type$();\n"); 551 } 552} 553 554void RepeatedPrimitiveFieldGenerator:: 555GenerateRepeatedDataSizeCode(io::Printer* printer) const { 556 // Creates a variable dataSize and puts the serialized size in 557 // there. 558 if (FixedSize(descriptor_->type()) == -1) { 559 printer->Print(variables_, 560 "int dataSize = 0;\n" 561 "for ($type$ element : this.$name$) {\n" 562 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 563 " .compute$capitalized_type$SizeNoTag(element);\n" 564 "}\n"); 565 } else { 566 printer->Print(variables_, 567 "int dataSize = $fixed_size$ * this.$name$.length;\n"); 568 } 569} 570 571void RepeatedPrimitiveFieldGenerator:: 572GenerateSerializationCode(io::Printer* printer) const { 573 printer->Print(variables_, 574 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 575 printer->Indent(); 576 577 if (descriptor_->options().packed()) { 578 GenerateRepeatedDataSizeCode(printer); 579 printer->Print(variables_, 580 "output.writeRawVarint32($tag$);\n" 581 "output.writeRawVarint32(dataSize);\n" 582 "for ($type$ element : this.$name$) {\n" 583 " output.write$capitalized_type$NoTag(element);\n" 584 "}\n"); 585 } else { 586 printer->Print(variables_, 587 "for ($type$ element : this.$name$) {\n" 588 " output.write$capitalized_type$($number$, element);\n" 589 "}\n"); 590 } 591 592 printer->Outdent(); 593 printer->Print("}\n"); 594} 595 596void RepeatedPrimitiveFieldGenerator:: 597GenerateSerializedSizeCode(io::Printer* printer) const { 598 printer->Print(variables_, 599 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 600 printer->Indent(); 601 602 GenerateRepeatedDataSizeCode(printer); 603 604 printer->Print( 605 "size += dataSize;\n"); 606 if (descriptor_->options().packed()) { 607 printer->Print(variables_, 608 "size += $tag_size$;\n" 609 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 610 " .computeRawVarint32Size(dataSize);\n"); 611 } else { 612 printer->Print(variables_, 613 "size += $tag_size$ * this.$name$.length;\n"); 614 } 615 616 printer->Outdent(); 617 618 printer->Print( 619 "}\n"); 620} 621 622string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { 623 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 624} 625 626} // namespace javanano 627} // namespace compiler 628} // namespace protobuf 629} // namespace google 630