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 (at) google.com (Kenton Varda) 32 // Author: jonp (at) 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.h> 46 #include <google/protobuf/io/printer.h> 47 #include <google/protobuf/wire_format.h> 48 #include <google/protobuf/stubs/strutil.h> 49 50 namespace google { 51 namespace protobuf { 52 namespace compiler { 53 namespace java { 54 55 using internal::WireFormat; 56 using internal::WireFormatLite; 57 58 namespace { 59 60 void 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"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; 69 70 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); 71 (*variables)["default_init"] = 72 "= " + ImmutableDefaultValue(descriptor, name_resolver); 73 (*variables)["capitalized_type"] = "String"; 74 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 75 (*variables)["tag_size"] = SimpleItoa( 76 WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 77 (*variables)["null_check"] = 78 " if (value == null) {\n" 79 " throw new NullPointerException();\n" 80 " }\n"; 81 (*variables)["writeString"] = 82 "com.google.protobuf.GeneratedMessage.writeString"; 83 (*variables)["computeStringSize"] = 84 "com.google.protobuf.GeneratedMessage.computeStringSize"; 85 86 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 87 // by the proto compiler 88 (*variables)["deprecation"] = descriptor->options().deprecated() 89 ? "@java.lang.Deprecated " : ""; 90 (*variables)["on_changed"] = "onChanged();"; 91 92 if (SupportFieldPresence(descriptor->file())) { 93 // For singular messages and builders, one bit is used for the hasField bit. 94 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 95 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 96 97 // Note that these have a trailing ";". 98 (*variables)["set_has_field_bit_message"] = 99 GenerateSetBit(messageBitIndex) + ";"; 100 (*variables)["set_has_field_bit_builder"] = 101 GenerateSetBit(builderBitIndex) + ";"; 102 (*variables)["clear_has_field_bit_builder"] = 103 GenerateClearBit(builderBitIndex) + ";"; 104 105 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); 106 } else { 107 (*variables)["set_has_field_bit_message"] = ""; 108 (*variables)["set_has_field_bit_builder"] = ""; 109 (*variables)["clear_has_field_bit_builder"] = ""; 110 111 (*variables)["is_field_present_message"] = 112 "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; 113 } 114 115 // For repeated builders, one bit is used for whether the array is immutable. 116 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 117 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 118 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 119 120 // For repeated fields, one bit is used for whether the array is immutable 121 // in the parsing constructor. 122 (*variables)["get_mutable_bit_parser"] = 123 GenerateGetBitMutableLocal(builderBitIndex); 124 (*variables)["set_mutable_bit_parser"] = 125 GenerateSetBitMutableLocal(builderBitIndex); 126 127 (*variables)["get_has_field_bit_from_local"] = 128 GenerateGetBitFromLocal(builderBitIndex); 129 (*variables)["set_has_field_bit_to_local"] = 130 GenerateSetBitToLocal(messageBitIndex); 131 } 132 133 } // namespace 134 135 // =================================================================== 136 137 ImmutableStringFieldGenerator:: 138 ImmutableStringFieldGenerator(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 150 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} 151 152 int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { 153 return 1; 154 } 155 156 int 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. 192 void ImmutableStringFieldGenerator:: 193 GenerateInterfaceMembers(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 208 void ImmutableStringFieldGenerator:: 209 GenerateMembers(io::Printer* printer) const { 210 printer->Print(variables_, 211 "private volatile 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 262 void ImmutableStringFieldGenerator:: 263 GenerateBuilderMembers(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 354 void ImmutableStringFieldGenerator:: 355 GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 356 // noop for primitives 357 } 358 359 void ImmutableStringFieldGenerator:: 360 GenerateInitializationCode(io::Printer* printer) const { 361 printer->Print(variables_, "$name$_ = $default$;\n"); 362 } 363 364 void ImmutableStringFieldGenerator:: 365 GenerateBuilderClearCode(io::Printer* printer) const { 366 printer->Print(variables_, 367 "$name$_ = $default$;\n" 368 "$clear_has_field_bit_builder$\n"); 369 } 370 371 void ImmutableStringFieldGenerator:: 372 GenerateMergingCode(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 391 void ImmutableStringFieldGenerator:: 392 GenerateBuildingCode(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 403 void ImmutableStringFieldGenerator:: 404 GenerateParsingCode(io::Printer* printer) const { 405 if (CheckUtf8(descriptor_)) { 406 printer->Print(variables_, 407 "java.lang.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 418 void ImmutableStringFieldGenerator:: 419 GenerateParsingDoneCode(io::Printer* printer) const { 420 // noop for strings. 421 } 422 423 void ImmutableStringFieldGenerator:: 424 GenerateSerializationCode(io::Printer* printer) const { 425 printer->Print(variables_, 426 "if ($is_field_present_message$) {\n" 427 " $writeString$(output, $number$, $name$_);\n" 428 "}\n"); 429 } 430 431 void ImmutableStringFieldGenerator:: 432 GenerateSerializedSizeCode(io::Printer* printer) const { 433 printer->Print(variables_, 434 "if ($is_field_present_message$) {\n" 435 " size += $computeStringSize$($number$, $name$_);\n" 436 "}\n"); 437 } 438 439 void ImmutableStringFieldGenerator:: 440 GenerateEqualsCode(io::Printer* printer) const { 441 printer->Print(variables_, 442 "result = result && get$capitalized_name$()\n" 443 " .equals(other.get$capitalized_name$());\n"); 444 } 445 446 void ImmutableStringFieldGenerator:: 447 GenerateHashCode(io::Printer* printer) const { 448 printer->Print(variables_, 449 "hash = (37 * hash) + $constant_name$;\n"); 450 printer->Print(variables_, 451 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); 452 } 453 454 string ImmutableStringFieldGenerator::GetBoxedType() const { 455 return "java.lang.String"; 456 } 457 458 // =================================================================== 459 460 ImmutableStringOneofFieldGenerator:: 461 ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, 462 int messageBitIndex, 463 int builderBitIndex, 464 Context* context) 465 : ImmutableStringFieldGenerator( 466 descriptor, messageBitIndex, builderBitIndex, context) { 467 const OneofGeneratorInfo* info = 468 context->GetOneofGeneratorInfo(descriptor->containing_oneof()); 469 SetCommonOneofVariables(descriptor, info, &variables_); 470 } 471 472 ImmutableStringOneofFieldGenerator:: 473 ~ImmutableStringOneofFieldGenerator() {} 474 475 void ImmutableStringOneofFieldGenerator:: 476 GenerateMembers(io::Printer* printer) const { 477 PrintExtraFieldInfo(variables_, printer); 478 479 if (SupportFieldPresence(descriptor_->file())) { 480 WriteFieldDocComment(printer, descriptor_); 481 printer->Print(variables_, 482 "$deprecation$public boolean has$capitalized_name$() {\n" 483 " return $has_oneof_case_message$;\n" 484 "}\n"); 485 } 486 487 WriteFieldDocComment(printer, descriptor_); 488 printer->Print(variables_, 489 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 490 " java.lang.Object ref $default_init$;\n" 491 " if ($has_oneof_case_message$) {\n" 492 " ref = $oneof_name$_;\n" 493 " }\n" 494 " if (ref instanceof java.lang.String) {\n" 495 " return (java.lang.String) ref;\n" 496 " } else {\n" 497 " com.google.protobuf.ByteString bs = \n" 498 " (com.google.protobuf.ByteString) ref;\n" 499 " java.lang.String s = bs.toStringUtf8();\n"); 500 if (CheckUtf8(descriptor_)) { 501 printer->Print(variables_, 502 " if ($has_oneof_case_message$) {\n" 503 " $oneof_name$_ = s;\n" 504 " }\n"); 505 } else { 506 printer->Print(variables_, 507 " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" 508 " $oneof_name$_ = s;\n" 509 " }\n"); 510 } 511 printer->Print(variables_, 512 " return s;\n" 513 " }\n" 514 "}\n"); 515 WriteFieldDocComment(printer, descriptor_); 516 517 printer->Print(variables_, 518 "$deprecation$public com.google.protobuf.ByteString\n" 519 " get$capitalized_name$Bytes() {\n" 520 " java.lang.Object ref $default_init$;\n" 521 " if ($has_oneof_case_message$) {\n" 522 " ref = $oneof_name$_;\n" 523 " }\n" 524 " if (ref instanceof java.lang.String) {\n" 525 " com.google.protobuf.ByteString b = \n" 526 " com.google.protobuf.ByteString.copyFromUtf8(\n" 527 " (java.lang.String) ref);\n" 528 " if ($has_oneof_case_message$) {\n" 529 " $oneof_name$_ = b;\n" 530 " }\n" 531 " return b;\n" 532 " } else {\n" 533 " return (com.google.protobuf.ByteString) ref;\n" 534 " }\n" 535 "}\n"); 536 } 537 538 void ImmutableStringOneofFieldGenerator:: 539 GenerateBuilderMembers(io::Printer* printer) const { 540 if (SupportFieldPresence(descriptor_->file())) { 541 WriteFieldDocComment(printer, descriptor_); 542 printer->Print(variables_, 543 "$deprecation$public boolean has$capitalized_name$() {\n" 544 " return $has_oneof_case_message$;\n" 545 "}\n"); 546 } 547 548 WriteFieldDocComment(printer, descriptor_); 549 printer->Print(variables_, 550 "$deprecation$public java.lang.String get$capitalized_name$() {\n" 551 " java.lang.Object ref $default_init$;\n" 552 " if ($has_oneof_case_message$) {\n" 553 " ref = $oneof_name$_;\n" 554 " }\n" 555 " if (!(ref instanceof java.lang.String)) {\n" 556 " com.google.protobuf.ByteString bs =\n" 557 " (com.google.protobuf.ByteString) ref;\n" 558 " java.lang.String s = bs.toStringUtf8();\n" 559 " if ($has_oneof_case_message$) {\n"); 560 if (CheckUtf8(descriptor_)) { 561 printer->Print(variables_, 562 " $oneof_name$_ = s;\n"); 563 } else { 564 printer->Print(variables_, 565 " if (bs.isValidUtf8()) {\n" 566 " $oneof_name$_ = s;\n" 567 " }\n"); 568 } 569 printer->Print(variables_, 570 " }\n" 571 " return s;\n" 572 " } else {\n" 573 " return (java.lang.String) ref;\n" 574 " }\n" 575 "}\n"); 576 577 WriteFieldDocComment(printer, descriptor_); 578 printer->Print(variables_, 579 "$deprecation$public com.google.protobuf.ByteString\n" 580 " get$capitalized_name$Bytes() {\n" 581 " java.lang.Object ref $default_init$;\n" 582 " if ($has_oneof_case_message$) {\n" 583 " ref = $oneof_name$_;\n" 584 " }\n" 585 " if (ref instanceof String) {\n" 586 " com.google.protobuf.ByteString b = \n" 587 " com.google.protobuf.ByteString.copyFromUtf8(\n" 588 " (java.lang.String) ref);\n" 589 " if ($has_oneof_case_message$) {\n" 590 " $oneof_name$_ = b;\n" 591 " }\n" 592 " return b;\n" 593 " } else {\n" 594 " return (com.google.protobuf.ByteString) ref;\n" 595 " }\n" 596 "}\n"); 597 598 WriteFieldDocComment(printer, descriptor_); 599 printer->Print(variables_, 600 "$deprecation$public Builder set$capitalized_name$(\n" 601 " java.lang.String value) {\n" 602 "$null_check$" 603 " $set_oneof_case_message$;\n" 604 " $oneof_name$_ = value;\n" 605 " $on_changed$\n" 606 " return this;\n" 607 "}\n"); 608 WriteFieldDocComment(printer, descriptor_); 609 printer->Print(variables_, 610 "$deprecation$public Builder clear$capitalized_name$() {\n" 611 " if ($has_oneof_case_message$) {\n" 612 " $clear_oneof_case_message$;\n" 613 " $oneof_name$_ = null;\n" 614 " $on_changed$\n" 615 " }\n" 616 " return this;\n" 617 "}\n"); 618 619 WriteFieldDocComment(printer, descriptor_); 620 printer->Print(variables_, 621 "$deprecation$public Builder set$capitalized_name$Bytes(\n" 622 " com.google.protobuf.ByteString value) {\n" 623 "$null_check$"); 624 if (CheckUtf8(descriptor_)) { 625 printer->Print(variables_, 626 " checkByteStringIsUtf8(value);\n"); 627 } 628 printer->Print(variables_, 629 " $set_oneof_case_message$;\n" 630 " $oneof_name$_ = value;\n" 631 " $on_changed$\n" 632 " return this;\n" 633 "}\n"); 634 } 635 636 void ImmutableStringOneofFieldGenerator:: 637 GenerateMergingCode(io::Printer* printer) const { 638 // Allow a slight breach of abstraction here in order to avoid forcing 639 // all string fields to Strings when copying fields from a Message. 640 printer->Print(variables_, 641 "$set_oneof_case_message$;\n" 642 "$oneof_name$_ = other.$oneof_name$_;\n" 643 "$on_changed$\n"); 644 } 645 646 void ImmutableStringOneofFieldGenerator:: 647 GenerateBuildingCode(io::Printer* printer) const { 648 printer->Print(variables_, 649 "if ($has_oneof_case_message$) {\n" 650 " result.$oneof_name$_ = $oneof_name$_;\n" 651 "}\n"); 652 } 653 654 void ImmutableStringOneofFieldGenerator:: 655 GenerateParsingCode(io::Printer* printer) const { 656 if (CheckUtf8(descriptor_)) { 657 printer->Print(variables_, 658 "java.lang.String s = input.readStringRequireUtf8();\n" 659 "$set_oneof_case_message$;\n" 660 "$oneof_name$_ = s;\n"); 661 } else { 662 printer->Print(variables_, 663 "com.google.protobuf.ByteString bs = input.readBytes();\n" 664 "$set_oneof_case_message$;\n" 665 "$oneof_name$_ = bs;\n"); 666 } 667 } 668 669 void ImmutableStringOneofFieldGenerator:: 670 GenerateSerializationCode(io::Printer* printer) const { 671 printer->Print(variables_, 672 "if ($has_oneof_case_message$) {\n" 673 " $writeString$(output, $number$, $oneof_name$_);\n" 674 "}\n"); 675 } 676 677 void ImmutableStringOneofFieldGenerator:: 678 GenerateSerializedSizeCode(io::Printer* printer) const { 679 printer->Print(variables_, 680 "if ($has_oneof_case_message$) {\n" 681 " size += $computeStringSize$($number$, $oneof_name$_);\n" 682 "}\n"); 683 } 684 685 // =================================================================== 686 687 RepeatedImmutableStringFieldGenerator:: 688 RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, 689 int messageBitIndex, 690 int builderBitIndex, 691 Context* context) 692 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 693 builderBitIndex_(builderBitIndex), context_(context), 694 name_resolver_(context->GetNameResolver()) { 695 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, 696 context->GetFieldGeneratorInfo(descriptor), 697 name_resolver_, &variables_); 698 } 699 700 RepeatedImmutableStringFieldGenerator:: 701 ~RepeatedImmutableStringFieldGenerator() {} 702 703 int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { 704 return 0; 705 } 706 707 int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { 708 return 1; 709 } 710 711 void RepeatedImmutableStringFieldGenerator:: 712 GenerateInterfaceMembers(io::Printer* printer) const { 713 WriteFieldDocComment(printer, descriptor_); 714 printer->Print(variables_, 715 "$deprecation$com.google.protobuf.ProtocolStringList\n" 716 " get$capitalized_name$List();\n"); 717 WriteFieldDocComment(printer, descriptor_); 718 printer->Print(variables_, 719 "$deprecation$int get$capitalized_name$Count();\n"); 720 WriteFieldDocComment(printer, descriptor_); 721 printer->Print(variables_, 722 "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); 723 WriteFieldDocComment(printer, descriptor_); 724 printer->Print(variables_, 725 "$deprecation$com.google.protobuf.ByteString\n" 726 " get$capitalized_name$Bytes(int index);\n"); 727 } 728 729 730 void RepeatedImmutableStringFieldGenerator:: 731 GenerateMembers(io::Printer* printer) const { 732 printer->Print(variables_, 733 "private com.google.protobuf.LazyStringList $name$_;\n"); 734 PrintExtraFieldInfo(variables_, printer); 735 WriteFieldDocComment(printer, descriptor_); 736 printer->Print(variables_, 737 "$deprecation$public com.google.protobuf.ProtocolStringList\n" 738 " get$capitalized_name$List() {\n" 739 " return $name$_;\n" // note: unmodifiable list 740 "}\n"); 741 WriteFieldDocComment(printer, descriptor_); 742 printer->Print(variables_, 743 "$deprecation$public int get$capitalized_name$Count() {\n" 744 " return $name$_.size();\n" 745 "}\n"); 746 WriteFieldDocComment(printer, descriptor_); 747 printer->Print(variables_, 748 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 749 " return $name$_.get(index);\n" 750 "}\n"); 751 WriteFieldDocComment(printer, descriptor_); 752 printer->Print(variables_, 753 "$deprecation$public com.google.protobuf.ByteString\n" 754 " get$capitalized_name$Bytes(int index) {\n" 755 " return $name$_.getByteString(index);\n" 756 "}\n"); 757 } 758 759 void RepeatedImmutableStringFieldGenerator:: 760 GenerateBuilderMembers(io::Printer* printer) const { 761 // One field is the list and the bit field keeps track of whether the 762 // list is immutable. If it's immutable, the invariant is that it must 763 // either an instance of Collections.emptyList() or it's an ArrayList 764 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 765 // a refererence to the underlying ArrayList. This invariant allows us to 766 // share instances of lists between protocol buffers avoiding expensive 767 // memory allocations. Note, immutable is a strong guarantee here -- not 768 // just that the list cannot be modified via the reference but that the 769 // list can never be modified. 770 printer->Print(variables_, 771 "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); 772 773 printer->Print(variables_, 774 "private void ensure$capitalized_name$IsMutable() {\n" 775 " if (!$get_mutable_bit_builder$) {\n" 776 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" 777 " $set_mutable_bit_builder$;\n" 778 " }\n" 779 "}\n"); 780 781 // Note: We return an unmodifiable list because otherwise the caller 782 // could hold on to the returned list and modify it after the message 783 // has been built, thus mutating the message which is supposed to be 784 // immutable. 785 WriteFieldDocComment(printer, descriptor_); 786 printer->Print(variables_, 787 "$deprecation$public com.google.protobuf.ProtocolStringList\n" 788 " get$capitalized_name$List() {\n" 789 " return $name$_.getUnmodifiableView();\n" 790 "}\n"); 791 WriteFieldDocComment(printer, descriptor_); 792 printer->Print(variables_, 793 "$deprecation$public int get$capitalized_name$Count() {\n" 794 " return $name$_.size();\n" 795 "}\n"); 796 WriteFieldDocComment(printer, descriptor_); 797 printer->Print(variables_, 798 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" 799 " return $name$_.get(index);\n" 800 "}\n"); 801 WriteFieldDocComment(printer, descriptor_); 802 printer->Print(variables_, 803 "$deprecation$public com.google.protobuf.ByteString\n" 804 " get$capitalized_name$Bytes(int index) {\n" 805 " return $name$_.getByteString(index);\n" 806 "}\n"); 807 WriteFieldDocComment(printer, descriptor_); 808 printer->Print(variables_, 809 "$deprecation$public Builder set$capitalized_name$(\n" 810 " int index, java.lang.String value) {\n" 811 "$null_check$" 812 " ensure$capitalized_name$IsMutable();\n" 813 " $name$_.set(index, value);\n" 814 " $on_changed$\n" 815 " return this;\n" 816 "}\n"); 817 WriteFieldDocComment(printer, descriptor_); 818 printer->Print(variables_, 819 "$deprecation$public Builder add$capitalized_name$(\n" 820 " java.lang.String value) {\n" 821 "$null_check$" 822 " ensure$capitalized_name$IsMutable();\n" 823 " $name$_.add(value);\n" 824 " $on_changed$\n" 825 " return this;\n" 826 "}\n"); 827 WriteFieldDocComment(printer, descriptor_); 828 printer->Print(variables_, 829 "$deprecation$public Builder addAll$capitalized_name$(\n" 830 " java.lang.Iterable<java.lang.String> values) {\n" 831 " ensure$capitalized_name$IsMutable();\n" 832 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" 833 " values, $name$_);\n" 834 " $on_changed$\n" 835 " return this;\n" 836 "}\n"); 837 WriteFieldDocComment(printer, descriptor_); 838 printer->Print(variables_, 839 "$deprecation$public Builder clear$capitalized_name$() {\n" 840 " $name$_ = $empty_list$;\n" 841 " $clear_mutable_bit_builder$;\n" 842 " $on_changed$\n" 843 " return this;\n" 844 "}\n"); 845 846 WriteFieldDocComment(printer, descriptor_); 847 printer->Print(variables_, 848 "$deprecation$public Builder add$capitalized_name$Bytes(\n" 849 " com.google.protobuf.ByteString value) {\n" 850 "$null_check$"); 851 if (CheckUtf8(descriptor_)) { 852 printer->Print(variables_, 853 " checkByteStringIsUtf8(value);\n"); 854 } 855 printer->Print(variables_, 856 " ensure$capitalized_name$IsMutable();\n" 857 " $name$_.add(value);\n" 858 " $on_changed$\n" 859 " return this;\n" 860 "}\n"); 861 } 862 863 void RepeatedImmutableStringFieldGenerator:: 864 GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 865 // noop for primitives 866 } 867 868 void RepeatedImmutableStringFieldGenerator:: 869 GenerateInitializationCode(io::Printer* printer) const { 870 printer->Print(variables_, "$name$_ = $empty_list$;\n"); 871 } 872 873 void RepeatedImmutableStringFieldGenerator:: 874 GenerateBuilderClearCode(io::Printer* printer) const { 875 printer->Print(variables_, 876 "$name$_ = $empty_list$;\n" 877 "$clear_mutable_bit_builder$;\n"); 878 } 879 880 void RepeatedImmutableStringFieldGenerator:: 881 GenerateMergingCode(io::Printer* printer) const { 882 // The code below does two optimizations: 883 // 1. If the other list is empty, there's nothing to do. This ensures we 884 // don't allocate a new array if we already have an immutable one. 885 // 2. If the other list is non-empty and our current list is empty, we can 886 // reuse the other list which is guaranteed to be immutable. 887 printer->Print(variables_, 888 "if (!other.$name$_.isEmpty()) {\n" 889 " if ($name$_.isEmpty()) {\n" 890 " $name$_ = other.$name$_;\n" 891 " $clear_mutable_bit_builder$;\n" 892 " } else {\n" 893 " ensure$capitalized_name$IsMutable();\n" 894 " $name$_.addAll(other.$name$_);\n" 895 " }\n" 896 " $on_changed$\n" 897 "}\n"); 898 } 899 900 void RepeatedImmutableStringFieldGenerator:: 901 GenerateBuildingCode(io::Printer* printer) const { 902 // The code below ensures that the result has an immutable list. If our 903 // list is immutable, we can just reuse it. If not, we make it immutable. 904 905 printer->Print(variables_, 906 "if ($get_mutable_bit_builder$) {\n" 907 " $name$_ = $name$_.getUnmodifiableView();\n" 908 " $clear_mutable_bit_builder$;\n" 909 "}\n" 910 "result.$name$_ = $name$_;\n"); 911 } 912 913 void RepeatedImmutableStringFieldGenerator:: 914 GenerateParsingCode(io::Printer* printer) const { 915 if (CheckUtf8(descriptor_)) { 916 printer->Print(variables_, 917 "java.lang.String s = input.readStringRequireUtf8();\n"); 918 } else { 919 printer->Print(variables_, 920 "com.google.protobuf.ByteString bs = input.readBytes();\n"); 921 } 922 printer->Print(variables_, 923 "if (!$get_mutable_bit_parser$) {\n" 924 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" 925 " $set_mutable_bit_parser$;\n" 926 "}\n"); 927 if (CheckUtf8(descriptor_)) { 928 printer->Print(variables_, 929 "$name$_.add(s);\n"); 930 } else { 931 printer->Print(variables_, 932 "$name$_.add(bs);\n"); 933 } 934 } 935 936 void RepeatedImmutableStringFieldGenerator:: 937 GenerateParsingDoneCode(io::Printer* printer) const { 938 printer->Print(variables_, 939 "if ($get_mutable_bit_parser$) {\n" 940 " $name$_ = $name$_.getUnmodifiableView();\n" 941 "}\n"); 942 } 943 944 void RepeatedImmutableStringFieldGenerator:: 945 GenerateSerializationCode(io::Printer* printer) const { 946 printer->Print(variables_, 947 "for (int i = 0; i < $name$_.size(); i++) {\n" 948 " $writeString$(output, $number$, $name$_.getRaw(i));\n" 949 "}\n"); 950 } 951 952 void RepeatedImmutableStringFieldGenerator:: 953 GenerateSerializedSizeCode(io::Printer* printer) const { 954 printer->Print(variables_, 955 "{\n" 956 " int dataSize = 0;\n"); 957 printer->Indent(); 958 959 printer->Print(variables_, 960 "for (int i = 0; i < $name$_.size(); i++) {\n" 961 " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n" 962 "}\n"); 963 964 printer->Print( 965 "size += dataSize;\n"); 966 967 printer->Print(variables_, 968 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 969 970 printer->Outdent(); 971 printer->Print("}\n"); 972 } 973 974 void RepeatedImmutableStringFieldGenerator:: 975 GenerateEqualsCode(io::Printer* printer) const { 976 printer->Print(variables_, 977 "result = result && get$capitalized_name$List()\n" 978 " .equals(other.get$capitalized_name$List());\n"); 979 } 980 981 void RepeatedImmutableStringFieldGenerator:: 982 GenerateHashCode(io::Printer* printer) const { 983 printer->Print(variables_, 984 "if (get$capitalized_name$Count() > 0) {\n" 985 " hash = (37 * hash) + $constant_name$;\n" 986 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" 987 "}\n"); 988 } 989 990 string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { 991 return "String"; 992 } 993 994 } // namespace java 995 } // namespace compiler 996 } // namespace protobuf 997 } // namespace google 998