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