javanano_primitive_field.cc revision 0b8579237336f221711a0aac42400eb31a58fed3
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 if (IsReferenceType(GetJavaType(descriptor))) { 291 (*variables)["null_check"] = 292 " if (value == null) {\n" 293 " throw new java.lang.NullPointerException();\n" 294 " }\n"; 295 } else { 296 (*variables)["null_check"] = ""; 297 } 298 int fixed_size = FixedSize(descriptor->type()); 299 if (fixed_size != -1) { 300 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 301 } 302 (*variables)["message_name"] = descriptor->containing_type()->name(); 303 (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor); 304} 305} // namespace 306 307// =================================================================== 308 309PrimitiveFieldGenerator:: 310PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 311 : FieldGenerator(params), descriptor_(descriptor) { 312 SetPrimitiveVariables(descriptor, params, &variables_); 313} 314 315PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 316 317void PrimitiveFieldGenerator:: 318GenerateMembers(io::Printer* printer) const { 319 if (variables_.find("default_constant_value") != variables_.end()) { 320 // Those primitive types that need a saved default. 321 printer->Print(variables_, 322 "private static final $type$ $default_constant$ = $default_constant_value$;\n"); 323 } 324 325 printer->Print(variables_, 326 "public $type$ $name$ = $default_copy_if_needed$;\n"); 327 328 if (params_.generate_has()) { 329 printer->Print(variables_, 330 "public boolean has$capitalized_name$ = false;\n"); 331 } 332} 333 334void PrimitiveFieldGenerator:: 335GenerateClearCode(io::Printer* printer) const { 336 printer->Print(variables_, 337 "$name$ = $default_copy_if_needed$;\n"); 338 339 if (params_.generate_has()) { 340 printer->Print(variables_, 341 "has$capitalized_name$ = false;\n"); 342 } 343} 344 345void PrimitiveFieldGenerator:: 346GenerateMergingCode(io::Printer* printer) const { 347 printer->Print(variables_, 348 "this.$name$ = input.read$capitalized_type$();\n"); 349 350 if (params_.generate_has()) { 351 printer->Print(variables_, 352 "has$capitalized_name$ = true;\n"); 353 } 354} 355 356void PrimitiveFieldGenerator:: 357GenerateSerializationConditional(io::Printer* printer) const { 358 if (params_.use_reference_types_for_primitives()) { 359 // For reference type mode, serialize based on equality 360 // to null. 361 printer->Print(variables_, 362 "if (this.$name$ != null) {\n"); 363 return; 364 } 365 if (params_.generate_has()) { 366 printer->Print(variables_, 367 "if (has$capitalized_name$ || "); 368 } else { 369 printer->Print(variables_, 370 "if ("); 371 } 372 if (IsArrayType(GetJavaType(descriptor_))) { 373 printer->Print(variables_, 374 "!java.util.Arrays.equals(this.$name$, $default$)) {\n"); 375 } else if (IsReferenceType(GetJavaType(descriptor_))) { 376 printer->Print(variables_, 377 "!this.$name$.equals($default$)) {\n"); 378 } else if (IsDefaultNaN(descriptor_)) { 379 printer->Print(variables_, 380 "!$capitalized_type$.isNaN(this.$name$)) {\n"); 381 } else { 382 printer->Print(variables_, 383 "this.$name$ != $default$) {\n"); 384 } 385} 386 387void PrimitiveFieldGenerator:: 388GenerateSerializationCode(io::Printer* printer) const { 389 if (descriptor_->is_required()) { 390 printer->Print(variables_, 391 "output.write$capitalized_type$($number$, this.$name$);\n"); 392 } else { 393 GenerateSerializationConditional(printer); 394 printer->Print(variables_, 395 " output.write$capitalized_type$($number$, this.$name$);\n" 396 "}\n"); 397 } 398} 399 400void PrimitiveFieldGenerator:: 401GenerateSerializedSizeCode(io::Printer* printer) const { 402 if (descriptor_->is_required()) { 403 printer->Print(variables_, 404 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 405 " .compute$capitalized_type$Size($number$, this.$name$);\n"); 406 } else { 407 GenerateSerializationConditional(printer); 408 printer->Print(variables_, 409 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 410 " .compute$capitalized_type$Size($number$, this.$name$);\n" 411 "}\n"); 412 } 413} 414 415string PrimitiveFieldGenerator::GetBoxedType() const { 416 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 417} 418 419// =================================================================== 420 421AccessorPrimitiveFieldGenerator:: 422AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 423 const Params& params, int has_bit_index) 424 : FieldGenerator(params), descriptor_(descriptor) { 425 SetPrimitiveVariables(descriptor, params, &variables_); 426 SetBitOperationVariables("has", has_bit_index, &variables_); 427} 428 429AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} 430 431void AccessorPrimitiveFieldGenerator:: 432GenerateMembers(io::Printer* printer) const { 433 if (variables_.find("default_constant_value") != variables_.end()) { 434 printer->Print(variables_, 435 "private static final $type$ $default_constant$ = $default_constant_value$;\n"); 436 } 437 printer->Print(variables_, 438 "private $type$ $name$_ = $default_copy_if_needed$;\n" 439 "public $type$ get$capitalized_name$() {\n" 440 " return $name$_;\n" 441 "}\n" 442 "public void set$capitalized_name$($type$ value) {\n" 443 "$null_check$" 444 " $name$_ = value;\n" 445 " $set_has$;\n" 446 "}\n" 447 "public boolean has$capitalized_name$() {\n" 448 " return $get_has$;\n" 449 "}\n" 450 "public void clear$capitalized_name$() {\n" 451 " $name$_ = $default_copy_if_needed$;\n" 452 " $clear_has$;\n" 453 "}\n"); 454} 455 456void AccessorPrimitiveFieldGenerator:: 457GenerateClearCode(io::Printer* printer) const { 458 printer->Print(variables_, 459 "$name$_ = $default_copy_if_needed$;\n"); 460} 461 462void AccessorPrimitiveFieldGenerator:: 463GenerateMergingCode(io::Printer* printer) const { 464 printer->Print(variables_, 465 "set$capitalized_name$(input.read$capitalized_type$());\n"); 466} 467 468void AccessorPrimitiveFieldGenerator:: 469GenerateSerializationCode(io::Printer* printer) const { 470 printer->Print(variables_, 471 "if (has$capitalized_name$()) {\n" 472 " output.write$capitalized_type$($number$, $name$_);\n" 473 "}\n"); 474} 475 476void AccessorPrimitiveFieldGenerator:: 477GenerateSerializedSizeCode(io::Printer* printer) const { 478 printer->Print(variables_, 479 "if (has$capitalized_name$()) {\n" 480 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 481 " .compute$capitalized_type$Size($number$, $name$_);\n" 482 "}\n"); 483} 484 485string AccessorPrimitiveFieldGenerator::GetBoxedType() const { 486 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 487} 488 489// =================================================================== 490 491RepeatedPrimitiveFieldGenerator:: 492RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 493 : FieldGenerator(params), descriptor_(descriptor) { 494 SetPrimitiveVariables(descriptor, params, &variables_); 495} 496 497RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 498 499void RepeatedPrimitiveFieldGenerator:: 500GenerateMembers(io::Printer* printer) const { 501 printer->Print(variables_, 502 "public $type$[] $name$ = $default$;\n"); 503} 504 505void RepeatedPrimitiveFieldGenerator:: 506GenerateClearCode(io::Printer* printer) const { 507 printer->Print(variables_, 508 "$name$ = $default$;\n"); 509} 510 511void RepeatedPrimitiveFieldGenerator:: 512GenerateMergingCode(io::Printer* printer) const { 513 // First, figure out the length of the array, then parse. 514 if (descriptor_->options().packed()) { 515 printer->Print(variables_, 516 "int length = input.readRawVarint32();\n" 517 "int limit = input.pushLimit(length);\n" 518 "// First pass to compute array length.\n" 519 "int arrayLength = 0;\n" 520 "int startPos = input.getPosition();\n" 521 "while (input.getBytesUntilLimit() > 0) {\n" 522 " input.read$capitalized_type$();\n" 523 " arrayLength++;\n" 524 "}\n" 525 "input.rewindToPosition(startPos);\n" 526 "this.$name$ = new $type$[arrayLength];\n" 527 "for (int i = 0; i < arrayLength; i++) {\n" 528 " this.$name$[i] = input.read$capitalized_type$();\n" 529 "}\n" 530 "input.popLimit(limit);\n"); 531 } else { 532 printer->Print(variables_, 533 "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" 534 "int i = this.$name$.length;\n"); 535 536 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { 537 printer->Print(variables_, 538 "byte[][] newArray = new byte[i + arrayLength][];\n" 539 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 540 "this.$name$ = newArray;\n"); 541 } else { 542 printer->Print(variables_, 543 "$type$[] newArray = new $type$[i + arrayLength];\n" 544 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 545 "this.$name$ = newArray;\n"); 546 } 547 printer->Print(variables_, 548 "for (; i < this.$name$.length - 1; i++) {\n" 549 " this.$name$[i] = input.read$capitalized_type$();\n" 550 " input.readTag();\n" 551 "}\n" 552 "// Last one without readTag.\n" 553 "this.$name$[i] = input.read$capitalized_type$();\n"); 554 } 555} 556 557void RepeatedPrimitiveFieldGenerator:: 558GenerateRepeatedDataSizeCode(io::Printer* printer) const { 559 // Creates a variable dataSize and puts the serialized size in 560 // there. 561 if (FixedSize(descriptor_->type()) == -1) { 562 printer->Print(variables_, 563 "int dataSize = 0;\n" 564 "for ($type$ element : this.$name$) {\n" 565 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 566 " .compute$capitalized_type$SizeNoTag(element);\n" 567 "}\n"); 568 } else { 569 printer->Print(variables_, 570 "int dataSize = $fixed_size$ * this.$name$.length;\n"); 571 } 572} 573 574void RepeatedPrimitiveFieldGenerator:: 575GenerateSerializationCode(io::Printer* printer) const { 576 if (descriptor_->options().packed()) { 577 printer->Print(variables_, 578 "if (this.$name$.length > 0) {\n"); 579 printer->Indent(); 580 GenerateRepeatedDataSizeCode(printer); 581 printer->Outdent(); 582 printer->Print(variables_, 583 " output.writeRawVarint32($tag$);\n" 584 " output.writeRawVarint32(dataSize);\n" 585 "}\n"); 586 printer->Print(variables_, 587 "for ($type$ element : this.$name$) {\n" 588 " output.write$capitalized_type$NoTag(element);\n" 589 "}\n"); 590 } else { 591 printer->Print(variables_, 592 "for ($type$ element : this.$name$) {\n" 593 " output.write$capitalized_type$($number$, element);\n" 594 "}\n"); 595 } 596} 597 598void RepeatedPrimitiveFieldGenerator:: 599GenerateSerializedSizeCode(io::Printer* printer) const { 600 printer->Print(variables_, 601 "if (this.$name$.length > 0) {\n"); 602 printer->Indent(); 603 604 GenerateRepeatedDataSizeCode(printer); 605 606 printer->Print( 607 "size += dataSize;\n"); 608 if (descriptor_->options().packed()) { 609 printer->Print(variables_, 610 "size += $tag_size$;\n" 611 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 612 " .computeRawVarint32Size(dataSize);\n"); 613 } else { 614 printer->Print(variables_, 615 "size += $tag_size$ * this.$name$.length;\n"); 616 } 617 618 printer->Outdent(); 619 620 printer->Print( 621 "}\n"); 622} 623 624string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { 625 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 626} 627 628} // namespace javanano 629} // namespace compiler 630} // namespace protobuf 631} // namespace google 632