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/java/java_primitive_field.h> 39#include <google/protobuf/compiler/java/java_doc_comment.h> 40#include <google/protobuf/stubs/common.h> 41#include <google/protobuf/compiler/java/java_helpers.h> 42#include <google/protobuf/io/printer.h> 43#include <google/protobuf/wire_format.h> 44#include <google/protobuf/stubs/strutil.h> 45 46namespace google { 47namespace protobuf { 48namespace compiler { 49namespace java { 50 51using internal::WireFormat; 52using internal::WireFormatLite; 53 54namespace { 55 56const char* PrimitiveTypeName(JavaType type) { 57 switch (type) { 58 case JAVATYPE_INT : return "int"; 59 case JAVATYPE_LONG : return "long"; 60 case JAVATYPE_FLOAT : return "float"; 61 case JAVATYPE_DOUBLE : return "double"; 62 case JAVATYPE_BOOLEAN: return "boolean"; 63 case JAVATYPE_STRING : return "java.lang.String"; 64 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; 65 case JAVATYPE_ENUM : return NULL; 66 case JAVATYPE_MESSAGE: return NULL; 67 68 // No default because we want the compiler to complain if any new 69 // JavaTypes are added. 70 } 71 72 GOOGLE_LOG(FATAL) << "Can't get here."; 73 return NULL; 74} 75 76bool IsReferenceType(JavaType type) { 77 switch (type) { 78 case JAVATYPE_INT : return false; 79 case JAVATYPE_LONG : return false; 80 case JAVATYPE_FLOAT : return false; 81 case JAVATYPE_DOUBLE : return false; 82 case JAVATYPE_BOOLEAN: return false; 83 case JAVATYPE_STRING : return true; 84 case JAVATYPE_BYTES : return true; 85 case JAVATYPE_ENUM : return true; 86 case JAVATYPE_MESSAGE: return true; 87 88 // No default because we want the compiler to complain if any new 89 // JavaTypes are added. 90 } 91 92 GOOGLE_LOG(FATAL) << "Can't get here."; 93 return false; 94} 95 96const char* GetCapitalizedType(const FieldDescriptor* field) { 97 switch (GetType(field)) { 98 case FieldDescriptor::TYPE_INT32 : return "Int32" ; 99 case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; 100 case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; 101 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; 102 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; 103 case FieldDescriptor::TYPE_INT64 : return "Int64" ; 104 case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; 105 case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; 106 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; 107 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; 108 case FieldDescriptor::TYPE_FLOAT : return "Float" ; 109 case FieldDescriptor::TYPE_DOUBLE : return "Double" ; 110 case FieldDescriptor::TYPE_BOOL : return "Bool" ; 111 case FieldDescriptor::TYPE_STRING : return "String" ; 112 case FieldDescriptor::TYPE_BYTES : return "Bytes" ; 113 case FieldDescriptor::TYPE_ENUM : return "Enum" ; 114 case FieldDescriptor::TYPE_GROUP : return "Group" ; 115 case FieldDescriptor::TYPE_MESSAGE : return "Message" ; 116 117 // No default because we want the compiler to complain if any new 118 // types are added. 119 } 120 121 GOOGLE_LOG(FATAL) << "Can't get here."; 122 return NULL; 123} 124 125// For encodings with fixed sizes, returns that size in bytes. Otherwise 126// returns -1. 127int FixedSize(FieldDescriptor::Type type) { 128 switch (type) { 129 case FieldDescriptor::TYPE_INT32 : return -1; 130 case FieldDescriptor::TYPE_INT64 : return -1; 131 case FieldDescriptor::TYPE_UINT32 : return -1; 132 case FieldDescriptor::TYPE_UINT64 : return -1; 133 case FieldDescriptor::TYPE_SINT32 : return -1; 134 case FieldDescriptor::TYPE_SINT64 : return -1; 135 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; 136 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; 137 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; 138 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; 139 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; 140 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; 141 142 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; 143 case FieldDescriptor::TYPE_ENUM : return -1; 144 145 case FieldDescriptor::TYPE_STRING : return -1; 146 case FieldDescriptor::TYPE_BYTES : return -1; 147 case FieldDescriptor::TYPE_GROUP : return -1; 148 case FieldDescriptor::TYPE_MESSAGE : return -1; 149 150 // No default because we want the compiler to complain if any new 151 // types are added. 152 } 153 GOOGLE_LOG(FATAL) << "Can't get here."; 154 return -1; 155} 156 157void SetPrimitiveVariables(const FieldDescriptor* descriptor, 158 int messageBitIndex, 159 int builderBitIndex, 160 map<string, string>* variables) { 161 (*variables)["name"] = 162 UnderscoresToCamelCase(descriptor); 163 (*variables)["capitalized_name"] = 164 UnderscoresToCapitalizedCamelCase(descriptor); 165 (*variables)["constant_name"] = FieldConstantName(descriptor); 166 (*variables)["number"] = SimpleItoa(descriptor->number()); 167 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); 168 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 169 (*variables)["field_type"] = (*variables)["type"]; 170 (*variables)["field_list_type"] = "java.util.List<" + 171 (*variables)["boxed_type"] + ">"; 172 (*variables)["empty_list"] = "java.util.Collections.emptyList()"; 173 (*variables)["default"] = DefaultValue(descriptor); 174 (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? 175 "" : ("= " + DefaultValue(descriptor)); 176 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); 177 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 178 (*variables)["tag_size"] = SimpleItoa( 179 WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 180 if (IsReferenceType(GetJavaType(descriptor))) { 181 (*variables)["null_check"] = 182 " if (value == null) {\n" 183 " throw new NullPointerException();\n" 184 " }\n"; 185 } else { 186 (*variables)["null_check"] = ""; 187 } 188 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 189 // by the proto compiler 190 (*variables)["deprecation"] = descriptor->options().deprecated() 191 ? "@java.lang.Deprecated " : ""; 192 int fixed_size = FixedSize(GetType(descriptor)); 193 if (fixed_size != -1) { 194 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 195 } 196 (*variables)["on_changed"] = 197 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; 198 199 // For singular messages and builders, one bit is used for the hasField bit. 200 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 201 (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); 202 203 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 204 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); 205 (*variables)["clear_has_field_bit_builder"] = 206 GenerateClearBit(builderBitIndex); 207 208 // For repated builders, one bit is used for whether the array is immutable. 209 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 210 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 211 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 212 213 // For repeated fields, one bit is used for whether the array is immutable 214 // in the parsing constructor. 215 (*variables)["get_mutable_bit_parser"] = 216 GenerateGetBitMutableLocal(builderBitIndex); 217 (*variables)["set_mutable_bit_parser"] = 218 GenerateSetBitMutableLocal(builderBitIndex); 219 220 (*variables)["get_has_field_bit_from_local"] = 221 GenerateGetBitFromLocal(builderBitIndex); 222 (*variables)["set_has_field_bit_to_local"] = 223 GenerateSetBitToLocal(messageBitIndex); 224} 225 226} // namespace 227 228// =================================================================== 229 230PrimitiveFieldGenerator:: 231PrimitiveFieldGenerator(const FieldDescriptor* descriptor, 232 int messageBitIndex, 233 int builderBitIndex) 234 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 235 builderBitIndex_(builderBitIndex) { 236 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 237 &variables_); 238} 239 240PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 241 242int PrimitiveFieldGenerator::GetNumBitsForMessage() const { 243 return 1; 244} 245 246int PrimitiveFieldGenerator::GetNumBitsForBuilder() const { 247 return 1; 248} 249 250void PrimitiveFieldGenerator:: 251GenerateInterfaceMembers(io::Printer* printer) const { 252 WriteFieldDocComment(printer, descriptor_); 253 printer->Print(variables_, 254 "$deprecation$boolean has$capitalized_name$();\n"); 255 WriteFieldDocComment(printer, descriptor_); 256 printer->Print(variables_, 257 "$deprecation$$type$ get$capitalized_name$();\n"); 258} 259 260void PrimitiveFieldGenerator:: 261GenerateMembers(io::Printer* printer) const { 262 printer->Print(variables_, 263 "private $field_type$ $name$_;\n"); 264 265 WriteFieldDocComment(printer, descriptor_); 266 printer->Print(variables_, 267 "$deprecation$public boolean has$capitalized_name$() {\n" 268 " return $get_has_field_bit_message$;\n" 269 "}\n"); 270 271 WriteFieldDocComment(printer, descriptor_); 272 printer->Print(variables_, 273 "$deprecation$public $type$ get$capitalized_name$() {\n" 274 " return $name$_;\n" 275 "}\n"); 276} 277 278void PrimitiveFieldGenerator:: 279GenerateBuilderMembers(io::Printer* printer) const { 280 printer->Print(variables_, 281 "private $field_type$ $name$_ $default_init$;\n"); 282 283 WriteFieldDocComment(printer, descriptor_); 284 printer->Print(variables_, 285 "$deprecation$public boolean has$capitalized_name$() {\n" 286 " return $get_has_field_bit_builder$;\n" 287 "}\n"); 288 289 WriteFieldDocComment(printer, descriptor_); 290 printer->Print(variables_, 291 "$deprecation$public $type$ get$capitalized_name$() {\n" 292 " return $name$_;\n" 293 "}\n"); 294 295 WriteFieldDocComment(printer, descriptor_); 296 printer->Print(variables_, 297 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" 298 "$null_check$" 299 " $set_has_field_bit_builder$;\n" 300 " $name$_ = value;\n" 301 " $on_changed$\n" 302 " return this;\n" 303 "}\n"); 304 305 WriteFieldDocComment(printer, descriptor_); 306 printer->Print(variables_, 307 "$deprecation$public Builder clear$capitalized_name$() {\n" 308 " $clear_has_field_bit_builder$;\n"); 309 JavaType type = GetJavaType(descriptor_); 310 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { 311 // The default value is not a simple literal so we want to avoid executing 312 // it multiple times. Instead, get the default out of the default instance. 313 printer->Print(variables_, 314 " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); 315 } else { 316 printer->Print(variables_, 317 " $name$_ = $default$;\n"); 318 } 319 printer->Print(variables_, 320 " $on_changed$\n" 321 " return this;\n" 322 "}\n"); 323} 324 325void PrimitiveFieldGenerator:: 326GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 327 // noop for primitives 328} 329 330void PrimitiveFieldGenerator:: 331GenerateInitializationCode(io::Printer* printer) const { 332 printer->Print(variables_, "$name$_ = $default$;\n"); 333} 334 335void PrimitiveFieldGenerator:: 336GenerateBuilderClearCode(io::Printer* printer) const { 337 printer->Print(variables_, 338 "$name$_ = $default$;\n" 339 "$clear_has_field_bit_builder$;\n"); 340} 341 342void PrimitiveFieldGenerator:: 343GenerateMergingCode(io::Printer* printer) const { 344 printer->Print(variables_, 345 "if (other.has$capitalized_name$()) {\n" 346 " set$capitalized_name$(other.get$capitalized_name$());\n" 347 "}\n"); 348} 349 350void PrimitiveFieldGenerator:: 351GenerateBuildingCode(io::Printer* printer) const { 352 printer->Print(variables_, 353 "if ($get_has_field_bit_from_local$) {\n" 354 " $set_has_field_bit_to_local$;\n" 355 "}\n" 356 "result.$name$_ = $name$_;\n"); 357} 358 359void PrimitiveFieldGenerator:: 360GenerateParsingCode(io::Printer* printer) const { 361 printer->Print(variables_, 362 "$set_has_field_bit_message$;\n" 363 "$name$_ = input.read$capitalized_type$();\n"); 364} 365 366void PrimitiveFieldGenerator:: 367GenerateParsingDoneCode(io::Printer* printer) const { 368 // noop for primitives. 369} 370 371void PrimitiveFieldGenerator:: 372GenerateSerializationCode(io::Printer* printer) const { 373 printer->Print(variables_, 374 "if ($get_has_field_bit_message$) {\n" 375 " output.write$capitalized_type$($number$, $name$_);\n" 376 "}\n"); 377} 378 379void PrimitiveFieldGenerator:: 380GenerateSerializedSizeCode(io::Printer* printer) const { 381 printer->Print(variables_, 382 "if ($get_has_field_bit_message$) {\n" 383 " size += com.google.protobuf.CodedOutputStream\n" 384 " .compute$capitalized_type$Size($number$, $name$_);\n" 385 "}\n"); 386} 387 388void PrimitiveFieldGenerator:: 389GenerateEqualsCode(io::Printer* printer) const { 390 switch (GetJavaType(descriptor_)) { 391 case JAVATYPE_INT: 392 case JAVATYPE_LONG: 393 case JAVATYPE_BOOLEAN: 394 printer->Print(variables_, 395 "result = result && (get$capitalized_name$()\n" 396 " == other.get$capitalized_name$());\n"); 397 break; 398 399 case JAVATYPE_FLOAT: 400 printer->Print(variables_, 401 "result = result && (Float.floatToIntBits(get$capitalized_name$())" 402 " == Float.floatToIntBits(other.get$capitalized_name$()));\n"); 403 break; 404 405 case JAVATYPE_DOUBLE: 406 printer->Print(variables_, 407 "result = result && (Double.doubleToLongBits(get$capitalized_name$())" 408 " == Double.doubleToLongBits(other.get$capitalized_name$()));\n"); 409 break; 410 411 case JAVATYPE_STRING: 412 case JAVATYPE_BYTES: 413 printer->Print(variables_, 414 "result = result && get$capitalized_name$()\n" 415 " .equals(other.get$capitalized_name$());\n"); 416 break; 417 418 case JAVATYPE_ENUM: 419 case JAVATYPE_MESSAGE: 420 default: 421 GOOGLE_LOG(FATAL) << "Can't get here."; 422 break; 423 } 424} 425 426void PrimitiveFieldGenerator:: 427GenerateHashCode(io::Printer* printer) const { 428 printer->Print(variables_, 429 "hash = (37 * hash) + $constant_name$;\n"); 430 switch (GetJavaType(descriptor_)) { 431 case JAVATYPE_INT: 432 printer->Print(variables_, 433 "hash = (53 * hash) + get$capitalized_name$();\n"); 434 break; 435 436 case JAVATYPE_LONG: 437 printer->Print(variables_, 438 "hash = (53 * hash) + hashLong(get$capitalized_name$());\n"); 439 break; 440 441 case JAVATYPE_BOOLEAN: 442 printer->Print(variables_, 443 "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n"); 444 break; 445 446 case JAVATYPE_FLOAT: 447 printer->Print(variables_, 448 "hash = (53 * hash) + Float.floatToIntBits(\n" 449 " get$capitalized_name$());\n"); 450 break; 451 452 case JAVATYPE_DOUBLE: 453 printer->Print(variables_, 454 "hash = (53 * hash) + hashLong(\n" 455 " Double.doubleToLongBits(get$capitalized_name$()));\n"); 456 break; 457 458 case JAVATYPE_STRING: 459 case JAVATYPE_BYTES: 460 printer->Print(variables_, 461 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); 462 break; 463 464 case JAVATYPE_ENUM: 465 case JAVATYPE_MESSAGE: 466 default: 467 GOOGLE_LOG(FATAL) << "Can't get here."; 468 break; 469 } 470} 471 472string PrimitiveFieldGenerator::GetBoxedType() const { 473 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 474} 475 476// =================================================================== 477 478RepeatedPrimitiveFieldGenerator:: 479RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 480 int messageBitIndex, 481 int builderBitIndex) 482 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 483 builderBitIndex_(builderBitIndex) { 484 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 485 &variables_); 486} 487 488RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 489 490int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const { 491 return 0; 492} 493 494int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const { 495 return 1; 496} 497 498void RepeatedPrimitiveFieldGenerator:: 499GenerateInterfaceMembers(io::Printer* printer) const { 500 WriteFieldDocComment(printer, descriptor_); 501 printer->Print(variables_, 502 "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); 503 WriteFieldDocComment(printer, descriptor_); 504 printer->Print(variables_, 505 "$deprecation$int get$capitalized_name$Count();\n"); 506 WriteFieldDocComment(printer, descriptor_); 507 printer->Print(variables_, 508 "$deprecation$$type$ get$capitalized_name$(int index);\n"); 509} 510 511 512void RepeatedPrimitiveFieldGenerator:: 513GenerateMembers(io::Printer* printer) const { 514 printer->Print(variables_, 515 "private $field_list_type$ $name$_;\n"); 516 WriteFieldDocComment(printer, descriptor_); 517 printer->Print(variables_, 518 "$deprecation$public java.util.List<$boxed_type$>\n" 519 " get$capitalized_name$List() {\n" 520 " return $name$_;\n" // note: unmodifiable list 521 "}\n"); 522 WriteFieldDocComment(printer, descriptor_); 523 printer->Print(variables_, 524 "$deprecation$public int get$capitalized_name$Count() {\n" 525 " return $name$_.size();\n" 526 "}\n"); 527 WriteFieldDocComment(printer, descriptor_); 528 printer->Print(variables_, 529 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 530 " return $name$_.get(index);\n" 531 "}\n"); 532 533 if (descriptor_->options().packed() && 534 HasGeneratedMethods(descriptor_->containing_type())) { 535 printer->Print(variables_, 536 "private int $name$MemoizedSerializedSize = -1;\n"); 537 } 538} 539 540void RepeatedPrimitiveFieldGenerator:: 541GenerateBuilderMembers(io::Printer* printer) const { 542 // One field is the list and the bit field keeps track of whether the 543 // list is immutable. If it's immutable, the invariant is that it must 544 // either an instance of Collections.emptyList() or it's an ArrayList 545 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 546 // a refererence to the underlying ArrayList. This invariant allows us to 547 // share instances of lists between protocol buffers avoiding expensive 548 // memory allocations. Note, immutable is a strong guarantee here -- not 549 // just that the list cannot be modified via the reference but that the 550 // list can never be modified. 551 printer->Print(variables_, 552 "private $field_list_type$ $name$_ = $empty_list$;\n"); 553 554 printer->Print(variables_, 555 "private void ensure$capitalized_name$IsMutable() {\n" 556 " if (!$get_mutable_bit_builder$) {\n" 557 " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" 558 " $set_mutable_bit_builder$;\n" 559 " }\n" 560 "}\n"); 561 562 // Note: We return an unmodifiable list because otherwise the caller 563 // could hold on to the returned list and modify it after the message 564 // has been built, thus mutating the message which is supposed to be 565 // immutable. 566 WriteFieldDocComment(printer, descriptor_); 567 printer->Print(variables_, 568 "$deprecation$public java.util.List<$boxed_type$>\n" 569 " get$capitalized_name$List() {\n" 570 " return java.util.Collections.unmodifiableList($name$_);\n" 571 "}\n"); 572 WriteFieldDocComment(printer, descriptor_); 573 printer->Print(variables_, 574 "$deprecation$public int get$capitalized_name$Count() {\n" 575 " return $name$_.size();\n" 576 "}\n"); 577 WriteFieldDocComment(printer, descriptor_); 578 printer->Print(variables_, 579 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 580 " return $name$_.get(index);\n" 581 "}\n"); 582 WriteFieldDocComment(printer, descriptor_); 583 printer->Print(variables_, 584 "$deprecation$public Builder set$capitalized_name$(\n" 585 " int index, $type$ value) {\n" 586 "$null_check$" 587 " ensure$capitalized_name$IsMutable();\n" 588 " $name$_.set(index, value);\n" 589 " $on_changed$\n" 590 " return this;\n" 591 "}\n"); 592 WriteFieldDocComment(printer, descriptor_); 593 printer->Print(variables_, 594 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" 595 "$null_check$" 596 " ensure$capitalized_name$IsMutable();\n" 597 " $name$_.add(value);\n" 598 " $on_changed$\n" 599 " return this;\n" 600 "}\n"); 601 WriteFieldDocComment(printer, descriptor_); 602 printer->Print(variables_, 603 "$deprecation$public Builder addAll$capitalized_name$(\n" 604 " java.lang.Iterable<? extends $boxed_type$> values) {\n" 605 " ensure$capitalized_name$IsMutable();\n" 606 " super.addAll(values, $name$_);\n" 607 " $on_changed$\n" 608 " return this;\n" 609 "}\n"); 610 WriteFieldDocComment(printer, descriptor_); 611 printer->Print(variables_, 612 "$deprecation$public Builder clear$capitalized_name$() {\n" 613 " $name$_ = $empty_list$;\n" 614 " $clear_mutable_bit_builder$;\n" 615 " $on_changed$\n" 616 " return this;\n" 617 "}\n"); 618} 619 620void RepeatedPrimitiveFieldGenerator:: 621GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 622 // noop for primitives 623} 624 625void RepeatedPrimitiveFieldGenerator:: 626GenerateInitializationCode(io::Printer* printer) const { 627 printer->Print(variables_, "$name$_ = $empty_list$;\n"); 628} 629 630void RepeatedPrimitiveFieldGenerator:: 631GenerateBuilderClearCode(io::Printer* printer) const { 632 printer->Print(variables_, 633 "$name$_ = $empty_list$;\n" 634 "$clear_mutable_bit_builder$;\n"); 635} 636 637void RepeatedPrimitiveFieldGenerator:: 638GenerateMergingCode(io::Printer* printer) const { 639 // The code below does two optimizations: 640 // 1. If the other list is empty, there's nothing to do. This ensures we 641 // don't allocate a new array if we already have an immutable one. 642 // 2. If the other list is non-empty and our current list is empty, we can 643 // reuse the other list which is guaranteed to be immutable. 644 printer->Print(variables_, 645 "if (!other.$name$_.isEmpty()) {\n" 646 " if ($name$_.isEmpty()) {\n" 647 " $name$_ = other.$name$_;\n" 648 " $clear_mutable_bit_builder$;\n" 649 " } else {\n" 650 " ensure$capitalized_name$IsMutable();\n" 651 " $name$_.addAll(other.$name$_);\n" 652 " }\n" 653 " $on_changed$\n" 654 "}\n"); 655} 656 657void RepeatedPrimitiveFieldGenerator:: 658GenerateBuildingCode(io::Printer* printer) const { 659 // The code below ensures that the result has an immutable list. If our 660 // list is immutable, we can just reuse it. If not, we make it immutable. 661 printer->Print(variables_, 662 "if ($get_mutable_bit_builder$) {\n" 663 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 664 " $clear_mutable_bit_builder$;\n" 665 "}\n" 666 "result.$name$_ = $name$_;\n"); 667} 668 669void RepeatedPrimitiveFieldGenerator:: 670GenerateParsingCode(io::Printer* printer) const { 671 printer->Print(variables_, 672 "if (!$get_mutable_bit_parser$) {\n" 673 " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" 674 " $set_mutable_bit_parser$;\n" 675 "}\n" 676 "$name$_.add(input.read$capitalized_type$());\n"); 677} 678 679void RepeatedPrimitiveFieldGenerator:: 680GenerateParsingCodeFromPacked(io::Printer* printer) const { 681 printer->Print(variables_, 682 "int length = input.readRawVarint32();\n" 683 "int limit = input.pushLimit(length);\n" 684 "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" 685 " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" 686 " $set_mutable_bit_parser$;\n" 687 "}\n" 688 "while (input.getBytesUntilLimit() > 0) {\n" 689 " $name$_.add(input.read$capitalized_type$());\n" 690 "}\n" 691 "input.popLimit(limit);\n"); 692} 693 694void RepeatedPrimitiveFieldGenerator:: 695GenerateParsingDoneCode(io::Printer* printer) const { 696 printer->Print(variables_, 697 "if ($get_mutable_bit_parser$) {\n" 698 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 699 "}\n"); 700} 701 702void RepeatedPrimitiveFieldGenerator:: 703GenerateSerializationCode(io::Printer* printer) const { 704 if (descriptor_->options().packed()) { 705 printer->Print(variables_, 706 "if (get$capitalized_name$List().size() > 0) {\n" 707 " output.writeRawVarint32($tag$);\n" 708 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 709 "}\n" 710 "for (int i = 0; i < $name$_.size(); i++) {\n" 711 " output.write$capitalized_type$NoTag($name$_.get(i));\n" 712 "}\n"); 713 } else { 714 printer->Print(variables_, 715 "for (int i = 0; i < $name$_.size(); i++) {\n" 716 " output.write$capitalized_type$($number$, $name$_.get(i));\n" 717 "}\n"); 718 } 719} 720 721void RepeatedPrimitiveFieldGenerator:: 722GenerateSerializedSizeCode(io::Printer* printer) const { 723 printer->Print(variables_, 724 "{\n" 725 " int dataSize = 0;\n"); 726 printer->Indent(); 727 728 if (FixedSize(GetType(descriptor_)) == -1) { 729 printer->Print(variables_, 730 "for (int i = 0; i < $name$_.size(); i++) {\n" 731 " dataSize += com.google.protobuf.CodedOutputStream\n" 732 " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" 733 "}\n"); 734 } else { 735 printer->Print(variables_, 736 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); 737 } 738 739 printer->Print( 740 "size += dataSize;\n"); 741 742 if (descriptor_->options().packed()) { 743 printer->Print(variables_, 744 "if (!get$capitalized_name$List().isEmpty()) {\n" 745 " size += $tag_size$;\n" 746 " size += com.google.protobuf.CodedOutputStream\n" 747 " .computeInt32SizeNoTag(dataSize);\n" 748 "}\n"); 749 } else { 750 printer->Print(variables_, 751 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 752 } 753 754 // cache the data size for packed fields. 755 if (descriptor_->options().packed()) { 756 printer->Print(variables_, 757 "$name$MemoizedSerializedSize = dataSize;\n"); 758 } 759 760 printer->Outdent(); 761 printer->Print("}\n"); 762} 763 764void RepeatedPrimitiveFieldGenerator:: 765GenerateEqualsCode(io::Printer* printer) const { 766 printer->Print(variables_, 767 "result = result && get$capitalized_name$List()\n" 768 " .equals(other.get$capitalized_name$List());\n"); 769} 770 771void RepeatedPrimitiveFieldGenerator:: 772GenerateHashCode(io::Printer* printer) const { 773 printer->Print(variables_, 774 "if (get$capitalized_name$Count() > 0) {\n" 775 " hash = (37 * hash) + $constant_name$;\n" 776 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" 777 "}\n"); 778} 779 780string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { 781 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 782} 783 784} // namespace java 785} // namespace compiler 786} // namespace protobuf 787} // namespace google 788