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