1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// 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/compiler/java/java_string_field.h> 40#include <google/protobuf/compiler/java/java_doc_comment.h> 41#include <google/protobuf/stubs/common.h> 42#include <google/protobuf/compiler/java/java_helpers.h> 43#include <google/protobuf/io/printer.h> 44#include <google/protobuf/wire_format.h> 45#include <google/protobuf/stubs/strutil.h> 46 47namespace google { 48namespace protobuf { 49namespace compiler { 50namespace java { 51 52using internal::WireFormat; 53using internal::WireFormatLite; 54 55namespace { 56 57void SetPrimitiveVariables(const FieldDescriptor* descriptor, 58 int messageBitIndex, 59 int builderBitIndex, 60 map<string, string>* variables) { 61 (*variables)["name"] = 62 UnderscoresToCamelCase(descriptor); 63 (*variables)["capitalized_name"] = 64 UnderscoresToCapitalizedCamelCase(descriptor); 65 (*variables)["constant_name"] = FieldConstantName(descriptor); 66 (*variables)["number"] = SimpleItoa(descriptor->number()); 67 (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; 68 69 (*variables)["default"] = DefaultValue(descriptor); 70 (*variables)["default_init"] = ("= " + DefaultValue(descriptor)); 71 (*variables)["capitalized_type"] = "String"; 72 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 73 (*variables)["tag_size"] = SimpleItoa( 74 WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 75 (*variables)["null_check"] = 76 " if (value == null) {\n" 77 " throw new NullPointerException();\n" 78 " }\n"; 79 80 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 81 // by the proto compiler 82 (*variables)["deprecation"] = descriptor->options().deprecated() 83 ? "@java.lang.Deprecated " : ""; 84 (*variables)["on_changed"] = 85 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; 86 87 // For singular messages and builders, one bit is used for the hasField bit. 88 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 89 (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); 90 91 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 92 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); 93 (*variables)["clear_has_field_bit_builder"] = 94 GenerateClearBit(builderBitIndex); 95 96 // For repated builders, one bit is used for whether the array is immutable. 97 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 98 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 99 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 100 101 // For repeated fields, one bit is used for whether the array is immutable 102 // in the parsing constructor. 103 (*variables)["get_mutable_bit_parser"] = 104 GenerateGetBitMutableLocal(builderBitIndex); 105 (*variables)["set_mutable_bit_parser"] = 106 GenerateSetBitMutableLocal(builderBitIndex); 107 108 (*variables)["get_has_field_bit_from_local"] = 109 GenerateGetBitFromLocal(builderBitIndex); 110 (*variables)["set_has_field_bit_to_local"] = 111 GenerateSetBitToLocal(messageBitIndex); 112} 113 114} // namespace 115 116// =================================================================== 117 118StringFieldGenerator:: 119StringFieldGenerator(const FieldDescriptor* descriptor, 120 int messageBitIndex, 121 int builderBitIndex) 122 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 123 builderBitIndex_(builderBitIndex) { 124 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 125 &variables_); 126} 127 128StringFieldGenerator::~StringFieldGenerator() {} 129 130int StringFieldGenerator::GetNumBitsForMessage() const { 131 return 1; 132} 133 134int StringFieldGenerator::GetNumBitsForBuilder() const { 135 return 1; 136} 137 138// A note about how strings are handled. This code used to just store a String 139// in the Message. This had two issues: 140// 141// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded 142// strings, but rather fields that were raw bytes incorrectly marked 143// as strings in the proto file. This is common because in the proto1 144// syntax, string was the way to indicate bytes and C++ engineers can 145// easily make this mistake without affecting the C++ API. By converting to 146// strings immediately, some java code might corrupt these byte arrays as 147// it passes through a java server even if the field was never accessed by 148// application code. 149// 150// 2. There's a performance hit to converting between bytes and strings and 151// it many cases, the field is never even read by the application code. This 152// avoids unnecessary conversions in the common use cases. 153// 154// So now, the field for String is maintained as an Object reference which can 155// either store a String or a ByteString. The code uses an instanceof check 156// to see which one it has and converts to the other one if needed. It remembers 157// the last value requested (in a thread safe manner) as this is most likely 158// the one needed next. The thread safety is such that if two threads both 159// convert the field because the changes made by each thread were not visible to 160// the other, they may cause a conversion to happen more times than would 161// otherwise be necessary. This was deemed better than adding synchronization 162// overhead. It will not cause any corruption issues or affect the behavior of 163// the API. The instanceof check is also highly optimized in the JVM and we 164// decided it was better to reduce the memory overhead by not having two 165// separate fields but rather use dynamic type checking. 166// 167// For single fields, the logic for this is done inside the generated code. For 168// repeated fields, the logic is done in LazyStringArrayList and 169// UnmodifiableLazyStringList. 170void StringFieldGenerator:: 171GenerateInterfaceMembers(io::Printer* printer) const { 172 WriteFieldDocComment(printer, descriptor_); 173 printer->Print(variables_, 174 "$deprecation$boolean has$capitalized_name$();\n"); 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 StringFieldGenerator:: 185GenerateMembers(io::Printer* printer) const { 186 printer->Print(variables_, 187 "private java.lang.Object $name$_;\n"); 188 WriteFieldDocComment(printer, descriptor_); 189 printer->Print(variables_, 190 "$deprecation$public boolean has$capitalized_name$() {\n" 191 " return $get_has_field_bit_message$;\n" 192 "}\n"); 193 194 WriteFieldDocComment(printer, descriptor_); 195 printer->Print(variables_, 196 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 197 " java.lang.Object ref = $name$_;\n" 198 " if (ref instanceof java.lang.String) {\n" 199 " return (java.lang.String) ref;\n" 200 " } else {\n" 201 " com.google.protobuf.ByteString bs = \n" 202 " (com.google.protobuf.ByteString) ref;\n" 203 " java.lang.String s = bs.toStringUtf8();\n" 204 " if (bs.isValidUtf8()) {\n" 205 " $name$_ = s;\n" 206 " }\n" 207 " return s;\n" 208 " }\n" 209 "}\n"); 210 WriteFieldDocComment(printer, descriptor_); 211 printer->Print(variables_, 212 "$deprecation$public com.google.protobuf.ByteString\n" 213 " get$capitalized_name$Bytes() {\n" 214 " java.lang.Object ref = $name$_;\n" 215 " if (ref instanceof java.lang.String) {\n" 216 " com.google.protobuf.ByteString b = \n" 217 " com.google.protobuf.ByteString.copyFromUtf8(\n" 218 " (java.lang.String) ref);\n" 219 " $name$_ = b;\n" 220 " return b;\n" 221 " } else {\n" 222 " return (com.google.protobuf.ByteString) ref;\n" 223 " }\n" 224 "}\n"); 225} 226 227void StringFieldGenerator:: 228GenerateBuilderMembers(io::Printer* printer) const { 229 printer->Print(variables_, 230 "private java.lang.Object $name$_ $default_init$;\n"); 231 WriteFieldDocComment(printer, descriptor_); 232 printer->Print(variables_, 233 "$deprecation$public boolean has$capitalized_name$() {\n" 234 " return $get_has_field_bit_builder$;\n" 235 "}\n"); 236 237 WriteFieldDocComment(printer, descriptor_); 238 printer->Print(variables_, 239 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 240 " java.lang.Object ref = $name$_;\n" 241 " if (!(ref instanceof java.lang.String)) {\n" 242 " java.lang.String s = ((com.google.protobuf.ByteString) ref)\n" 243 " .toStringUtf8();\n" 244 " $name$_ = s;\n" 245 " return s;\n" 246 " } else {\n" 247 " return (java.lang.String) ref;\n" 248 " }\n" 249 "}\n"); 250 251 WriteFieldDocComment(printer, descriptor_); 252 printer->Print(variables_, 253 "$deprecation$public com.google.protobuf.ByteString\n" 254 " get$capitalized_name$Bytes() {\n" 255 " java.lang.Object ref = $name$_;\n" 256 " if (ref instanceof String) {\n" 257 " com.google.protobuf.ByteString b = \n" 258 " com.google.protobuf.ByteString.copyFromUtf8(\n" 259 " (java.lang.String) ref);\n" 260 " $name$_ = b;\n" 261 " return b;\n" 262 " } else {\n" 263 " return (com.google.protobuf.ByteString) ref;\n" 264 " }\n" 265 "}\n"); 266 267 WriteFieldDocComment(printer, descriptor_); 268 printer->Print(variables_, 269 "$deprecation$public Builder set$capitalized_name$(\n" 270 " java.lang.String value) {\n" 271 "$null_check$" 272 " $set_has_field_bit_builder$;\n" 273 " $name$_ = value;\n" 274 " $on_changed$\n" 275 " return this;\n" 276 "}\n"); 277 WriteFieldDocComment(printer, descriptor_); 278 printer->Print(variables_, 279 "$deprecation$public Builder clear$capitalized_name$() {\n" 280 " $clear_has_field_bit_builder$;\n"); 281 // The default value is not a simple literal so we want to avoid executing 282 // it multiple times. Instead, get the default out of the default instance. 283 printer->Print(variables_, 284 " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); 285 printer->Print(variables_, 286 " $on_changed$\n" 287 " return this;\n" 288 "}\n"); 289 290 WriteFieldDocComment(printer, descriptor_); 291 printer->Print(variables_, 292 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 293 " com.google.protobuf.ByteString value) {\n" 294 "$null_check$" 295 " $set_has_field_bit_builder$;\n" 296 " $name$_ = value;\n" 297 " $on_changed$\n" 298 " return this;\n" 299 "}\n"); 300} 301 302void StringFieldGenerator:: 303GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 304 // noop for primitives 305} 306 307void StringFieldGenerator:: 308GenerateInitializationCode(io::Printer* printer) const { 309 printer->Print(variables_, "$name$_ = $default$;\n"); 310} 311 312void StringFieldGenerator:: 313GenerateBuilderClearCode(io::Printer* printer) const { 314 printer->Print(variables_, 315 "$name$_ = $default$;\n" 316 "$clear_has_field_bit_builder$;\n"); 317} 318 319void StringFieldGenerator:: 320GenerateMergingCode(io::Printer* printer) const { 321 // Allow a slight breach of abstraction here in order to avoid forcing 322 // all string fields to Strings when copying fields from a Message. 323 printer->Print(variables_, 324 "if (other.has$capitalized_name$()) {\n" 325 " $set_has_field_bit_builder$;\n" 326 " $name$_ = other.$name$_;\n" 327 " $on_changed$\n" 328 "}\n"); 329} 330 331void StringFieldGenerator:: 332GenerateBuildingCode(io::Printer* printer) const { 333 printer->Print(variables_, 334 "if ($get_has_field_bit_from_local$) {\n" 335 " $set_has_field_bit_to_local$;\n" 336 "}\n" 337 "result.$name$_ = $name$_;\n"); 338} 339 340void StringFieldGenerator:: 341GenerateParsingCode(io::Printer* printer) const { 342 printer->Print(variables_, 343 "$set_has_field_bit_message$;\n" 344 "$name$_ = input.readBytes();\n"); 345} 346 347void StringFieldGenerator:: 348GenerateParsingDoneCode(io::Printer* printer) const { 349 // noop for strings. 350} 351 352void StringFieldGenerator:: 353GenerateSerializationCode(io::Printer* printer) const { 354 printer->Print(variables_, 355 "if ($get_has_field_bit_message$) {\n" 356 " output.writeBytes($number$, get$capitalized_name$Bytes());\n" 357 "}\n"); 358} 359 360void StringFieldGenerator:: 361GenerateSerializedSizeCode(io::Printer* printer) const { 362 printer->Print(variables_, 363 "if ($get_has_field_bit_message$) {\n" 364 " size += com.google.protobuf.CodedOutputStream\n" 365 " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" 366 "}\n"); 367} 368 369void StringFieldGenerator:: 370GenerateEqualsCode(io::Printer* printer) const { 371 printer->Print(variables_, 372 "result = result && get$capitalized_name$()\n" 373 " .equals(other.get$capitalized_name$());\n"); 374} 375 376void StringFieldGenerator:: 377GenerateHashCode(io::Printer* printer) const { 378 printer->Print(variables_, 379 "hash = (37 * hash) + $constant_name$;\n"); 380 printer->Print(variables_, 381 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); 382} 383 384string StringFieldGenerator::GetBoxedType() const { 385 return "java.lang.String"; 386} 387 388 389// =================================================================== 390 391RepeatedStringFieldGenerator:: 392RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, 393 int messageBitIndex, 394 int builderBitIndex) 395 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 396 builderBitIndex_(builderBitIndex) { 397 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 398 &variables_); 399} 400 401RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} 402 403int RepeatedStringFieldGenerator::GetNumBitsForMessage() const { 404 return 0; 405} 406 407int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const { 408 return 1; 409} 410 411void RepeatedStringFieldGenerator:: 412GenerateInterfaceMembers(io::Printer* printer) const { 413 WriteFieldDocComment(printer, descriptor_); 414 printer->Print(variables_, 415 "$deprecation$java.util.List<java.lang.String>\n" 416 "get$capitalized_name$List();\n"); 417 WriteFieldDocComment(printer, descriptor_); 418 printer->Print(variables_, 419 "$deprecation$int get$capitalized_name$Count();\n"); 420 WriteFieldDocComment(printer, descriptor_); 421 printer->Print(variables_, 422 "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); 423 WriteFieldDocComment(printer, descriptor_); 424 printer->Print(variables_, 425 "$deprecation$com.google.protobuf.ByteString\n" 426 " get$capitalized_name$Bytes(int index);\n"); 427} 428 429 430void RepeatedStringFieldGenerator:: 431GenerateMembers(io::Printer* printer) const { 432 printer->Print(variables_, 433 "private com.google.protobuf.LazyStringList $name$_;\n"); 434 WriteFieldDocComment(printer, descriptor_); 435 printer->Print(variables_, 436 "$deprecation$public java.util.List<java.lang.String>\n" 437 " get$capitalized_name$List() {\n" 438 " return $name$_;\n" // note: unmodifiable list 439 "}\n"); 440 WriteFieldDocComment(printer, descriptor_); 441 printer->Print(variables_, 442 "$deprecation$public int get$capitalized_name$Count() {\n" 443 " return $name$_.size();\n" 444 "}\n"); 445 WriteFieldDocComment(printer, descriptor_); 446 printer->Print(variables_, 447 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 448 " return $name$_.get(index);\n" 449 "}\n"); 450 WriteFieldDocComment(printer, descriptor_); 451 printer->Print(variables_, 452 "$deprecation$public com.google.protobuf.ByteString\n" 453 " get$capitalized_name$Bytes(int index) {\n" 454 " return $name$_.getByteString(index);\n" 455 "}\n"); 456 457 if (descriptor_->options().packed() && 458 HasGeneratedMethods(descriptor_->containing_type())) { 459 printer->Print(variables_, 460 "private int $name$MemoizedSerializedSize = -1;\n"); 461 } 462} 463 464void RepeatedStringFieldGenerator:: 465GenerateBuilderMembers(io::Printer* printer) const { 466 // One field is the list and the bit field keeps track of whether the 467 // list is immutable. If it's immutable, the invariant is that it must 468 // either an instance of Collections.emptyList() or it's an ArrayList 469 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 470 // a refererence to the underlying ArrayList. This invariant allows us to 471 // share instances of lists between protocol buffers avoiding expensive 472 // memory allocations. Note, immutable is a strong guarantee here -- not 473 // just that the list cannot be modified via the reference but that the 474 // list can never be modified. 475 printer->Print(variables_, 476 "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); 477 478 printer->Print(variables_, 479 "private void ensure$capitalized_name$IsMutable() {\n" 480 " if (!$get_mutable_bit_builder$) {\n" 481 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" 482 " $set_mutable_bit_builder$;\n" 483 " }\n" 484 "}\n"); 485 486 // Note: We return an unmodifiable list because otherwise the caller 487 // could hold on to the returned list and modify it after the message 488 // has been built, thus mutating the message which is supposed to be 489 // immutable. 490 WriteFieldDocComment(printer, descriptor_); 491 printer->Print(variables_, 492 "$deprecation$public java.util.List<java.lang.String>\n" 493 " get$capitalized_name$List() {\n" 494 " return java.util.Collections.unmodifiableList($name$_);\n" 495 "}\n"); 496 WriteFieldDocComment(printer, descriptor_); 497 printer->Print(variables_, 498 "$deprecation$public int get$capitalized_name$Count() {\n" 499 " return $name$_.size();\n" 500 "}\n"); 501 WriteFieldDocComment(printer, descriptor_); 502 printer->Print(variables_, 503 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 504 " return $name$_.get(index);\n" 505 "}\n"); 506 WriteFieldDocComment(printer, descriptor_); 507 printer->Print(variables_, 508 "$deprecation$public com.google.protobuf.ByteString\n" 509 " get$capitalized_name$Bytes(int index) {\n" 510 " return $name$_.getByteString(index);\n" 511 "}\n"); 512 WriteFieldDocComment(printer, descriptor_); 513 printer->Print(variables_, 514 "$deprecation$public Builder set$capitalized_name$(\n" 515 " int index, java.lang.String value) {\n" 516 "$null_check$" 517 " ensure$capitalized_name$IsMutable();\n" 518 " $name$_.set(index, value);\n" 519 " $on_changed$\n" 520 " return this;\n" 521 "}\n"); 522 WriteFieldDocComment(printer, descriptor_); 523 printer->Print(variables_, 524 "$deprecation$public Builder add$capitalized_name$(\n" 525 " java.lang.String value) {\n" 526 "$null_check$" 527 " ensure$capitalized_name$IsMutable();\n" 528 " $name$_.add(value);\n" 529 " $on_changed$\n" 530 " return this;\n" 531 "}\n"); 532 WriteFieldDocComment(printer, descriptor_); 533 printer->Print(variables_, 534 "$deprecation$public Builder addAll$capitalized_name$(\n" 535 " java.lang.Iterable<java.lang.String> values) {\n" 536 " ensure$capitalized_name$IsMutable();\n" 537 " super.addAll(values, $name$_);\n" 538 " $on_changed$\n" 539 " return this;\n" 540 "}\n"); 541 WriteFieldDocComment(printer, descriptor_); 542 printer->Print(variables_, 543 "$deprecation$public Builder clear$capitalized_name$() {\n" 544 " $name$_ = $empty_list$;\n" 545 " $clear_mutable_bit_builder$;\n" 546 " $on_changed$\n" 547 " return this;\n" 548 "}\n"); 549 550 WriteFieldDocComment(printer, descriptor_); 551 printer->Print(variables_, 552 "$deprecation$public Builder add$capitalized_name$Bytes(\n" 553 " com.google.protobuf.ByteString value) {\n" 554 "$null_check$" 555 " ensure$capitalized_name$IsMutable();\n" 556 " $name$_.add(value);\n" 557 " $on_changed$\n" 558 " return this;\n" 559 "}\n"); 560} 561 562void RepeatedStringFieldGenerator:: 563GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 564 // noop for primitives 565} 566 567void RepeatedStringFieldGenerator:: 568GenerateInitializationCode(io::Printer* printer) const { 569 printer->Print(variables_, "$name$_ = $empty_list$;\n"); 570} 571 572void RepeatedStringFieldGenerator:: 573GenerateBuilderClearCode(io::Printer* printer) const { 574 printer->Print(variables_, 575 "$name$_ = $empty_list$;\n" 576 "$clear_mutable_bit_builder$;\n"); 577} 578 579void RepeatedStringFieldGenerator:: 580GenerateMergingCode(io::Printer* printer) const { 581 // The code below does two optimizations: 582 // 1. If the other list is empty, there's nothing to do. This ensures we 583 // don't allocate a new array if we already have an immutable one. 584 // 2. If the other list is non-empty and our current list is empty, we can 585 // reuse the other list which is guaranteed to be immutable. 586 printer->Print(variables_, 587 "if (!other.$name$_.isEmpty()) {\n" 588 " if ($name$_.isEmpty()) {\n" 589 " $name$_ = other.$name$_;\n" 590 " $clear_mutable_bit_builder$;\n" 591 " } else {\n" 592 " ensure$capitalized_name$IsMutable();\n" 593 " $name$_.addAll(other.$name$_);\n" 594 " }\n" 595 " $on_changed$\n" 596 "}\n"); 597} 598 599void RepeatedStringFieldGenerator:: 600GenerateBuildingCode(io::Printer* printer) const { 601 // The code below ensures that the result has an immutable list. If our 602 // list is immutable, we can just reuse it. If not, we make it immutable. 603 604 printer->Print(variables_, 605 "if ($get_mutable_bit_builder$) {\n" 606 " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n" 607 " $name$_);\n" 608 " $clear_mutable_bit_builder$;\n" 609 "}\n" 610 "result.$name$_ = $name$_;\n"); 611} 612 613void RepeatedStringFieldGenerator:: 614GenerateParsingCode(io::Printer* printer) const { 615 printer->Print(variables_, 616 "if (!$get_mutable_bit_parser$) {\n" 617 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" 618 " $set_mutable_bit_parser$;\n" 619 "}\n" 620 "$name$_.add(input.readBytes());\n"); 621} 622 623void RepeatedStringFieldGenerator:: 624GenerateParsingCodeFromPacked(io::Printer* printer) const { 625 printer->Print(variables_, 626 "int length = input.readRawVarint32();\n" 627 "int limit = input.pushLimit(length);\n" 628 "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" 629 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" 630 " $set_mutable_bit_parser$;\n" 631 "}\n" 632 "while (input.getBytesUntilLimit() > 0) {\n" 633 " $name$.add(input.read$capitalized_type$());\n" 634 "}\n" 635 "input.popLimit(limit);\n"); 636} 637 638void RepeatedStringFieldGenerator:: 639GenerateParsingDoneCode(io::Printer* printer) const { 640 printer->Print(variables_, 641 "if ($get_mutable_bit_parser$) {\n" 642 " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n" 643 "}\n"); 644} 645 646void RepeatedStringFieldGenerator:: 647GenerateSerializationCode(io::Printer* printer) const { 648 if (descriptor_->options().packed()) { 649 printer->Print(variables_, 650 "if (get$capitalized_name$List().size() > 0) {\n" 651 " output.writeRawVarint32($tag$);\n" 652 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 653 "}\n" 654 "for (int i = 0; i < $name$_.size(); i++) {\n" 655 " output.write$capitalized_type$NoTag($name$_.get(i));\n" 656 "}\n"); 657 } else { 658 printer->Print(variables_, 659 "for (int i = 0; i < $name$_.size(); i++) {\n" 660 " output.writeBytes($number$, $name$_.getByteString(i));\n" 661 "}\n"); 662 } 663} 664 665void RepeatedStringFieldGenerator:: 666GenerateSerializedSizeCode(io::Printer* printer) const { 667 printer->Print(variables_, 668 "{\n" 669 " int dataSize = 0;\n"); 670 printer->Indent(); 671 672 printer->Print(variables_, 673 "for (int i = 0; i < $name$_.size(); i++) {\n" 674 " dataSize += com.google.protobuf.CodedOutputStream\n" 675 " .computeBytesSizeNoTag($name$_.getByteString(i));\n" 676 "}\n"); 677 678 printer->Print( 679 "size += dataSize;\n"); 680 681 if (descriptor_->options().packed()) { 682 printer->Print(variables_, 683 "if (!get$capitalized_name$List().isEmpty()) {\n" 684 " size += $tag_size$;\n" 685 " size += com.google.protobuf.CodedOutputStream\n" 686 " .computeInt32SizeNoTag(dataSize);\n" 687 "}\n"); 688 } else { 689 printer->Print(variables_, 690 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 691 } 692 693 // cache the data size for packed fields. 694 if (descriptor_->options().packed()) { 695 printer->Print(variables_, 696 "$name$MemoizedSerializedSize = dataSize;\n"); 697 } 698 699 printer->Outdent(); 700 printer->Print("}\n"); 701} 702 703void RepeatedStringFieldGenerator:: 704GenerateEqualsCode(io::Printer* printer) const { 705 printer->Print(variables_, 706 "result = result && get$capitalized_name$List()\n" 707 " .equals(other.get$capitalized_name$List());\n"); 708} 709 710void RepeatedStringFieldGenerator:: 711GenerateHashCode(io::Printer* printer) const { 712 printer->Print(variables_, 713 "if (get$capitalized_name$Count() > 0) {\n" 714 " hash = (37 * hash) + $constant_name$;\n" 715 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" 716 "}\n"); 717} 718 719string RepeatedStringFieldGenerator::GetBoxedType() const { 720 return "String"; 721} 722 723} // namespace java 724} // namespace compiler 725} // namespace protobuf 726} // namespace google 727