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 (at) google.com (Kenton Varda) 32 // Based on original Protocol Buffers design by 33 // Sanjay Ghemawat, Jeff Dean, and others. 34 35 #include <map> 36 #include <math.h> 37 #include <string> 38 39 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h> 40 #include <google/protobuf/stubs/common.h> 41 #include <google/protobuf/compiler/javanano/javanano_helpers.h> 42 #include <google/protobuf/io/printer.h> 43 #include <google/protobuf/wire_format.h> 44 #include <google/protobuf/stubs/strutil.h> 45 #include <google/protobuf/stubs/substitute.h> 46 47 namespace google { 48 namespace protobuf { 49 namespace compiler { 50 namespace javanano { 51 52 using internal::WireFormat; 53 using internal::WireFormatLite; 54 55 namespace { 56 57 bool IsReferenceType(JavaType type) { 58 switch (type) { 59 case JAVATYPE_INT : return false; 60 case JAVATYPE_LONG : return false; 61 case JAVATYPE_FLOAT : return false; 62 case JAVATYPE_DOUBLE : return false; 63 case JAVATYPE_BOOLEAN: return false; 64 case JAVATYPE_STRING : return true; 65 case JAVATYPE_BYTES : return true; 66 case JAVATYPE_ENUM : return false; 67 case JAVATYPE_MESSAGE: return true; 68 69 // No default because we want the compiler to complain if any new 70 // JavaTypes are added. 71 } 72 73 GOOGLE_LOG(FATAL) << "Can't get here."; 74 return false; 75 } 76 77 bool IsArrayType(JavaType type) { 78 switch (type) { 79 case JAVATYPE_INT : return false; 80 case JAVATYPE_LONG : return false; 81 case JAVATYPE_FLOAT : return false; 82 case JAVATYPE_DOUBLE : return false; 83 case JAVATYPE_BOOLEAN: return false; 84 case JAVATYPE_STRING : return false; 85 case JAVATYPE_BYTES : return true; 86 case JAVATYPE_ENUM : return false; 87 case JAVATYPE_MESSAGE: return false; 88 89 // No default because we want the compiler to complain if any new 90 // JavaTypes are added. 91 } 92 93 GOOGLE_LOG(FATAL) << "Can't get here."; 94 return false; 95 } 96 97 const char* GetCapitalizedType(const FieldDescriptor* field) { 98 switch (field->type()) { 99 case FieldDescriptor::TYPE_INT32 : return "Int32" ; 100 case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; 101 case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; 102 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; 103 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; 104 case FieldDescriptor::TYPE_INT64 : return "Int64" ; 105 case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; 106 case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; 107 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; 108 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; 109 case FieldDescriptor::TYPE_FLOAT : return "Float" ; 110 case FieldDescriptor::TYPE_DOUBLE : return "Double" ; 111 case FieldDescriptor::TYPE_BOOL : return "Bool" ; 112 case FieldDescriptor::TYPE_STRING : return "String" ; 113 case FieldDescriptor::TYPE_BYTES : return "Bytes" ; 114 case FieldDescriptor::TYPE_ENUM : return "Enum" ; 115 case FieldDescriptor::TYPE_GROUP : return "Group" ; 116 case FieldDescriptor::TYPE_MESSAGE : return "Message" ; 117 118 // No default because we want the compiler to complain if any new 119 // types are added. 120 } 121 122 GOOGLE_LOG(FATAL) << "Can't get here."; 123 return NULL; 124 } 125 126 // For encodings with fixed sizes, returns that size in bytes. Otherwise 127 // returns -1. 128 int FixedSize(FieldDescriptor::Type type) { 129 switch (type) { 130 case FieldDescriptor::TYPE_INT32 : return -1; 131 case FieldDescriptor::TYPE_INT64 : return -1; 132 case FieldDescriptor::TYPE_UINT32 : return -1; 133 case FieldDescriptor::TYPE_UINT64 : return -1; 134 case FieldDescriptor::TYPE_SINT32 : return -1; 135 case FieldDescriptor::TYPE_SINT64 : return -1; 136 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; 137 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; 138 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; 139 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; 140 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; 141 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; 142 143 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; 144 case FieldDescriptor::TYPE_ENUM : return -1; 145 146 case FieldDescriptor::TYPE_STRING : return -1; 147 case FieldDescriptor::TYPE_BYTES : return -1; 148 case FieldDescriptor::TYPE_GROUP : return -1; 149 case FieldDescriptor::TYPE_MESSAGE : return -1; 150 151 // No default because we want the compiler to complain if any new 152 // types are added. 153 } 154 GOOGLE_LOG(FATAL) << "Can't get here."; 155 return -1; 156 } 157 158 // Return true if the type is a that has variable length 159 // for instance String's. 160 bool IsVariableLenType(JavaType type) { 161 switch (type) { 162 case JAVATYPE_INT : return false; 163 case JAVATYPE_LONG : return false; 164 case JAVATYPE_FLOAT : return false; 165 case JAVATYPE_DOUBLE : return false; 166 case JAVATYPE_BOOLEAN: return false; 167 case JAVATYPE_STRING : return true; 168 case JAVATYPE_BYTES : return true; 169 case JAVATYPE_ENUM : return false; 170 case JAVATYPE_MESSAGE: return true; 171 172 // No default because we want the compiler to complain if any new 173 // JavaTypes are added. 174 } 175 176 GOOGLE_LOG(FATAL) << "Can't get here."; 177 return false; 178 } 179 180 bool AllAscii(const string& text) { 181 for (int i = 0; i < text.size(); i++) { 182 if ((text[i] & 0x80) != 0) { 183 return false; 184 } 185 } 186 return true; 187 } 188 189 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, 190 map<string, string>* variables) { 191 (*variables)["name"] = 192 RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); 193 (*variables)["capitalized_name"] = 194 RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); 195 (*variables)["number"] = SimpleItoa(descriptor->number()); 196 if (params.use_reference_types_for_primitives() 197 && !descriptor->is_repeated()) { 198 (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 199 } else { 200 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); 201 } 202 // Deals with defaults. For C++-string types (string and bytes), 203 // we might need to have the generated code do the unicode decoding 204 // (see comments in InternalNano.java for gory details.). We would 205 // like to do this once into a static field and re-use that from 206 // then on. 207 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && 208 !descriptor->default_value_string().empty() && 209 !params.use_reference_types_for_primitives()) { 210 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { 211 (*variables)["default"] = DefaultValue(params, descriptor); 212 (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); 213 (*variables)["default_constant_value"] = strings::Substitute( 214 "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")", 215 CEscape(descriptor->default_value_string())); 216 (*variables)["default_copy_if_needed"] = 217 (*variables)["default"] + ".clone()"; 218 } else if (AllAscii(descriptor->default_value_string())) { 219 // All chars are ASCII. In this case directly referencing a 220 // CEscape()'d string literal works fine. 221 (*variables)["default"] = 222 "\"" + CEscape(descriptor->default_value_string()) + "\""; 223 (*variables)["default_copy_if_needed"] = (*variables)["default"]; 224 } else { 225 // Strings where some chars are non-ASCII. We need to save the 226 // default value. 227 (*variables)["default"] = DefaultValue(params, descriptor); 228 (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); 229 (*variables)["default_constant_value"] = strings::Substitute( 230 "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", 231 CEscape(descriptor->default_value_string())); 232 (*variables)["default_copy_if_needed"] = (*variables)["default"]; 233 } 234 } else { 235 // Non-string, non-bytes field. Defaults are literals. 236 (*variables)["default"] = DefaultValue(params, descriptor); 237 (*variables)["default_copy_if_needed"] = (*variables)["default"]; 238 } 239 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 240 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); 241 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 242 (*variables)["tag_size"] = SimpleItoa( 243 WireFormat::TagSize(descriptor->number(), descriptor->type())); 244 (*variables)["non_packed_tag"] = SimpleItoa( 245 internal::WireFormatLite::MakeTag(descriptor->number(), 246 internal::WireFormat::WireTypeForFieldType(descriptor->type()))); 247 int fixed_size = FixedSize(descriptor->type()); 248 if (fixed_size != -1) { 249 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 250 } 251 (*variables)["message_name"] = descriptor->containing_type()->name(); 252 (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor); 253 } 254 } // namespace 255 256 // =================================================================== 257 258 PrimitiveFieldGenerator:: 259 PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 260 : FieldGenerator(params), descriptor_(descriptor) { 261 SetPrimitiveVariables(descriptor, params, &variables_); 262 } 263 264 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 265 266 bool PrimitiveFieldGenerator::SavedDefaultNeeded() const { 267 return variables_.find("default_constant") != variables_.end(); 268 } 269 270 void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const { 271 if (variables_.find("default_constant") != variables_.end()) { 272 printer->Print(variables_, 273 "$default_constant$ = $default_constant_value$;\n"); 274 } 275 } 276 277 void PrimitiveFieldGenerator:: 278 GenerateMembers(io::Printer* printer, bool lazy_init) const { 279 if (variables_.find("default_constant") != variables_.end()) { 280 // Those primitive types that need a saved default. 281 if (lazy_init) { 282 printer->Print(variables_, 283 "private static $type$ $default_constant$;\n"); 284 } else { 285 printer->Print(variables_, 286 "private static final $type$ $default_constant$ =\n" 287 " $default_constant_value$;\n"); 288 } 289 } 290 291 printer->Print(variables_, 292 "public $type$ $name$;\n"); 293 294 if (params_.generate_has()) { 295 printer->Print(variables_, 296 "public boolean has$capitalized_name$;\n"); 297 } 298 } 299 300 void PrimitiveFieldGenerator:: 301 GenerateClearCode(io::Printer* printer) const { 302 printer->Print(variables_, 303 "$name$ = $default_copy_if_needed$;\n"); 304 305 if (params_.generate_has()) { 306 printer->Print(variables_, 307 "has$capitalized_name$ = false;\n"); 308 } 309 } 310 311 void PrimitiveFieldGenerator:: 312 GenerateMergingCode(io::Printer* printer) const { 313 printer->Print(variables_, 314 "this.$name$ = input.read$capitalized_type$();\n"); 315 316 if (params_.generate_has()) { 317 printer->Print(variables_, 318 "has$capitalized_name$ = true;\n"); 319 } 320 } 321 322 void PrimitiveFieldGenerator:: 323 GenerateSerializationConditional(io::Printer* printer) const { 324 if (params_.use_reference_types_for_primitives()) { 325 // For reference type mode, serialize based on equality 326 // to null. 327 printer->Print(variables_, 328 "if (this.$name$ != null) {\n"); 329 return; 330 } 331 if (params_.generate_has()) { 332 printer->Print(variables_, 333 "if (has$capitalized_name$ || "); 334 } else { 335 printer->Print(variables_, 336 "if ("); 337 } 338 JavaType java_type = GetJavaType(descriptor_); 339 if (IsArrayType(java_type)) { 340 printer->Print(variables_, 341 "!java.util.Arrays.equals(this.$name$, $default$)) {\n"); 342 } else if (IsReferenceType(java_type)) { 343 printer->Print(variables_, 344 "!this.$name$.equals($default$)) {\n"); 345 } else if (java_type == JAVATYPE_FLOAT) { 346 printer->Print(variables_, 347 "java.lang.Float.floatToIntBits(this.$name$)\n" 348 " != java.lang.Float.floatToIntBits($default$)) {\n"); 349 } else if (java_type == JAVATYPE_DOUBLE) { 350 printer->Print(variables_, 351 "java.lang.Double.doubleToLongBits(this.$name$)\n" 352 " != java.lang.Double.doubleToLongBits($default$)) {\n"); 353 } else { 354 printer->Print(variables_, 355 "this.$name$ != $default$) {\n"); 356 } 357 } 358 359 void PrimitiveFieldGenerator:: 360 GenerateSerializationCode(io::Printer* printer) const { 361 if (descriptor_->is_required() && !params_.generate_has()) { 362 // Always serialize a required field if we don't have the 'has' signal. 363 printer->Print(variables_, 364 "output.write$capitalized_type$($number$, this.$name$);\n"); 365 } else { 366 GenerateSerializationConditional(printer); 367 printer->Print(variables_, 368 " output.write$capitalized_type$($number$, this.$name$);\n" 369 "}\n"); 370 } 371 } 372 373 void PrimitiveFieldGenerator:: 374 GenerateSerializedSizeCode(io::Printer* printer) const { 375 if (descriptor_->is_required() && !params_.generate_has()) { 376 printer->Print(variables_, 377 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 378 " .compute$capitalized_type$Size($number$, this.$name$);\n"); 379 } else { 380 GenerateSerializationConditional(printer); 381 printer->Print(variables_, 382 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 383 " .compute$capitalized_type$Size($number$, this.$name$);\n" 384 "}\n"); 385 } 386 } 387 388 void RepeatedPrimitiveFieldGenerator:: 389 GenerateFixClonedCode(io::Printer* printer) const { 390 printer->Print(variables_, 391 "if (this.$name$ != null && this.$name$.length > 0) {\n" 392 " cloned.$name$ = this.$name$.clone();\n" 393 "}\n"); 394 } 395 396 void PrimitiveFieldGenerator:: 397 GenerateEqualsCode(io::Printer* printer) const { 398 // We define equality as serialized form equality. If generate_has(), 399 // then if the field value equals the default value in both messages, 400 // but one's 'has' field is set and the other's is not, the serialized 401 // forms are different and we should return false. 402 JavaType java_type = GetJavaType(descriptor_); 403 if (java_type == JAVATYPE_BYTES) { 404 printer->Print(variables_, 405 "if (!java.util.Arrays.equals(this.$name$, other.$name$)"); 406 if (params_.generate_has()) { 407 printer->Print(variables_, 408 "\n" 409 " || (java.util.Arrays.equals(this.$name$, $default$)\n" 410 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 411 } 412 printer->Print(") {\n" 413 " return false;\n" 414 "}\n"); 415 } else if (java_type == JAVATYPE_STRING 416 || params_.use_reference_types_for_primitives()) { 417 printer->Print(variables_, 418 "if (this.$name$ == null) {\n" 419 " if (other.$name$ != null) {\n" 420 " return false;\n" 421 " }\n" 422 "} else if (!this.$name$.equals(other.$name$)"); 423 if (params_.generate_has()) { 424 printer->Print(variables_, 425 "\n" 426 " || (this.$name$.equals($default$)\n" 427 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 428 } 429 printer->Print(") {\n" 430 " return false;\n" 431 "}\n"); 432 } else if (java_type == JAVATYPE_FLOAT) { 433 printer->Print(variables_, 434 "{\n" 435 " int bits = java.lang.Float.floatToIntBits(this.$name$);\n" 436 " if (bits != java.lang.Float.floatToIntBits(other.$name$)"); 437 if (params_.generate_has()) { 438 printer->Print(variables_, 439 "\n" 440 " || (bits == java.lang.Float.floatToIntBits($default$)\n" 441 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 442 } 443 printer->Print(") {\n" 444 " return false;\n" 445 " }\n" 446 "}\n"); 447 } else if (java_type == JAVATYPE_DOUBLE) { 448 printer->Print(variables_, 449 "{\n" 450 " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n" 451 " if (bits != java.lang.Double.doubleToLongBits(other.$name$)"); 452 if (params_.generate_has()) { 453 printer->Print(variables_, 454 "\n" 455 " || (bits == java.lang.Double.doubleToLongBits($default$)\n" 456 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 457 } 458 printer->Print(") {\n" 459 " return false;\n" 460 " }\n" 461 "}\n"); 462 } else { 463 printer->Print(variables_, 464 "if (this.$name$ != other.$name$"); 465 if (params_.generate_has()) { 466 printer->Print(variables_, 467 "\n" 468 " || (this.$name$ == $default$\n" 469 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 470 } 471 printer->Print(") {\n" 472 " return false;\n" 473 "}\n"); 474 } 475 } 476 477 void PrimitiveFieldGenerator:: 478 GenerateHashCodeCode(io::Printer* printer) const { 479 JavaType java_type = GetJavaType(descriptor_); 480 if (java_type == JAVATYPE_BYTES) { 481 printer->Print(variables_, 482 "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n"); 483 } else if (java_type == JAVATYPE_STRING 484 || params_.use_reference_types_for_primitives()) { 485 printer->Print(variables_, 486 "result = 31 * result\n" 487 " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); 488 } else { 489 switch (java_type) { 490 // For all Java primitive types below, the hash codes match the 491 // results of BoxedType.valueOf(primitiveValue).hashCode(). 492 case JAVATYPE_INT: 493 printer->Print(variables_, 494 "result = 31 * result + this.$name$;\n"); 495 break; 496 case JAVATYPE_LONG: 497 printer->Print(variables_, 498 "result = 31 * result\n" 499 " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n"); 500 break; 501 case JAVATYPE_FLOAT: 502 printer->Print(variables_, 503 "result = 31 * result\n" 504 " + java.lang.Float.floatToIntBits(this.$name$);\n"); 505 break; 506 case JAVATYPE_DOUBLE: 507 printer->Print(variables_, 508 "{\n" 509 " long v = java.lang.Double.doubleToLongBits(this.$name$);\n" 510 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 511 "}\n"); 512 break; 513 case JAVATYPE_BOOLEAN: 514 printer->Print(variables_, 515 "result = 31 * result + (this.$name$ ? 1231 : 1237);\n"); 516 break; 517 default: 518 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 519 break; 520 } 521 } 522 } 523 524 // =================================================================== 525 526 AccessorPrimitiveFieldGenerator:: 527 AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 528 const Params& params, int has_bit_index) 529 : FieldGenerator(params), descriptor_(descriptor) { 530 SetPrimitiveVariables(descriptor, params, &variables_); 531 SetBitOperationVariables("has", has_bit_index, &variables_); 532 } 533 534 AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} 535 536 bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const { 537 return variables_.find("default_constant") != variables_.end(); 538 } 539 540 void AccessorPrimitiveFieldGenerator:: 541 GenerateInitSavedDefaultCode(io::Printer* printer) const { 542 if (variables_.find("default_constant") != variables_.end()) { 543 printer->Print(variables_, 544 "$default_constant$ = $default_constant_value$;\n"); 545 } 546 } 547 548 void AccessorPrimitiveFieldGenerator:: 549 GenerateMembers(io::Printer* printer, bool lazy_init) const { 550 if (variables_.find("default_constant") != variables_.end()) { 551 // Those primitive types that need a saved default. 552 if (lazy_init) { 553 printer->Print(variables_, 554 "private static $type$ $default_constant$;\n"); 555 } else { 556 printer->Print(variables_, 557 "private static final $type$ $default_constant$ =\n" 558 " $default_constant_value$;\n"); 559 } 560 } 561 printer->Print(variables_, 562 "private $type$ $name$_;\n" 563 "public $type$ get$capitalized_name$() {\n" 564 " return $name$_;\n" 565 "}\n" 566 "public $message_name$ set$capitalized_name$($type$ value) {\n"); 567 if (IsReferenceType(GetJavaType(descriptor_))) { 568 printer->Print(variables_, 569 " if (value == null) {\n" 570 " throw new java.lang.NullPointerException();\n" 571 " }\n"); 572 } 573 printer->Print(variables_, 574 " $name$_ = value;\n" 575 " $set_has$;\n" 576 " return this;\n" 577 "}\n" 578 "public boolean has$capitalized_name$() {\n" 579 " return $get_has$;\n" 580 "}\n" 581 "public $message_name$ clear$capitalized_name$() {\n" 582 " $name$_ = $default_copy_if_needed$;\n" 583 " $clear_has$;\n" 584 " return this;\n" 585 "}\n"); 586 } 587 588 void AccessorPrimitiveFieldGenerator:: 589 GenerateClearCode(io::Printer* printer) const { 590 printer->Print(variables_, 591 "$name$_ = $default_copy_if_needed$;\n"); 592 } 593 594 void AccessorPrimitiveFieldGenerator:: 595 GenerateMergingCode(io::Printer* printer) const { 596 printer->Print(variables_, 597 "$name$_ = input.read$capitalized_type$();\n" 598 "$set_has$;\n"); 599 } 600 601 void AccessorPrimitiveFieldGenerator:: 602 GenerateSerializationCode(io::Printer* printer) const { 603 printer->Print(variables_, 604 "if ($get_has$) {\n" 605 " output.write$capitalized_type$($number$, $name$_);\n" 606 "}\n"); 607 } 608 609 void AccessorPrimitiveFieldGenerator:: 610 GenerateSerializedSizeCode(io::Printer* printer) const { 611 printer->Print(variables_, 612 "if ($get_has$) {\n" 613 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 614 " .compute$capitalized_type$Size($number$, $name$_);\n" 615 "}\n"); 616 } 617 618 void AccessorPrimitiveFieldGenerator:: 619 GenerateEqualsCode(io::Printer* printer) const { 620 switch (GetJavaType(descriptor_)) { 621 // For all Java primitive types below, the equality checks match the 622 // results of BoxedType.valueOf(primitiveValue).equals(otherValue). 623 case JAVATYPE_FLOAT: 624 printer->Print(variables_, 625 "if ($different_has$\n" 626 " || java.lang.Float.floatToIntBits($name$_)\n" 627 " != java.lang.Float.floatToIntBits(other.$name$_)) {\n" 628 " return false;\n" 629 "}\n"); 630 break; 631 case JAVATYPE_DOUBLE: 632 printer->Print(variables_, 633 "if ($different_has$\n" 634 " || java.lang.Double.doubleToLongBits($name$_)\n" 635 " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n" 636 " return false;\n" 637 "}\n"); 638 break; 639 case JAVATYPE_INT: 640 case JAVATYPE_LONG: 641 case JAVATYPE_BOOLEAN: 642 printer->Print(variables_, 643 "if ($different_has$\n" 644 " || $name$_ != other.$name$_) {\n" 645 " return false;\n" 646 "}\n"); 647 break; 648 case JAVATYPE_STRING: 649 // Accessor style would guarantee $name$_ non-null 650 printer->Print(variables_, 651 "if ($different_has$\n" 652 " || !$name$_.equals(other.$name$_)) {\n" 653 " return false;\n" 654 "}\n"); 655 break; 656 case JAVATYPE_BYTES: 657 // Accessor style would guarantee $name$_ non-null 658 printer->Print(variables_, 659 "if ($different_has$\n" 660 " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n" 661 " return false;\n" 662 "}\n"); 663 break; 664 default: 665 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 666 break; 667 } 668 } 669 670 void AccessorPrimitiveFieldGenerator:: 671 GenerateHashCodeCode(io::Printer* printer) const { 672 switch (GetJavaType(descriptor_)) { 673 // For all Java primitive types below, the hash codes match the 674 // results of BoxedType.valueOf(primitiveValue).hashCode(). 675 case JAVATYPE_INT: 676 printer->Print(variables_, 677 "result = 31 * result + $name$_;\n"); 678 break; 679 case JAVATYPE_LONG: 680 printer->Print(variables_, 681 "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n"); 682 break; 683 case JAVATYPE_FLOAT: 684 printer->Print(variables_, 685 "result = 31 * result +\n" 686 " java.lang.Float.floatToIntBits($name$_);\n"); 687 break; 688 case JAVATYPE_DOUBLE: 689 printer->Print(variables_, 690 "{\n" 691 " long v = java.lang.Double.doubleToLongBits($name$_);\n" 692 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 693 "}\n"); 694 break; 695 case JAVATYPE_BOOLEAN: 696 printer->Print(variables_, 697 "result = 31 * result + ($name$_ ? 1231 : 1237);\n"); 698 break; 699 case JAVATYPE_STRING: 700 // Accessor style would guarantee $name$_ non-null 701 printer->Print(variables_, 702 "result = 31 * result + $name$_.hashCode();\n"); 703 break; 704 case JAVATYPE_BYTES: 705 // Accessor style would guarantee $name$_ non-null 706 printer->Print(variables_, 707 "result = 31 * result + java.util.Arrays.hashCode($name$_);\n"); 708 break; 709 default: 710 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 711 break; 712 } 713 } 714 715 // =================================================================== 716 717 RepeatedPrimitiveFieldGenerator:: 718 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 719 : FieldGenerator(params), descriptor_(descriptor) { 720 SetPrimitiveVariables(descriptor, params, &variables_); 721 } 722 723 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 724 725 void RepeatedPrimitiveFieldGenerator:: 726 GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const { 727 printer->Print(variables_, 728 "public $type$[] $name$;\n"); 729 } 730 731 void RepeatedPrimitiveFieldGenerator:: 732 GenerateClearCode(io::Printer* printer) const { 733 printer->Print(variables_, 734 "$name$ = $default$;\n"); 735 } 736 737 void RepeatedPrimitiveFieldGenerator:: 738 GenerateMergingCode(io::Printer* printer) const { 739 // First, figure out the length of the array, then parse. 740 printer->Print(variables_, 741 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 742 " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n" 743 "int i = this.$name$ == null ? 0 : this.$name$.length;\n"); 744 745 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { 746 printer->Print(variables_, 747 "byte[][] newArray = new byte[i + arrayLength][];\n"); 748 } else { 749 printer->Print(variables_, 750 "$type$[] newArray = new $type$[i + arrayLength];\n"); 751 } 752 printer->Print(variables_, 753 "if (i != 0) {\n" 754 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 755 "}\n" 756 "for (; i < newArray.length - 1; i++) {\n" 757 " newArray[i] = input.read$capitalized_type$();\n" 758 " input.readTag();\n" 759 "}\n" 760 "// Last one without readTag.\n" 761 "newArray[i] = input.read$capitalized_type$();\n" 762 "this.$name$ = newArray;\n"); 763 } 764 765 void RepeatedPrimitiveFieldGenerator:: 766 GenerateMergingCodeFromPacked(io::Printer* printer) const { 767 printer->Print( 768 "int length = input.readRawVarint32();\n" 769 "int limit = input.pushLimit(length);\n"); 770 771 // If we know the elements will all be of the same size, the arrayLength 772 // can be calculated much more easily. However, FixedSize() returns 1 for 773 // repeated bool fields, which are guaranteed to have the fixed size of 774 // 1 byte per value only if we control the output. On the wire they can 775 // legally appear as variable-size integers, so we need to use the slow 776 // way for repeated bool fields. 777 if (descriptor_->type() == FieldDescriptor::TYPE_BOOL 778 || FixedSize(descriptor_->type()) == -1) { 779 printer->Print(variables_, 780 "// First pass to compute array length.\n" 781 "int arrayLength = 0;\n" 782 "int startPos = input.getPosition();\n" 783 "while (input.getBytesUntilLimit() > 0) {\n" 784 " input.read$capitalized_type$();\n" 785 " arrayLength++;\n" 786 "}\n" 787 "input.rewindToPosition(startPos);\n"); 788 } else { 789 printer->Print(variables_, 790 "int arrayLength = length / $fixed_size$;\n"); 791 } 792 793 printer->Print(variables_, 794 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 795 "$type$[] newArray = new $type$[i + arrayLength];\n" 796 "if (i != 0) {\n" 797 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 798 "}\n" 799 "for (; i < newArray.length; i++) {\n" 800 " newArray[i] = input.read$capitalized_type$();\n" 801 "}\n" 802 "this.$name$ = newArray;\n" 803 "input.popLimit(limit);\n"); 804 } 805 806 void RepeatedPrimitiveFieldGenerator:: 807 GenerateRepeatedDataSizeCode(io::Printer* printer) const { 808 // Creates a variable dataSize and puts the serialized size in there. 809 // If the element type is a Java reference type, also generates 810 // dataCount which stores the number of non-null elements in the field. 811 if (IsReferenceType(GetJavaType(descriptor_))) { 812 printer->Print(variables_, 813 "int dataCount = 0;\n" 814 "int dataSize = 0;\n" 815 "for (int i = 0; i < this.$name$.length; i++) {\n" 816 " $type$ element = this.$name$[i];\n" 817 " if (element != null) {\n" 818 " dataCount++;\n" 819 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 820 " .compute$capitalized_type$SizeNoTag(element);\n" 821 " }\n" 822 "}\n"); 823 } else if (FixedSize(descriptor_->type()) == -1) { 824 printer->Print(variables_, 825 "int dataSize = 0;\n" 826 "for (int i = 0; i < this.$name$.length; i++) {\n" 827 " $type$ element = this.$name$[i];\n" 828 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 829 " .compute$capitalized_type$SizeNoTag(element);\n" 830 "}\n"); 831 } else { 832 printer->Print(variables_, 833 "int dataSize = $fixed_size$ * this.$name$.length;\n"); 834 } 835 } 836 837 void RepeatedPrimitiveFieldGenerator:: 838 GenerateSerializationCode(io::Printer* printer) const { 839 printer->Print(variables_, 840 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 841 printer->Indent(); 842 843 if (descriptor_->is_packable() && descriptor_->options().packed()) { 844 GenerateRepeatedDataSizeCode(printer); 845 printer->Print(variables_, 846 "output.writeRawVarint32($tag$);\n" 847 "output.writeRawVarint32(dataSize);\n" 848 "for (int i = 0; i < this.$name$.length; i++) {\n" 849 " output.write$capitalized_type$NoTag(this.$name$[i]);\n" 850 "}\n"); 851 } else if (IsReferenceType(GetJavaType(descriptor_))) { 852 printer->Print(variables_, 853 "for (int i = 0; i < this.$name$.length; i++) {\n" 854 " $type$ element = this.$name$[i];\n" 855 " if (element != null) {\n" 856 " output.write$capitalized_type$($number$, element);\n" 857 " }\n" 858 "}\n"); 859 } else { 860 printer->Print(variables_, 861 "for (int i = 0; i < this.$name$.length; i++) {\n" 862 " output.write$capitalized_type$($number$, this.$name$[i]);\n" 863 "}\n"); 864 } 865 866 printer->Outdent(); 867 printer->Print("}\n"); 868 } 869 870 void RepeatedPrimitiveFieldGenerator:: 871 GenerateSerializedSizeCode(io::Printer* printer) const { 872 printer->Print(variables_, 873 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 874 printer->Indent(); 875 876 GenerateRepeatedDataSizeCode(printer); 877 878 printer->Print( 879 "size += dataSize;\n"); 880 if (descriptor_->is_packable() && descriptor_->options().packed()) { 881 printer->Print(variables_, 882 "size += $tag_size$;\n" 883 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 884 " .computeRawVarint32Size(dataSize);\n"); 885 } else if (IsReferenceType(GetJavaType(descriptor_))) { 886 printer->Print(variables_, 887 "size += $tag_size$ * dataCount;\n"); 888 } else { 889 printer->Print(variables_, 890 "size += $tag_size$ * this.$name$.length;\n"); 891 } 892 893 printer->Outdent(); 894 895 printer->Print( 896 "}\n"); 897 } 898 899 void RepeatedPrimitiveFieldGenerator:: 900 GenerateEqualsCode(io::Printer* printer) const { 901 printer->Print(variables_, 902 "if (!com.google.protobuf.nano.InternalNano.equals(\n" 903 " this.$name$, other.$name$)) {\n" 904 " return false;\n" 905 "}\n"); 906 } 907 908 void RepeatedPrimitiveFieldGenerator:: 909 GenerateHashCodeCode(io::Printer* printer) const { 910 printer->Print(variables_, 911 "result = 31 * result\n" 912 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); 913 } 914 915 } // namespace javanano 916 } // namespace compiler 917 } // namespace protobuf 918 } // namespace google 919