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// Author: jonp@google.com (Jon Perlow) 33// Based on original Protocol Buffers design by 34// Sanjay Ghemawat, Jeff Dean, and others. 35 36#include <map> 37#include <string> 38 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_string_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)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; 68 69 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); 70 (*variables)["default_init"] = 71 "= " + ImmutableDefaultValue(descriptor, name_resolver); 72 (*variables)["capitalized_type"] = "String"; 73 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 74 (*variables)["tag_size"] = SimpleItoa( 75 WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 76 (*variables)["null_check"] = 77 " if (value == null) {\n" 78 " throw new NullPointerException();\n" 79 " }\n"; 80 81 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 82 // by the proto compiler 83 (*variables)["deprecation"] = descriptor->options().deprecated() 84 ? "@java.lang.Deprecated " : ""; 85 (*variables)["on_changed"] = 86 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; 87 88 if (SupportFieldPresence(descriptor->file())) { 89 // For singular messages and builders, one bit is used for the hasField bit. 90 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 91 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 92 93 // Note that these have a trailing ";". 94 (*variables)["set_has_field_bit_message"] = 95 GenerateSetBit(messageBitIndex) + ";"; 96 (*variables)["set_has_field_bit_builder"] = 97 GenerateSetBit(builderBitIndex) + ";"; 98 (*variables)["clear_has_field_bit_builder"] = 99 GenerateClearBit(builderBitIndex) + ";"; 100 101 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); 102 } else { 103 (*variables)["set_has_field_bit_message"] = ""; 104 (*variables)["set_has_field_bit_builder"] = ""; 105 (*variables)["clear_has_field_bit_builder"] = ""; 106 107 (*variables)["is_field_present_message"] = 108 "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; 109 } 110 111 // For repeated builders, one bit is used for whether the array is immutable. 112 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 113 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 114 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 115 116 // For repeated fields, one bit is used for whether the array is immutable 117 // in the parsing constructor. 118 (*variables)["get_mutable_bit_parser"] = 119 GenerateGetBitMutableLocal(builderBitIndex); 120 (*variables)["set_mutable_bit_parser"] = 121 GenerateSetBitMutableLocal(builderBitIndex); 122 123 (*variables)["get_has_field_bit_from_local"] = 124 GenerateGetBitFromLocal(builderBitIndex); 125 (*variables)["set_has_field_bit_to_local"] = 126 GenerateSetBitToLocal(messageBitIndex); 127} 128 129bool CheckUtf8(const FieldDescriptor* descriptor) { 130 return descriptor->file()->options().java_string_check_utf8(); 131} 132 133} // namespace 134 135// =================================================================== 136 137ImmutableStringFieldGenerator:: 138ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, 139 int messageBitIndex, 140 int builderBitIndex, 141 Context* context) 142 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 143 builderBitIndex_(builderBitIndex), context_(context), 144 name_resolver_(context->GetNameResolver()) { 145 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 146 context->GetFieldGeneratorInfo(descriptor), 147 name_resolver_, &variables_); 148} 149 150ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} 151 152int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { 153 return 1; 154} 155 156int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { 157 return 1; 158} 159 160// A note about how strings are handled. This code used to just store a String 161// in the Message. This had two issues: 162// 163// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded 164// strings, but rather fields that were raw bytes incorrectly marked 165// as strings in the proto file. This is common because in the proto1 166// syntax, string was the way to indicate bytes and C++ engineers can 167// easily make this mistake without affecting the C++ API. By converting to 168// strings immediately, some java code might corrupt these byte arrays as 169// it passes through a java server even if the field was never accessed by 170// application code. 171// 172// 2. There's a performance hit to converting between bytes and strings and 173// it many cases, the field is never even read by the application code. This 174// avoids unnecessary conversions in the common use cases. 175// 176// So now, the field for String is maintained as an Object reference which can 177// either store a String or a ByteString. The code uses an instanceof check 178// to see which one it has and converts to the other one if needed. It remembers 179// the last value requested (in a thread safe manner) as this is most likely 180// the one needed next. The thread safety is such that if two threads both 181// convert the field because the changes made by each thread were not visible to 182// the other, they may cause a conversion to happen more times than would 183// otherwise be necessary. This was deemed better than adding synchronization 184// overhead. It will not cause any corruption issues or affect the behavior of 185// the API. The instanceof check is also highly optimized in the JVM and we 186// decided it was better to reduce the memory overhead by not having two 187// separate fields but rather use dynamic type checking. 188// 189// For single fields, the logic for this is done inside the generated code. For 190// repeated fields, the logic is done in LazyStringArrayList and 191// UnmodifiableLazyStringList. 192void ImmutableStringFieldGenerator:: 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$java.lang.String get$capitalized_name$();\n"); 202 WriteFieldDocComment(printer, descriptor_); 203 printer->Print(variables_, 204 "$deprecation$com.google.protobuf.ByteString\n" 205 " get$capitalized_name$Bytes();\n"); 206} 207 208void ImmutableStringFieldGenerator:: 209GenerateMembers(io::Printer* printer) const { 210 printer->Print(variables_, 211 "private java.lang.Object $name$_;\n"); 212 PrintExtraFieldInfo(variables_, printer); 213 214 if (SupportFieldPresence(descriptor_->file())) { 215 WriteFieldDocComment(printer, descriptor_); 216 printer->Print(variables_, 217 "$deprecation$public boolean has$capitalized_name$() {\n" 218 " return $get_has_field_bit_message$;\n" 219 "}\n"); 220 } 221 222 WriteFieldDocComment(printer, descriptor_); 223 printer->Print(variables_, 224 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 225 " java.lang.Object ref = $name$_;\n" 226 " if (ref instanceof java.lang.String) {\n" 227 " return (java.lang.String) ref;\n" 228 " } else {\n" 229 " com.google.protobuf.ByteString bs = \n" 230 " (com.google.protobuf.ByteString) ref;\n" 231 " java.lang.String s = bs.toStringUtf8();\n"); 232 if (CheckUtf8(descriptor_)) { 233 printer->Print(variables_, 234 " $name$_ = s;\n"); 235 } else { 236 printer->Print(variables_, 237 " if (bs.isValidUtf8()) {\n" 238 " $name$_ = s;\n" 239 " }\n"); 240 } 241 printer->Print(variables_, 242 " return s;\n" 243 " }\n" 244 "}\n"); 245 WriteFieldDocComment(printer, descriptor_); 246 printer->Print(variables_, 247 "$deprecation$public com.google.protobuf.ByteString\n" 248 " get$capitalized_name$Bytes() {\n" 249 " java.lang.Object ref = $name$_;\n" 250 " if (ref instanceof java.lang.String) {\n" 251 " com.google.protobuf.ByteString b = \n" 252 " com.google.protobuf.ByteString.copyFromUtf8(\n" 253 " (java.lang.String) ref);\n" 254 " $name$_ = b;\n" 255 " return b;\n" 256 " } else {\n" 257 " return (com.google.protobuf.ByteString) ref;\n" 258 " }\n" 259 "}\n"); 260} 261 262void ImmutableStringFieldGenerator:: 263GenerateBuilderMembers(io::Printer* printer) const { 264 printer->Print(variables_, 265 "private java.lang.Object $name$_ $default_init$;\n"); 266 if (SupportFieldPresence(descriptor_->file())) { 267 WriteFieldDocComment(printer, descriptor_); 268 printer->Print(variables_, 269 "$deprecation$public boolean has$capitalized_name$() {\n" 270 " return $get_has_field_bit_builder$;\n" 271 "}\n"); 272 } 273 274 WriteFieldDocComment(printer, descriptor_); 275 printer->Print(variables_, 276 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 277 " java.lang.Object ref = $name$_;\n" 278 " if (!(ref instanceof java.lang.String)) {\n" 279 " com.google.protobuf.ByteString bs =\n" 280 " (com.google.protobuf.ByteString) ref;\n" 281 " java.lang.String s = bs.toStringUtf8();\n"); 282 if (CheckUtf8(descriptor_)) { 283 printer->Print(variables_, 284 " $name$_ = s;\n"); 285 } else { 286 printer->Print(variables_, 287 " if (bs.isValidUtf8()) {\n" 288 " $name$_ = s;\n" 289 " }\n"); 290 } 291 printer->Print(variables_, 292 " return s;\n" 293 " } else {\n" 294 " return (java.lang.String) ref;\n" 295 " }\n" 296 "}\n"); 297 298 WriteFieldDocComment(printer, descriptor_); 299 printer->Print(variables_, 300 "$deprecation$public com.google.protobuf.ByteString\n" 301 " get$capitalized_name$Bytes() {\n" 302 " java.lang.Object ref = $name$_;\n" 303 " if (ref instanceof String) {\n" 304 " com.google.protobuf.ByteString b = \n" 305 " com.google.protobuf.ByteString.copyFromUtf8(\n" 306 " (java.lang.String) ref);\n" 307 " $name$_ = b;\n" 308 " return b;\n" 309 " } else {\n" 310 " return (com.google.protobuf.ByteString) ref;\n" 311 " }\n" 312 "}\n"); 313 314 WriteFieldDocComment(printer, descriptor_); 315 printer->Print(variables_, 316 "$deprecation$public Builder set$capitalized_name$(\n" 317 " java.lang.String value) {\n" 318 "$null_check$" 319 " $set_has_field_bit_builder$\n" 320 " $name$_ = value;\n" 321 " $on_changed$\n" 322 " return this;\n" 323 "}\n"); 324 WriteFieldDocComment(printer, descriptor_); 325 printer->Print(variables_, 326 "$deprecation$public Builder clear$capitalized_name$() {\n" 327 " $clear_has_field_bit_builder$\n"); 328 // The default value is not a simple literal so we want to avoid executing 329 // it multiple times. Instead, get the default out of the default instance. 330 printer->Print(variables_, 331 " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); 332 printer->Print(variables_, 333 " $on_changed$\n" 334 " return this;\n" 335 "}\n"); 336 337 WriteFieldDocComment(printer, descriptor_); 338 printer->Print(variables_, 339 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 340 " com.google.protobuf.ByteString value) {\n" 341 "$null_check$"); 342 if (CheckUtf8(descriptor_)) { 343 printer->Print(variables_, 344 " checkByteStringIsUtf8(value);\n"); 345 } 346 printer->Print(variables_, 347 " $set_has_field_bit_builder$\n" 348 " $name$_ = value;\n" 349 " $on_changed$\n" 350 " return this;\n" 351 "}\n"); 352} 353 354void ImmutableStringFieldGenerator:: 355GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 356 // noop for primitives 357} 358 359void ImmutableStringFieldGenerator:: 360GenerateInitializationCode(io::Printer* printer) const { 361 printer->Print(variables_, "$name$_ = $default$;\n"); 362} 363 364void ImmutableStringFieldGenerator:: 365GenerateBuilderClearCode(io::Printer* printer) const { 366 printer->Print(variables_, 367 "$name$_ = $default$;\n" 368 "$clear_has_field_bit_builder$\n"); 369} 370 371void ImmutableStringFieldGenerator:: 372GenerateMergingCode(io::Printer* printer) const { 373 if (SupportFieldPresence(descriptor_->file())) { 374 // Allow a slight breach of abstraction here in order to avoid forcing 375 // all string fields to Strings when copying fields from a Message. 376 printer->Print(variables_, 377 "if (other.has$capitalized_name$()) {\n" 378 " $set_has_field_bit_builder$\n" 379 " $name$_ = other.$name$_;\n" 380 " $on_changed$\n" 381 "}\n"); 382 } else { 383 printer->Print(variables_, 384 "if (!other.get$capitalized_name$().isEmpty()) {\n" 385 " $name$_ = other.$name$_;\n" 386 " $on_changed$\n" 387 "}\n"); 388 } 389} 390 391void ImmutableStringFieldGenerator:: 392GenerateBuildingCode(io::Printer* printer) const { 393 if (SupportFieldPresence(descriptor_->file())) { 394 printer->Print(variables_, 395 "if ($get_has_field_bit_from_local$) {\n" 396 " $set_has_field_bit_to_local$;\n" 397 "}\n"); 398 } 399 printer->Print(variables_, 400 "result.$name$_ = $name$_;\n"); 401} 402 403void ImmutableStringFieldGenerator:: 404GenerateParsingCode(io::Printer* printer) const { 405 if (CheckUtf8(descriptor_)) { 406 printer->Print(variables_, 407 "String s = input.readStringRequireUtf8();\n" 408 "$set_has_field_bit_message$\n" 409 "$name$_ = s;\n"); 410 } else { 411 printer->Print(variables_, 412 "com.google.protobuf.ByteString bs = input.readBytes();\n" 413 "$set_has_field_bit_message$\n" 414 "$name$_ = bs;\n"); 415 } 416} 417 418void ImmutableStringFieldGenerator:: 419GenerateParsingDoneCode(io::Printer* printer) const { 420 // noop for strings. 421} 422 423void ImmutableStringFieldGenerator:: 424GenerateSerializationCode(io::Printer* printer) const { 425 printer->Print(variables_, 426 "if ($is_field_present_message$) {\n" 427 " output.writeBytes($number$, get$capitalized_name$Bytes());\n" 428 "}\n"); 429} 430 431void ImmutableStringFieldGenerator:: 432GenerateSerializedSizeCode(io::Printer* printer) const { 433 printer->Print(variables_, 434 "if ($is_field_present_message$) {\n" 435 " size += com.google.protobuf.CodedOutputStream\n" 436 " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" 437 "}\n"); 438} 439 440void ImmutableStringFieldGenerator:: 441GenerateEqualsCode(io::Printer* printer) const { 442 printer->Print(variables_, 443 "result = result && get$capitalized_name$()\n" 444 " .equals(other.get$capitalized_name$());\n"); 445} 446 447void ImmutableStringFieldGenerator:: 448GenerateHashCode(io::Printer* printer) const { 449 printer->Print(variables_, 450 "hash = (37 * hash) + $constant_name$;\n"); 451 printer->Print(variables_, 452 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); 453} 454 455string ImmutableStringFieldGenerator::GetBoxedType() const { 456 return "java.lang.String"; 457} 458 459// =================================================================== 460 461ImmutableStringOneofFieldGenerator:: 462ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, 463 int messageBitIndex, 464 int builderBitIndex, 465 Context* context) 466 : ImmutableStringFieldGenerator( 467 descriptor, messageBitIndex, builderBitIndex, context) { 468 const OneofGeneratorInfo* info = 469 context->GetOneofGeneratorInfo(descriptor->containing_oneof()); 470 SetCommonOneofVariables(descriptor, info, &variables_); 471} 472 473ImmutableStringOneofFieldGenerator:: 474~ImmutableStringOneofFieldGenerator() {} 475 476void ImmutableStringOneofFieldGenerator:: 477GenerateMembers(io::Printer* printer) const { 478 PrintExtraFieldInfo(variables_, printer); 479 480 if (SupportFieldPresence(descriptor_->file())) { 481 WriteFieldDocComment(printer, descriptor_); 482 printer->Print(variables_, 483 "$deprecation$public boolean has$capitalized_name$() {\n" 484 " return $has_oneof_case_message$;\n" 485 "}\n"); 486 } 487 488 WriteFieldDocComment(printer, descriptor_); 489 printer->Print(variables_, 490 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 491 " java.lang.Object ref $default_init$;\n" 492 " if ($has_oneof_case_message$) {\n" 493 " ref = $oneof_name$_;\n" 494 " }\n" 495 " if (ref instanceof java.lang.String) {\n" 496 " return (java.lang.String) ref;\n" 497 " } else {\n" 498 " com.google.protobuf.ByteString bs = \n" 499 " (com.google.protobuf.ByteString) ref;\n" 500 " java.lang.String s = bs.toStringUtf8();\n"); 501 if (CheckUtf8(descriptor_)) { 502 printer->Print(variables_, 503 " if ($has_oneof_case_message$) {\n" 504 " $oneof_name$_ = s;\n" 505 " }\n"); 506 } else { 507 printer->Print(variables_, 508 " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" 509 " $oneof_name$_ = s;\n" 510 " }\n"); 511 } 512 printer->Print(variables_, 513 " return s;\n" 514 " }\n" 515 "}\n"); 516 WriteFieldDocComment(printer, descriptor_); 517 518 printer->Print(variables_, 519 "$deprecation$public com.google.protobuf.ByteString\n" 520 " get$capitalized_name$Bytes() {\n" 521 " java.lang.Object ref $default_init$;\n" 522 " if ($has_oneof_case_message$) {\n" 523 " ref = $oneof_name$_;\n" 524 " }\n" 525 " if (ref instanceof java.lang.String) {\n" 526 " com.google.protobuf.ByteString b = \n" 527 " com.google.protobuf.ByteString.copyFromUtf8(\n" 528 " (java.lang.String) ref);\n" 529 " if ($has_oneof_case_message$) {\n" 530 " $oneof_name$_ = b;\n" 531 " }\n" 532 " return b;\n" 533 " } else {\n" 534 " return (com.google.protobuf.ByteString) ref;\n" 535 " }\n" 536 "}\n"); 537} 538 539void ImmutableStringOneofFieldGenerator:: 540GenerateBuilderMembers(io::Printer* printer) const { 541 if (SupportFieldPresence(descriptor_->file())) { 542 WriteFieldDocComment(printer, descriptor_); 543 printer->Print(variables_, 544 "$deprecation$public boolean has$capitalized_name$() {\n" 545 " return $has_oneof_case_message$;\n" 546 "}\n"); 547 } 548 549 WriteFieldDocComment(printer, descriptor_); 550 printer->Print(variables_, 551 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 552 " java.lang.Object ref $default_init$;\n" 553 " if ($has_oneof_case_message$) {\n" 554 " ref = $oneof_name$_;\n" 555 " }\n" 556 " if (!(ref instanceof java.lang.String)) {\n" 557 " com.google.protobuf.ByteString bs =\n" 558 " (com.google.protobuf.ByteString) ref;\n" 559 " java.lang.String s = bs.toStringUtf8();\n" 560 " if ($has_oneof_case_message$) {\n"); 561 if (CheckUtf8(descriptor_)) { 562 printer->Print(variables_, 563 " $oneof_name$_ = s;\n"); 564 } else { 565 printer->Print(variables_, 566 " if (bs.isValidUtf8()) {\n" 567 " $oneof_name$_ = s;\n" 568 " }\n"); 569 } 570 printer->Print(variables_, 571 " }\n" 572 " return s;\n" 573 " } else {\n" 574 " return (java.lang.String) ref;\n" 575 " }\n" 576 "}\n"); 577 578 WriteFieldDocComment(printer, descriptor_); 579 printer->Print(variables_, 580 "$deprecation$public com.google.protobuf.ByteString\n" 581 " get$capitalized_name$Bytes() {\n" 582 " java.lang.Object ref $default_init$;\n" 583 " if ($has_oneof_case_message$) {\n" 584 " ref = $oneof_name$_;\n" 585 " }\n" 586 " if (ref instanceof String) {\n" 587 " com.google.protobuf.ByteString b = \n" 588 " com.google.protobuf.ByteString.copyFromUtf8(\n" 589 " (java.lang.String) ref);\n" 590 " if ($has_oneof_case_message$) {\n" 591 " $oneof_name$_ = b;\n" 592 " }\n" 593 " return b;\n" 594 " } else {\n" 595 " return (com.google.protobuf.ByteString) ref;\n" 596 " }\n" 597 "}\n"); 598 599 WriteFieldDocComment(printer, descriptor_); 600 printer->Print(variables_, 601 "$deprecation$public Builder set$capitalized_name$(\n" 602 " java.lang.String value) {\n" 603 "$null_check$" 604 " $set_oneof_case_message$;\n" 605 " $oneof_name$_ = value;\n" 606 " $on_changed$\n" 607 " return this;\n" 608 "}\n"); 609 WriteFieldDocComment(printer, descriptor_); 610 printer->Print(variables_, 611 "$deprecation$public Builder clear$capitalized_name$() {\n" 612 " if ($has_oneof_case_message$) {\n" 613 " $clear_oneof_case_message$;\n" 614 " $oneof_name$_ = null;\n" 615 " $on_changed$\n" 616 " }\n" 617 " return this;\n" 618 "}\n"); 619 620 WriteFieldDocComment(printer, descriptor_); 621 printer->Print(variables_, 622 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 623 " com.google.protobuf.ByteString value) {\n" 624 "$null_check$"); 625 if (CheckUtf8(descriptor_)) { 626 printer->Print(variables_, 627 " checkByteStringIsUtf8(value);\n"); 628 } 629 printer->Print(variables_, 630 " $set_oneof_case_message$;\n" 631 " $oneof_name$_ = value;\n" 632 " $on_changed$\n" 633 " return this;\n" 634 "}\n"); 635} 636 637void ImmutableStringOneofFieldGenerator:: 638GenerateMergingCode(io::Printer* printer) const { 639 // Allow a slight breach of abstraction here in order to avoid forcing 640 // all string fields to Strings when copying fields from a Message. 641 printer->Print(variables_, 642 "$set_oneof_case_message$;\n" 643 "$oneof_name$_ = other.$oneof_name$_;\n" 644 "$on_changed$\n"); 645} 646 647void ImmutableStringOneofFieldGenerator:: 648GenerateBuildingCode(io::Printer* printer) const { 649 printer->Print(variables_, 650 "if ($has_oneof_case_message$) {\n" 651 " result.$oneof_name$_ = $oneof_name$_;\n" 652 "}\n"); 653} 654 655void ImmutableStringOneofFieldGenerator:: 656GenerateParsingCode(io::Printer* printer) const { 657 if (CheckUtf8(descriptor_)) { 658 printer->Print(variables_, 659 "String s = input.readStringRequireUtf8();\n" 660 "$set_oneof_case_message$;\n" 661 "$oneof_name$_ = s;\n}\n"); 662 } else { 663 printer->Print(variables_, 664 "com.google.protobuf.ByteString bs = input.readBytes();\n" 665 "$set_oneof_case_message$;\n" 666 "$oneof_name$_ = bs;\n"); 667 } 668} 669 670void ImmutableStringOneofFieldGenerator:: 671GenerateSerializationCode(io::Printer* printer) const { 672 printer->Print(variables_, 673 "if ($has_oneof_case_message$) {\n" 674 " output.writeBytes($number$, get$capitalized_name$Bytes());\n" 675 "}\n"); 676} 677 678void ImmutableStringOneofFieldGenerator:: 679GenerateSerializedSizeCode(io::Printer* printer) const { 680 printer->Print(variables_, 681 "if ($has_oneof_case_message$) {\n" 682 " size += com.google.protobuf.CodedOutputStream\n" 683 " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" 684 "}\n"); 685} 686 687// =================================================================== 688 689RepeatedImmutableStringFieldGenerator:: 690RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, 691 int messageBitIndex, 692 int builderBitIndex, 693 Context* context) 694 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 695 builderBitIndex_(builderBitIndex), context_(context), 696 name_resolver_(context->GetNameResolver()) { 697 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 698 context->GetFieldGeneratorInfo(descriptor), 699 name_resolver_, &variables_); 700} 701 702RepeatedImmutableStringFieldGenerator:: 703~RepeatedImmutableStringFieldGenerator() {} 704 705int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { 706 return 0; 707} 708 709int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { 710 return 1; 711} 712 713void RepeatedImmutableStringFieldGenerator:: 714GenerateInterfaceMembers(io::Printer* printer) const { 715 WriteFieldDocComment(printer, descriptor_); 716 printer->Print(variables_, 717 "$deprecation$com.google.protobuf.ProtocolStringList\n" 718 " get$capitalized_name$List();\n"); 719 WriteFieldDocComment(printer, descriptor_); 720 printer->Print(variables_, 721 "$deprecation$int get$capitalized_name$Count();\n"); 722 WriteFieldDocComment(printer, descriptor_); 723 printer->Print(variables_, 724 "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); 725 WriteFieldDocComment(printer, descriptor_); 726 printer->Print(variables_, 727 "$deprecation$com.google.protobuf.ByteString\n" 728 " get$capitalized_name$Bytes(int index);\n"); 729} 730 731 732void RepeatedImmutableStringFieldGenerator:: 733GenerateMembers(io::Printer* printer) const { 734 printer->Print(variables_, 735 "private com.google.protobuf.LazyStringList $name$_;\n"); 736 PrintExtraFieldInfo(variables_, printer); 737 WriteFieldDocComment(printer, descriptor_); 738 printer->Print(variables_, 739 "$deprecation$public com.google.protobuf.ProtocolStringList\n" 740 " get$capitalized_name$List() {\n" 741 " return $name$_;\n" // note: unmodifiable list 742 "}\n"); 743 WriteFieldDocComment(printer, descriptor_); 744 printer->Print(variables_, 745 "$deprecation$public int get$capitalized_name$Count() {\n" 746 " return $name$_.size();\n" 747 "}\n"); 748 WriteFieldDocComment(printer, descriptor_); 749 printer->Print(variables_, 750 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 751 " return $name$_.get(index);\n" 752 "}\n"); 753 WriteFieldDocComment(printer, descriptor_); 754 printer->Print(variables_, 755 "$deprecation$public com.google.protobuf.ByteString\n" 756 " get$capitalized_name$Bytes(int index) {\n" 757 " return $name$_.getByteString(index);\n" 758 "}\n"); 759 760 if (descriptor_->options().packed() && 761 HasGeneratedMethods(descriptor_->containing_type())) { 762 printer->Print(variables_, 763 "private int $name$MemoizedSerializedSize = -1;\n"); 764 } 765} 766 767void RepeatedImmutableStringFieldGenerator:: 768GenerateBuilderMembers(io::Printer* printer) const { 769 // One field is the list and the bit field keeps track of whether the 770 // list is immutable. If it's immutable, the invariant is that it must 771 // either an instance of Collections.emptyList() or it's an ArrayList 772 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 773 // a refererence to the underlying ArrayList. This invariant allows us to 774 // share instances of lists between protocol buffers avoiding expensive 775 // memory allocations. Note, immutable is a strong guarantee here -- not 776 // just that the list cannot be modified via the reference but that the 777 // list can never be modified. 778 printer->Print(variables_, 779 "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); 780 781 printer->Print(variables_, 782 "private void ensure$capitalized_name$IsMutable() {\n" 783 " if (!$get_mutable_bit_builder$) {\n" 784 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" 785 " $set_mutable_bit_builder$;\n" 786 " }\n" 787 "}\n"); 788 789 // Note: We return an unmodifiable list because otherwise the caller 790 // could hold on to the returned list and modify it after the message 791 // has been built, thus mutating the message which is supposed to be 792 // immutable. 793 WriteFieldDocComment(printer, descriptor_); 794 printer->Print(variables_, 795 "$deprecation$public com.google.protobuf.ProtocolStringList\n" 796 " get$capitalized_name$List() {\n" 797 " return $name$_.getUnmodifiableView();\n" 798 "}\n"); 799 WriteFieldDocComment(printer, descriptor_); 800 printer->Print(variables_, 801 "$deprecation$public int get$capitalized_name$Count() {\n" 802 " return $name$_.size();\n" 803 "}\n"); 804 WriteFieldDocComment(printer, descriptor_); 805 printer->Print(variables_, 806 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 807 " return $name$_.get(index);\n" 808 "}\n"); 809 WriteFieldDocComment(printer, descriptor_); 810 printer->Print(variables_, 811 "$deprecation$public com.google.protobuf.ByteString\n" 812 " get$capitalized_name$Bytes(int index) {\n" 813 " return $name$_.getByteString(index);\n" 814 "}\n"); 815 WriteFieldDocComment(printer, descriptor_); 816 printer->Print(variables_, 817 "$deprecation$public Builder set$capitalized_name$(\n" 818 " int index, java.lang.String value) {\n" 819 "$null_check$" 820 " ensure$capitalized_name$IsMutable();\n" 821 " $name$_.set(index, value);\n" 822 " $on_changed$\n" 823 " return this;\n" 824 "}\n"); 825 WriteFieldDocComment(printer, descriptor_); 826 printer->Print(variables_, 827 "$deprecation$public Builder add$capitalized_name$(\n" 828 " java.lang.String value) {\n" 829 "$null_check$" 830 " ensure$capitalized_name$IsMutable();\n" 831 " $name$_.add(value);\n" 832 " $on_changed$\n" 833 " return this;\n" 834 "}\n"); 835 WriteFieldDocComment(printer, descriptor_); 836 printer->Print(variables_, 837 "$deprecation$public Builder addAll$capitalized_name$(\n" 838 " java.lang.Iterable<java.lang.String> values) {\n" 839 " ensure$capitalized_name$IsMutable();\n" 840 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" 841 " values, $name$_);\n" 842 " $on_changed$\n" 843 " return this;\n" 844 "}\n"); 845 WriteFieldDocComment(printer, descriptor_); 846 printer->Print(variables_, 847 "$deprecation$public Builder clear$capitalized_name$() {\n" 848 " $name$_ = $empty_list$;\n" 849 " $clear_mutable_bit_builder$;\n" 850 " $on_changed$\n" 851 " return this;\n" 852 "}\n"); 853 854 WriteFieldDocComment(printer, descriptor_); 855 printer->Print(variables_, 856 "$deprecation$public Builder add$capitalized_name$Bytes(\n" 857 " com.google.protobuf.ByteString value) {\n" 858 "$null_check$"); 859 if (CheckUtf8(descriptor_)) { 860 printer->Print(variables_, 861 " checkByteStringIsUtf8(value);\n"); 862 } 863 printer->Print(variables_, 864 " ensure$capitalized_name$IsMutable();\n" 865 " $name$_.add(value);\n" 866 " $on_changed$\n" 867 " return this;\n" 868 "}\n"); 869} 870 871void RepeatedImmutableStringFieldGenerator:: 872GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 873 // noop for primitives 874} 875 876void RepeatedImmutableStringFieldGenerator:: 877GenerateInitializationCode(io::Printer* printer) const { 878 printer->Print(variables_, "$name$_ = $empty_list$;\n"); 879} 880 881void RepeatedImmutableStringFieldGenerator:: 882GenerateBuilderClearCode(io::Printer* printer) const { 883 printer->Print(variables_, 884 "$name$_ = $empty_list$;\n" 885 "$clear_mutable_bit_builder$;\n"); 886} 887 888void RepeatedImmutableStringFieldGenerator:: 889GenerateMergingCode(io::Printer* printer) const { 890 // The code below does two optimizations: 891 // 1. If the other list is empty, there's nothing to do. This ensures we 892 // don't allocate a new array if we already have an immutable one. 893 // 2. If the other list is non-empty and our current list is empty, we can 894 // reuse the other list which is guaranteed to be immutable. 895 printer->Print(variables_, 896 "if (!other.$name$_.isEmpty()) {\n" 897 " if ($name$_.isEmpty()) {\n" 898 " $name$_ = other.$name$_;\n" 899 " $clear_mutable_bit_builder$;\n" 900 " } else {\n" 901 " ensure$capitalized_name$IsMutable();\n" 902 " $name$_.addAll(other.$name$_);\n" 903 " }\n" 904 " $on_changed$\n" 905 "}\n"); 906} 907 908void RepeatedImmutableStringFieldGenerator:: 909GenerateBuildingCode(io::Printer* printer) const { 910 // The code below ensures that the result has an immutable list. If our 911 // list is immutable, we can just reuse it. If not, we make it immutable. 912 913 printer->Print(variables_, 914 "if ($get_mutable_bit_builder$) {\n" 915 " $name$_ = $name$_.getUnmodifiableView();\n" 916 " $clear_mutable_bit_builder$;\n" 917 "}\n" 918 "result.$name$_ = $name$_;\n"); 919} 920 921void RepeatedImmutableStringFieldGenerator:: 922GenerateParsingCode(io::Printer* printer) const { 923 if (CheckUtf8(descriptor_)) { 924 printer->Print(variables_, 925 "String s = input.readStringRequireUtf8();\n"); 926 } else { 927 printer->Print(variables_, 928 "com.google.protobuf.ByteString bs = input.readBytes();\n"); 929 } 930 printer->Print(variables_, 931 "if (!$get_mutable_bit_parser$) {\n" 932 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" 933 " $set_mutable_bit_parser$;\n" 934 "}\n"); 935 if (CheckUtf8(descriptor_)) { 936 printer->Print(variables_, 937 "$name$_.add(s);\n"); 938 } else { 939 printer->Print(variables_, 940 "$name$_.add(bs);\n"); 941 } 942} 943 944void RepeatedImmutableStringFieldGenerator:: 945GenerateParsingCodeFromPacked(io::Printer* printer) const { 946 printer->Print(variables_, 947 "int length = input.readRawVarint32();\n" 948 "int limit = input.pushLimit(length);\n" 949 "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" 950 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" 951 " $set_mutable_bit_parser$;\n" 952 "}\n" 953 "while (input.getBytesUntilLimit() > 0) {\n"); 954 if (CheckUtf8(descriptor_)) { 955 printer->Print(variables_, 956 " String s = input.readStringRequireUtf8();\n"); 957 } else { 958 printer->Print(variables_, 959 " String s = input.readString();\n"); 960 } 961 printer->Print(variables_, 962 " $name$.add(s);\n"); 963 printer->Print(variables_, 964 "}\n" 965 "input.popLimit(limit);\n"); 966} 967 968void RepeatedImmutableStringFieldGenerator:: 969GenerateParsingDoneCode(io::Printer* printer) const { 970 printer->Print(variables_, 971 "if ($get_mutable_bit_parser$) {\n" 972 " $name$_ = $name$_.getUnmodifiableView();\n" 973 "}\n"); 974} 975 976void RepeatedImmutableStringFieldGenerator:: 977GenerateSerializationCode(io::Printer* printer) const { 978 if (descriptor_->options().packed()) { 979 printer->Print(variables_, 980 "if (get$capitalized_name$List().size() > 0) {\n" 981 " output.writeRawVarint32($tag$);\n" 982 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 983 "}\n" 984 "for (int i = 0; i < $name$_.size(); i++) {\n" 985 " output.write$capitalized_type$NoTag($name$_.get(i));\n" 986 "}\n"); 987 } else { 988 printer->Print(variables_, 989 "for (int i = 0; i < $name$_.size(); i++) {\n" 990 " output.writeBytes($number$, $name$_.getByteString(i));\n" 991 "}\n"); 992 } 993} 994 995void RepeatedImmutableStringFieldGenerator:: 996GenerateSerializedSizeCode(io::Printer* printer) const { 997 printer->Print(variables_, 998 "{\n" 999 " int dataSize = 0;\n"); 1000 printer->Indent(); 1001 1002 printer->Print(variables_, 1003 "for (int i = 0; i < $name$_.size(); i++) {\n" 1004 " dataSize += com.google.protobuf.CodedOutputStream\n" 1005 " .computeBytesSizeNoTag($name$_.getByteString(i));\n" 1006 "}\n"); 1007 1008 printer->Print( 1009 "size += dataSize;\n"); 1010 1011 if (descriptor_->options().packed()) { 1012 printer->Print(variables_, 1013 "if (!get$capitalized_name$List().isEmpty()) {\n" 1014 " size += $tag_size$;\n" 1015 " size += com.google.protobuf.CodedOutputStream\n" 1016 " .computeInt32SizeNoTag(dataSize);\n" 1017 "}\n"); 1018 } else { 1019 printer->Print(variables_, 1020 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 1021 } 1022 1023 // cache the data size for packed fields. 1024 if (descriptor_->options().packed()) { 1025 printer->Print(variables_, 1026 "$name$MemoizedSerializedSize = dataSize;\n"); 1027 } 1028 1029 printer->Outdent(); 1030 printer->Print("}\n"); 1031} 1032 1033void RepeatedImmutableStringFieldGenerator:: 1034GenerateEqualsCode(io::Printer* printer) const { 1035 printer->Print(variables_, 1036 "result = result && get$capitalized_name$List()\n" 1037 " .equals(other.get$capitalized_name$List());\n"); 1038} 1039 1040void RepeatedImmutableStringFieldGenerator:: 1041GenerateHashCode(io::Printer* printer) const { 1042 printer->Print(variables_, 1043 "if (get$capitalized_name$Count() > 0) {\n" 1044 " hash = (37 * hash) + $constant_name$;\n" 1045 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" 1046 "}\n"); 1047} 1048 1049string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { 1050 return "String"; 1051} 1052 1053} // namespace java 1054} // namespace compiler 1055} // namespace protobuf 1056} // namespace google 1057