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/logging.h> 40#include <google/protobuf/stubs/common.h> 41#include <google/protobuf/compiler/java/java_context.h> 42#include <google/protobuf/compiler/java/java_doc_comment.h> 43#include <google/protobuf/compiler/java/java_helpers.h> 44#include <google/protobuf/compiler/java/java_name_resolver.h> 45#include <google/protobuf/compiler/java/java_string_field_lite.h> 46#include <google/protobuf/io/printer.h> 47#include <google/protobuf/wire_format.h> 48#include <google/protobuf/stubs/strutil.h> 49 50namespace google { 51namespace protobuf { 52namespace compiler { 53namespace java { 54 55using internal::WireFormat; 56using internal::WireFormatLite; 57 58namespace { 59 60void SetPrimitiveVariables(const FieldDescriptor* descriptor, 61 int messageBitIndex, 62 int builderBitIndex, 63 const FieldGeneratorInfo* info, 64 ClassNameResolver* name_resolver, 65 map<string, string>* variables) { 66 SetCommonFieldVariables(descriptor, info, variables); 67 68 (*variables)["empty_list"] = 69 "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()"; 70 71 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); 72 (*variables)["default_init"] = 73 "= " + ImmutableDefaultValue(descriptor, name_resolver); 74 (*variables)["capitalized_type"] = "String"; 75 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 76 (*variables)["tag_size"] = SimpleItoa( 77 WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 78 (*variables)["null_check"] = 79 " if (value == null) {\n" 80 " throw new NullPointerException();\n" 81 " }\n"; 82 83 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 84 // by the proto compiler 85 (*variables)["deprecation"] = descriptor->options().deprecated() 86 ? "@java.lang.Deprecated " : ""; 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 92 // Note that these have a trailing ";". 93 (*variables)["set_has_field_bit_message"] = 94 GenerateSetBit(messageBitIndex) + ";"; 95 (*variables)["clear_has_field_bit_message"] = 96 GenerateClearBit(messageBitIndex) + ";"; 97 98 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); 99 } else { 100 (*variables)["set_has_field_bit_message"] = ""; 101 (*variables)["clear_has_field_bit_message"] = ""; 102 103 (*variables)["is_field_present_message"] = 104 "!" + (*variables)["name"] + "_.isEmpty()"; 105 } 106 107 // For repeated builders, the underlying list tracks mutability state. 108 (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; 109 110 (*variables)["get_has_field_bit_from_local"] = 111 GenerateGetBitFromLocal(builderBitIndex); 112 (*variables)["set_has_field_bit_to_local"] = 113 GenerateSetBitToLocal(messageBitIndex); 114} 115 116} // namespace 117 118// =================================================================== 119 120ImmutableStringFieldLiteGenerator:: 121ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, 122 int messageBitIndex, 123 int builderBitIndex, 124 Context* context) 125 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 126 builderBitIndex_(builderBitIndex), context_(context), 127 name_resolver_(context->GetNameResolver()) { 128 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 129 context->GetFieldGeneratorInfo(descriptor), 130 name_resolver_, &variables_); 131} 132 133ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {} 134 135int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { 136 return 1; 137} 138 139int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { 140 return 0; 141} 142 143// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes, 144// strings are not stored as java.lang.String in the Message because of two 145// issues: 146// 147// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded 148// strings, but rather fields that were raw bytes incorrectly marked 149// as strings in the proto file. This is common because in the proto1 150// syntax, string was the way to indicate bytes and C++ engineers can 151// easily make this mistake without affecting the C++ API. By converting to 152// strings immediately, some java code might corrupt these byte arrays as 153// it passes through a java server even if the field was never accessed by 154// application code. 155// 156// 2. There's a performance hit to converting between bytes and strings and 157// it many cases, the field is never even read by the application code. This 158// avoids unnecessary conversions in the common use cases. 159// 160// In the LITE_RUNTIME, we store strings as java.lang.String because we assume 161// that the users of this runtime are not subject to proto1 constraints and are 162// running code on devices that are user facing. That is, the developers are 163// properly incentivized to only fetch the data they need to read and wish to 164// reduce the number of allocations incurred when running on a user's device. 165 166// TODO(dweis): Consider dropping all of the *Bytes() methods. They really 167// shouldn't be necessary or used on devices. 168void ImmutableStringFieldLiteGenerator:: 169GenerateInterfaceMembers(io::Printer* printer) const { 170 if (SupportFieldPresence(descriptor_->file())) { 171 WriteFieldDocComment(printer, descriptor_); 172 printer->Print(variables_, 173 "$deprecation$boolean has$capitalized_name$();\n"); 174 } 175 WriteFieldDocComment(printer, descriptor_); 176 printer->Print(variables_, 177 "$deprecation$java.lang.String get$capitalized_name$();\n"); 178 WriteFieldDocComment(printer, descriptor_); 179 printer->Print(variables_, 180 "$deprecation$com.google.protobuf.ByteString\n" 181 " get$capitalized_name$Bytes();\n"); 182} 183 184void ImmutableStringFieldLiteGenerator:: 185GenerateMembers(io::Printer* printer) const { 186 printer->Print(variables_, 187 "private java.lang.String $name$_;\n"); 188 PrintExtraFieldInfo(variables_, printer); 189 190 if (SupportFieldPresence(descriptor_->file())) { 191 WriteFieldDocComment(printer, descriptor_); 192 printer->Print(variables_, 193 "$deprecation$public boolean has$capitalized_name$() {\n" 194 " return $get_has_field_bit_message$;\n" 195 "}\n"); 196 } 197 198 WriteFieldDocComment(printer, descriptor_); 199 printer->Print(variables_, 200 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 201 " return $name$_;\n" 202 "}\n"); 203 WriteFieldDocComment(printer, descriptor_); 204 printer->Print(variables_, 205 "$deprecation$public com.google.protobuf.ByteString\n" 206 " get$capitalized_name$Bytes() {\n" 207 " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n" 208 "}\n"); 209 210 WriteFieldDocComment(printer, descriptor_); 211 printer->Print(variables_, 212 "private void set$capitalized_name$(\n" 213 " java.lang.String value) {\n" 214 "$null_check$" 215 " $set_has_field_bit_message$\n" 216 " $name$_ = value;\n" 217 "}\n"); 218 WriteFieldDocComment(printer, descriptor_); 219 printer->Print(variables_, 220 "private void clear$capitalized_name$() {\n" 221 " $clear_has_field_bit_message$\n" 222 // The default value is not a simple literal so we want to avoid executing 223 // it multiple times. Instead, get the default out of the default instance. 224 " $name$_ = getDefaultInstance().get$capitalized_name$();\n" 225 "}\n"); 226 227 WriteFieldDocComment(printer, descriptor_); 228 printer->Print(variables_, 229 "private void set$capitalized_name$Bytes(\n" 230 " com.google.protobuf.ByteString value) {\n" 231 "$null_check$"); 232 if (CheckUtf8(descriptor_)) { 233 printer->Print(variables_, 234 " checkByteStringIsUtf8(value);\n"); 235 } 236 printer->Print(variables_, 237 " $set_has_field_bit_message$\n" 238 " $name$_ = value.toStringUtf8();\n" 239 "}\n"); 240} 241 242void ImmutableStringFieldLiteGenerator:: 243GenerateBuilderMembers(io::Printer* printer) const { 244 if (SupportFieldPresence(descriptor_->file())) { 245 WriteFieldDocComment(printer, descriptor_); 246 printer->Print(variables_, 247 "$deprecation$public boolean has$capitalized_name$() {\n" 248 " return instance.has$capitalized_name$();\n" 249 "}\n"); 250 } 251 252 WriteFieldDocComment(printer, descriptor_); 253 printer->Print(variables_, 254 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 255 " return instance.get$capitalized_name$();\n" 256 "}\n"); 257 258 WriteFieldDocComment(printer, descriptor_); 259 printer->Print(variables_, 260 "$deprecation$public com.google.protobuf.ByteString\n" 261 " get$capitalized_name$Bytes() {\n" 262 " return instance.get$capitalized_name$Bytes();\n" 263 "}\n"); 264 265 WriteFieldDocComment(printer, descriptor_); 266 printer->Print(variables_, 267 "$deprecation$public Builder set$capitalized_name$(\n" 268 " java.lang.String value) {\n" 269 " copyOnWrite();\n" 270 " instance.set$capitalized_name$(value);\n" 271 " return this;\n" 272 "}\n"); 273 WriteFieldDocComment(printer, descriptor_); 274 printer->Print(variables_, 275 "$deprecation$public Builder clear$capitalized_name$() {\n" 276 " copyOnWrite();\n" 277 " instance.clear$capitalized_name$();\n" 278 " return this;\n" 279 "}\n"); 280 281 WriteFieldDocComment(printer, descriptor_); 282 printer->Print(variables_, 283 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 284 " com.google.protobuf.ByteString value) {\n" 285 " copyOnWrite();\n" 286 " instance.set$capitalized_name$Bytes(value);\n" 287 " return this;\n" 288 "}\n"); 289} 290 291void ImmutableStringFieldLiteGenerator:: 292GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 293 // noop for strings 294} 295 296void ImmutableStringFieldLiteGenerator:: 297GenerateInitializationCode(io::Printer* printer) const { 298 printer->Print(variables_, "$name$_ = $default$;\n"); 299} 300 301void ImmutableStringFieldLiteGenerator:: 302GenerateVisitCode(io::Printer* printer) const { 303 if (SupportFieldPresence(descriptor_->file())) { 304 printer->Print(variables_, 305 "$name$_ = visitor.visitString(\n" 306 " has$capitalized_name$(), $name$_,\n" 307 " other.has$capitalized_name$(), other.$name$_);\n"); 308 } else { 309 printer->Print(variables_, 310 "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n" 311 " !other.$name$_.isEmpty(), other.$name$_);\n"); 312 } 313} 314 315void ImmutableStringFieldLiteGenerator:: 316GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { 317 // noop for scalars 318} 319 320void ImmutableStringFieldLiteGenerator:: 321GenerateParsingCode(io::Printer* printer) const { 322 if (CheckUtf8(descriptor_)) { 323 printer->Print(variables_, 324 "String s = input.readStringRequireUtf8();\n" 325 "$set_has_field_bit_message$\n" 326 "$name$_ = s;\n"); 327 } else { 328 // Lite runtime should attempt to reduce allocations by attempting to 329 // construct the string directly from the input stream buffer. This avoids 330 // spurious intermediary ByteString allocations, cutting overall allocations 331 // in half. 332 printer->Print(variables_, 333 "String s = input.readString();\n" 334 "$set_has_field_bit_message$\n" 335 "$name$_ = s;\n"); 336 } 337} 338 339void ImmutableStringFieldLiteGenerator:: 340GenerateParsingDoneCode(io::Printer* printer) const { 341 // noop for strings 342} 343 344void ImmutableStringFieldLiteGenerator:: 345GenerateSerializationCode(io::Printer* printer) const { 346 // Lite runtime should reduce allocations by serializing the string directly. 347 // This avoids spurious intermediary ByteString allocations, cutting overall 348 // allocations in half. 349 printer->Print(variables_, 350 "if ($is_field_present_message$) {\n" 351 " output.writeString($number$, get$capitalized_name$());\n" 352 "}\n"); 353} 354 355void ImmutableStringFieldLiteGenerator:: 356GenerateSerializedSizeCode(io::Printer* printer) const { 357 // Lite runtime should reduce allocations by computing on the string directly. 358 // This avoids spurious intermediary ByteString allocations, cutting overall 359 // allocations in half. 360 printer->Print(variables_, 361 "if ($is_field_present_message$) {\n" 362 " size += com.google.protobuf.CodedOutputStream\n" 363 " .computeStringSize($number$, get$capitalized_name$());\n" 364 "}\n"); 365} 366 367void ImmutableStringFieldLiteGenerator:: 368GenerateEqualsCode(io::Printer* printer) const { 369 printer->Print(variables_, 370 "result = result && get$capitalized_name$()\n" 371 " .equals(other.get$capitalized_name$());\n"); 372} 373 374void ImmutableStringFieldLiteGenerator:: 375GenerateHashCode(io::Printer* printer) const { 376 printer->Print(variables_, 377 "hash = (37 * hash) + $constant_name$;\n"); 378 printer->Print(variables_, 379 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); 380} 381 382string ImmutableStringFieldLiteGenerator::GetBoxedType() const { 383 return "java.lang.String"; 384} 385 386// =================================================================== 387 388ImmutableStringOneofFieldLiteGenerator:: 389ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, 390 int messageBitIndex, 391 int builderBitIndex, 392 Context* context) 393 : ImmutableStringFieldLiteGenerator( 394 descriptor, messageBitIndex, builderBitIndex, context) { 395 const OneofGeneratorInfo* info = 396 context->GetOneofGeneratorInfo(descriptor->containing_oneof()); 397 SetCommonOneofVariables(descriptor, info, &variables_); 398} 399 400ImmutableStringOneofFieldLiteGenerator:: 401~ImmutableStringOneofFieldLiteGenerator() {} 402 403void ImmutableStringOneofFieldLiteGenerator:: 404GenerateMembers(io::Printer* printer) const { 405 PrintExtraFieldInfo(variables_, printer); 406 407 if (SupportFieldPresence(descriptor_->file())) { 408 WriteFieldDocComment(printer, descriptor_); 409 printer->Print(variables_, 410 "$deprecation$public boolean has$capitalized_name$() {\n" 411 " return $has_oneof_case_message$;\n" 412 "}\n"); 413 } 414 415 WriteFieldDocComment(printer, descriptor_); 416 printer->Print(variables_, 417 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 418 " java.lang.String ref $default_init$;\n" 419 " if ($has_oneof_case_message$) {\n" 420 " ref = (java.lang.String) $oneof_name$_;\n" 421 " }\n" 422 " return ref;\n" 423 "}\n"); 424 WriteFieldDocComment(printer, descriptor_); 425 426 printer->Print(variables_, 427 "$deprecation$public com.google.protobuf.ByteString\n" 428 " get$capitalized_name$Bytes() {\n" 429 " java.lang.String ref $default_init$;\n" 430 " if ($has_oneof_case_message$) {\n" 431 " ref = (java.lang.String) $oneof_name$_;\n" 432 " }\n" 433 " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n" 434 "}\n"); 435 436 WriteFieldDocComment(printer, descriptor_); 437 printer->Print(variables_, 438 "private void set$capitalized_name$(\n" 439 " java.lang.String value) {\n" 440 "$null_check$" 441 " $set_oneof_case_message$;\n" 442 " $oneof_name$_ = value;\n" 443 "}\n"); 444 WriteFieldDocComment(printer, descriptor_); 445 printer->Print(variables_, 446 "private void clear$capitalized_name$() {\n" 447 " if ($has_oneof_case_message$) {\n" 448 " $clear_oneof_case_message$;\n" 449 " $oneof_name$_ = null;\n" 450 " }\n" 451 "}\n"); 452 453 WriteFieldDocComment(printer, descriptor_); 454 printer->Print(variables_, 455 "private void set$capitalized_name$Bytes(\n" 456 " com.google.protobuf.ByteString value) {\n" 457 "$null_check$"); 458 if (CheckUtf8(descriptor_)) { 459 printer->Print(variables_, 460 " checkByteStringIsUtf8(value);\n"); 461 } 462 printer->Print(variables_, 463 " $set_oneof_case_message$;\n" 464 " $oneof_name$_ = value.toStringUtf8();\n" 465 "}\n"); 466} 467 468void ImmutableStringOneofFieldLiteGenerator:: 469GenerateBuilderMembers(io::Printer* printer) const { 470 if (SupportFieldPresence(descriptor_->file())) { 471 WriteFieldDocComment(printer, descriptor_); 472 printer->Print(variables_, 473 "$deprecation$public boolean has$capitalized_name$() {\n" 474 " return instance.has$capitalized_name$();\n" 475 "}\n"); 476 } 477 478 WriteFieldDocComment(printer, descriptor_); 479 printer->Print(variables_, 480 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 481 " return instance.get$capitalized_name$();\n" 482 "}\n"); 483 484 WriteFieldDocComment(printer, descriptor_); 485 printer->Print(variables_, 486 "$deprecation$public com.google.protobuf.ByteString\n" 487 " get$capitalized_name$Bytes() {\n" 488 " return instance.get$capitalized_name$Bytes();\n" 489 "}\n"); 490 491 WriteFieldDocComment(printer, descriptor_); 492 printer->Print(variables_, 493 "$deprecation$public Builder set$capitalized_name$(\n" 494 " java.lang.String value) {\n" 495 " copyOnWrite();\n" 496 " instance.set$capitalized_name$(value);\n" 497 " return this;\n" 498 "}\n"); 499 WriteFieldDocComment(printer, descriptor_); 500 printer->Print(variables_, 501 "$deprecation$public Builder clear$capitalized_name$() {\n" 502 " copyOnWrite();\n" 503 " instance.clear$capitalized_name$();\n" 504 " return this;\n" 505 "}\n"); 506 507 WriteFieldDocComment(printer, descriptor_); 508 printer->Print(variables_, 509 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 510 " com.google.protobuf.ByteString value) {\n" 511 " copyOnWrite();\n" 512 " instance.set$capitalized_name$Bytes(value);\n" 513 " return this;\n" 514 "}\n"); 515} 516 517void ImmutableStringOneofFieldLiteGenerator:: 518GenerateVisitCode(io::Printer* printer) const { 519 printer->Print(variables_, 520 "$oneof_name$_ = visitor.visitOneofString(\n" 521 " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); 522} 523 524void ImmutableStringOneofFieldLiteGenerator:: 525GenerateParsingCode(io::Printer* printer) const { 526 if (CheckUtf8(descriptor_)) { 527 printer->Print(variables_, 528 "String s = input.readStringRequireUtf8();\n" 529 "$set_oneof_case_message$;\n" 530 "$oneof_name$_ = s;\n"); 531 } else { 532 // Lite runtime should attempt to reduce allocations by attempting to 533 // construct the string directly from the input stream buffer. This avoids 534 // spurious intermediary ByteString allocations, cutting overall allocations 535 // in half. 536 printer->Print(variables_, 537 "String s = input.readString();\n" 538 "$set_oneof_case_message$;\n" 539 "$oneof_name$_ = s;\n"); 540 } 541} 542 543void ImmutableStringOneofFieldLiteGenerator:: 544GenerateSerializationCode(io::Printer* printer) const { 545 // Lite runtime should reduce allocations by serializing the string directly. 546 // This avoids spurious intermediary ByteString allocations, cutting overall 547 // allocations in half. 548 printer->Print(variables_, 549 "if ($has_oneof_case_message$) {\n" 550 " output.writeString($number$, get$capitalized_name$());\n" 551 "}\n"); 552} 553 554void ImmutableStringOneofFieldLiteGenerator:: 555GenerateSerializedSizeCode(io::Printer* printer) const { 556 // Lite runtime should reduce allocations by computing on the string directly. 557 // This avoids spurious intermediary ByteString allocations, cutting overall 558 // allocations in half. 559 printer->Print(variables_, 560 "if ($has_oneof_case_message$) {\n" 561 " size += com.google.protobuf.CodedOutputStream\n" 562 " .computeStringSize($number$, get$capitalized_name$());\n" 563 "}\n"); 564} 565 566// =================================================================== 567 568RepeatedImmutableStringFieldLiteGenerator:: 569RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, 570 int messageBitIndex, 571 int builderBitIndex, 572 Context* context) 573 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 574 builderBitIndex_(builderBitIndex), context_(context), 575 name_resolver_(context->GetNameResolver()) { 576 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 577 context->GetFieldGeneratorInfo(descriptor), 578 name_resolver_, &variables_); 579} 580 581RepeatedImmutableStringFieldLiteGenerator:: 582~RepeatedImmutableStringFieldLiteGenerator() {} 583 584int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { 585 return 0; 586} 587 588int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { 589 return 0; 590} 591 592void RepeatedImmutableStringFieldLiteGenerator:: 593GenerateInterfaceMembers(io::Printer* printer) const { 594 WriteFieldDocComment(printer, descriptor_); 595 printer->Print(variables_, 596 "$deprecation$java.util.List<String>\n" 597 " get$capitalized_name$List();\n"); 598 WriteFieldDocComment(printer, descriptor_); 599 printer->Print(variables_, 600 "$deprecation$int get$capitalized_name$Count();\n"); 601 WriteFieldDocComment(printer, descriptor_); 602 printer->Print(variables_, 603 "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); 604 WriteFieldDocComment(printer, descriptor_); 605 printer->Print(variables_, 606 "$deprecation$com.google.protobuf.ByteString\n" 607 " get$capitalized_name$Bytes(int index);\n"); 608} 609 610 611void RepeatedImmutableStringFieldLiteGenerator:: 612GenerateMembers(io::Printer* printer) const { 613 printer->Print(variables_, 614 "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n"); 615 PrintExtraFieldInfo(variables_, printer); 616 WriteFieldDocComment(printer, descriptor_); 617 printer->Print(variables_, 618 "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n" 619 " return $name$_;\n" // note: unmodifiable list 620 "}\n"); 621 WriteFieldDocComment(printer, descriptor_); 622 printer->Print(variables_, 623 "$deprecation$public int get$capitalized_name$Count() {\n" 624 " return $name$_.size();\n" 625 "}\n"); 626 WriteFieldDocComment(printer, descriptor_); 627 printer->Print(variables_, 628 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 629 " return $name$_.get(index);\n" 630 "}\n"); 631 WriteFieldDocComment(printer, descriptor_); 632 printer->Print(variables_, 633 "$deprecation$public com.google.protobuf.ByteString\n" 634 " get$capitalized_name$Bytes(int index) {\n" 635 " return com.google.protobuf.ByteString.copyFromUtf8(\n" 636 " $name$_.get(index));\n" 637 "}\n"); 638 639 printer->Print(variables_, 640 "private void ensure$capitalized_name$IsMutable() {\n" 641 " if (!$is_mutable$) {\n" 642 " $name$_ =\n" 643 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" 644 " }\n" 645 "}\n"); 646 647 WriteFieldDocComment(printer, descriptor_); 648 printer->Print(variables_, 649 "private void set$capitalized_name$(\n" 650 " int index, java.lang.String value) {\n" 651 "$null_check$" 652 " ensure$capitalized_name$IsMutable();\n" 653 " $name$_.set(index, value);\n" 654 "}\n"); 655 WriteFieldDocComment(printer, descriptor_); 656 printer->Print(variables_, 657 "private void add$capitalized_name$(\n" 658 " java.lang.String value) {\n" 659 "$null_check$" 660 " ensure$capitalized_name$IsMutable();\n" 661 " $name$_.add(value);\n" 662 "}\n"); 663 WriteFieldDocComment(printer, descriptor_); 664 printer->Print(variables_, 665 "private void addAll$capitalized_name$(\n" 666 " java.lang.Iterable<java.lang.String> values) {\n" 667 " ensure$capitalized_name$IsMutable();\n" 668 " com.google.protobuf.AbstractMessageLite.addAll(\n" 669 " values, $name$_);\n" 670 "}\n"); 671 WriteFieldDocComment(printer, descriptor_); 672 printer->Print(variables_, 673 "private void clear$capitalized_name$() {\n" 674 " $name$_ = $empty_list$;\n" 675 "}\n"); 676 677 WriteFieldDocComment(printer, descriptor_); 678 printer->Print(variables_, 679 "private void add$capitalized_name$Bytes(\n" 680 " com.google.protobuf.ByteString value) {\n" 681 "$null_check$"); 682 if (CheckUtf8(descriptor_)) { 683 printer->Print(variables_, 684 " checkByteStringIsUtf8(value);\n"); 685 } 686 printer->Print(variables_, 687 " ensure$capitalized_name$IsMutable();\n" 688 " $name$_.add(value.toStringUtf8());\n" 689 "}\n"); 690} 691 692void RepeatedImmutableStringFieldLiteGenerator:: 693GenerateBuilderMembers(io::Printer* printer) const { 694 WriteFieldDocComment(printer, descriptor_); 695 printer->Print(variables_, 696 "$deprecation$public java.util.List<String>\n" 697 " get$capitalized_name$List() {\n" 698 " return java.util.Collections.unmodifiableList(\n" 699 " instance.get$capitalized_name$List());\n" 700 "}\n"); 701 WriteFieldDocComment(printer, descriptor_); 702 printer->Print(variables_, 703 "$deprecation$public int get$capitalized_name$Count() {\n" 704 " return instance.get$capitalized_name$Count();\n" 705 "}\n"); 706 WriteFieldDocComment(printer, descriptor_); 707 printer->Print(variables_, 708 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 709 " return instance.get$capitalized_name$(index);\n" 710 "}\n"); 711 WriteFieldDocComment(printer, descriptor_); 712 printer->Print(variables_, 713 "$deprecation$public com.google.protobuf.ByteString\n" 714 " get$capitalized_name$Bytes(int index) {\n" 715 " return instance.get$capitalized_name$Bytes(index);\n" 716 "}\n"); 717 WriteFieldDocComment(printer, descriptor_); 718 printer->Print(variables_, 719 "$deprecation$public Builder set$capitalized_name$(\n" 720 " int index, java.lang.String value) {\n" 721 " copyOnWrite();\n" 722 " instance.set$capitalized_name$(index, value);\n" 723 " return this;\n" 724 "}\n"); 725 WriteFieldDocComment(printer, descriptor_); 726 printer->Print(variables_, 727 "$deprecation$public Builder add$capitalized_name$(\n" 728 " java.lang.String value) {\n" 729 " copyOnWrite();\n" 730 " instance.add$capitalized_name$(value);\n" 731 " return this;\n" 732 "}\n"); 733 WriteFieldDocComment(printer, descriptor_); 734 printer->Print(variables_, 735 "$deprecation$public Builder addAll$capitalized_name$(\n" 736 " java.lang.Iterable<java.lang.String> values) {\n" 737 " copyOnWrite();\n" 738 " instance.addAll$capitalized_name$(values);\n" 739 " return this;\n" 740 "}\n"); 741 WriteFieldDocComment(printer, descriptor_); 742 printer->Print(variables_, 743 "$deprecation$public Builder clear$capitalized_name$() {\n" 744 " copyOnWrite();\n" 745 " instance.clear$capitalized_name$();\n" 746 " return this;\n" 747 "}\n"); 748 749 WriteFieldDocComment(printer, descriptor_); 750 printer->Print(variables_, 751 "$deprecation$public Builder add$capitalized_name$Bytes(\n" 752 " com.google.protobuf.ByteString value) {\n" 753 " copyOnWrite();\n" 754 " instance.add$capitalized_name$Bytes(value);\n" 755 " return this;\n" 756 "}\n"); 757} 758 759void RepeatedImmutableStringFieldLiteGenerator:: 760GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 761 // noop for strings 762} 763 764void RepeatedImmutableStringFieldLiteGenerator:: 765GenerateInitializationCode(io::Printer* printer) const { 766 printer->Print(variables_, "$name$_ = $empty_list$;\n"); 767} 768 769void RepeatedImmutableStringFieldLiteGenerator:: 770GenerateVisitCode(io::Printer* printer) const { 771 printer->Print(variables_, 772 "$name$_= visitor.visitList($name$_, other.$name$_);\n"); 773} 774 775void RepeatedImmutableStringFieldLiteGenerator:: 776GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { 777 printer->Print(variables_, 778 "$name$_.makeImmutable();\n"); 779} 780 781void RepeatedImmutableStringFieldLiteGenerator:: 782GenerateParsingCode(io::Printer* printer) const { 783 if (CheckUtf8(descriptor_)) { 784 printer->Print(variables_, 785 "String s = input.readStringRequireUtf8();\n"); 786 } else { 787 // Lite runtime should attempt to reduce allocations by attempting to 788 // construct the string directly from the input stream buffer. This avoids 789 // spurious intermediary ByteString allocations, cutting overall allocations 790 // in half. 791 printer->Print(variables_, 792 "String s = input.readString();\n"); 793 } 794 printer->Print(variables_, 795 "if (!$is_mutable$) {\n" 796 " $name$_ =\n" 797 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" 798 "}\n"); 799 printer->Print(variables_, 800 "$name$_.add(s);\n"); 801} 802 803void RepeatedImmutableStringFieldLiteGenerator:: 804GenerateParsingDoneCode(io::Printer* printer) const { 805 printer->Print(variables_, 806 "if ($is_mutable$) {\n" 807 " $name$_.makeImmutable();\n" 808 "}\n"); 809} 810 811void RepeatedImmutableStringFieldLiteGenerator:: 812GenerateSerializationCode(io::Printer* printer) const { 813 // Lite runtime should reduce allocations by serializing the string directly. 814 // This avoids spurious intermediary ByteString allocations, cutting overall 815 // allocations in half. 816 printer->Print(variables_, 817 "for (int i = 0; i < $name$_.size(); i++) {\n" 818 " output.writeString($number$, $name$_.get(i));\n" 819 "}\n"); 820} 821 822void RepeatedImmutableStringFieldLiteGenerator:: 823GenerateSerializedSizeCode(io::Printer* printer) const { 824 // Lite runtime should reduce allocations by computing on the string directly. 825 // This avoids spurious intermediary ByteString allocations, cutting overall 826 // allocations in half. 827 printer->Print(variables_, 828 "{\n" 829 " int dataSize = 0;\n"); 830 printer->Indent(); 831 832 printer->Print(variables_, 833 "for (int i = 0; i < $name$_.size(); i++) {\n" 834 " dataSize += com.google.protobuf.CodedOutputStream\n" 835 " .computeStringSizeNoTag($name$_.get(i));\n" 836 "}\n"); 837 838 printer->Print( 839 "size += dataSize;\n"); 840 841 842 printer->Print(variables_, 843 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 844 845 printer->Outdent(); 846 printer->Print("}\n"); 847} 848 849void RepeatedImmutableStringFieldLiteGenerator:: 850GenerateEqualsCode(io::Printer* printer) const { 851 printer->Print(variables_, 852 "result = result && get$capitalized_name$List()\n" 853 " .equals(other.get$capitalized_name$List());\n"); 854} 855 856void RepeatedImmutableStringFieldLiteGenerator:: 857GenerateHashCode(io::Printer* printer) const { 858 printer->Print(variables_, 859 "if (get$capitalized_name$Count() > 0) {\n" 860 " hash = (37 * hash) + $constant_name$;\n" 861 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" 862 "}\n"); 863} 864 865string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const { 866 return "String"; 867} 868 869} // namespace java 870} // namespace compiler 871} // namespace protobuf 872} // namespace google 873