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 PrimitiveFieldGenerator:: 389 GenerateEqualsCode(io::Printer* printer) const { 390 // We define equality as serialized form equality. If generate_has(), 391 // then if the field value equals the default value in both messages, 392 // but one's 'has' field is set and the other's is not, the serialized 393 // forms are different and we should return false. 394 JavaType java_type = GetJavaType(descriptor_); 395 if (java_type == JAVATYPE_BYTES) { 396 printer->Print(variables_, 397 "if (!java.util.Arrays.equals(this.$name$, other.$name$)"); 398 if (params_.generate_has()) { 399 printer->Print(variables_, 400 "\n" 401 " || (java.util.Arrays.equals(this.$name$, $default$)\n" 402 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 403 } 404 printer->Print(") {\n" 405 " return false;\n" 406 "}\n"); 407 } else if (java_type == JAVATYPE_STRING 408 || params_.use_reference_types_for_primitives()) { 409 printer->Print(variables_, 410 "if (this.$name$ == null) {\n" 411 " if (other.$name$ != null) {\n" 412 " return false;\n" 413 " }\n" 414 "} else if (!this.$name$.equals(other.$name$)"); 415 if (params_.generate_has()) { 416 printer->Print(variables_, 417 "\n" 418 " || (this.$name$.equals($default$)\n" 419 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 420 } 421 printer->Print(") {\n" 422 " return false;\n" 423 "}\n"); 424 } else if (java_type == JAVATYPE_FLOAT) { 425 printer->Print(variables_, 426 "{\n" 427 " int bits = java.lang.Float.floatToIntBits(this.$name$);\n" 428 " if (bits != java.lang.Float.floatToIntBits(other.$name$)"); 429 if (params_.generate_has()) { 430 printer->Print(variables_, 431 "\n" 432 " || (bits == java.lang.Float.floatToIntBits($default$)\n" 433 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 434 } 435 printer->Print(") {\n" 436 " return false;\n" 437 " }\n" 438 "}\n"); 439 } else if (java_type == JAVATYPE_DOUBLE) { 440 printer->Print(variables_, 441 "{\n" 442 " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n" 443 " if (bits != java.lang.Double.doubleToLongBits(other.$name$)"); 444 if (params_.generate_has()) { 445 printer->Print(variables_, 446 "\n" 447 " || (bits == java.lang.Double.doubleToLongBits($default$)\n" 448 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 449 } 450 printer->Print(") {\n" 451 " return false;\n" 452 " }\n" 453 "}\n"); 454 } else { 455 printer->Print(variables_, 456 "if (this.$name$ != other.$name$"); 457 if (params_.generate_has()) { 458 printer->Print(variables_, 459 "\n" 460 " || (this.$name$ == $default$\n" 461 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 462 } 463 printer->Print(") {\n" 464 " return false;\n" 465 "}\n"); 466 } 467 } 468 469 void PrimitiveFieldGenerator:: 470 GenerateHashCodeCode(io::Printer* printer) const { 471 JavaType java_type = GetJavaType(descriptor_); 472 if (java_type == JAVATYPE_BYTES) { 473 printer->Print(variables_, 474 "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n"); 475 } else if (java_type == JAVATYPE_STRING 476 || params_.use_reference_types_for_primitives()) { 477 printer->Print(variables_, 478 "result = 31 * result\n" 479 " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); 480 } else { 481 switch (java_type) { 482 // For all Java primitive types below, the hash codes match the 483 // results of BoxedType.valueOf(primitiveValue).hashCode(). 484 case JAVATYPE_INT: 485 printer->Print(variables_, 486 "result = 31 * result + this.$name$;\n"); 487 break; 488 case JAVATYPE_LONG: 489 printer->Print(variables_, 490 "result = 31 * result\n" 491 " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n"); 492 break; 493 case JAVATYPE_FLOAT: 494 printer->Print(variables_, 495 "result = 31 * result\n" 496 " + java.lang.Float.floatToIntBits(this.$name$);\n"); 497 break; 498 case JAVATYPE_DOUBLE: 499 printer->Print(variables_, 500 "{\n" 501 " long v = java.lang.Double.doubleToLongBits(this.$name$);\n" 502 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 503 "}\n"); 504 break; 505 case JAVATYPE_BOOLEAN: 506 printer->Print(variables_, 507 "result = 31 * result + (this.$name$ ? 1231 : 1237);\n"); 508 break; 509 default: 510 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 511 break; 512 } 513 } 514 } 515 516 // =================================================================== 517 518 AccessorPrimitiveFieldGenerator:: 519 AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 520 const Params& params, int has_bit_index) 521 : FieldGenerator(params), descriptor_(descriptor) { 522 SetPrimitiveVariables(descriptor, params, &variables_); 523 SetBitOperationVariables("has", has_bit_index, &variables_); 524 } 525 526 AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} 527 528 bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const { 529 return variables_.find("default_constant") != variables_.end(); 530 } 531 532 void AccessorPrimitiveFieldGenerator:: 533 GenerateInitSavedDefaultCode(io::Printer* printer) const { 534 if (variables_.find("default_constant") != variables_.end()) { 535 printer->Print(variables_, 536 "$default_constant$ = $default_constant_value$;\n"); 537 } 538 } 539 540 void AccessorPrimitiveFieldGenerator:: 541 GenerateMembers(io::Printer* printer, bool lazy_init) const { 542 if (variables_.find("default_constant") != variables_.end()) { 543 // Those primitive types that need a saved default. 544 if (lazy_init) { 545 printer->Print(variables_, 546 "private static $type$ $default_constant$;\n"); 547 } else { 548 printer->Print(variables_, 549 "private static final $type$ $default_constant$ =\n" 550 " $default_constant_value$;\n"); 551 } 552 } 553 printer->Print(variables_, 554 "private $type$ $name$_;\n" 555 "public $type$ get$capitalized_name$() {\n" 556 " return $name$_;\n" 557 "}\n" 558 "public $message_name$ set$capitalized_name$($type$ value) {\n"); 559 if (IsReferenceType(GetJavaType(descriptor_))) { 560 printer->Print(variables_, 561 " if (value == null) {\n" 562 " throw new java.lang.NullPointerException();\n" 563 " }\n"); 564 } 565 printer->Print(variables_, 566 " $name$_ = value;\n" 567 " $set_has$;\n" 568 " return this;\n" 569 "}\n" 570 "public boolean has$capitalized_name$() {\n" 571 " return $get_has$;\n" 572 "}\n" 573 "public $message_name$ clear$capitalized_name$() {\n" 574 " $name$_ = $default_copy_if_needed$;\n" 575 " $clear_has$;\n" 576 " return this;\n" 577 "}\n"); 578 } 579 580 void AccessorPrimitiveFieldGenerator:: 581 GenerateClearCode(io::Printer* printer) const { 582 printer->Print(variables_, 583 "$name$_ = $default_copy_if_needed$;\n"); 584 } 585 586 void AccessorPrimitiveFieldGenerator:: 587 GenerateMergingCode(io::Printer* printer) const { 588 printer->Print(variables_, 589 "$name$_ = input.read$capitalized_type$();\n" 590 "$set_has$;\n"); 591 } 592 593 void AccessorPrimitiveFieldGenerator:: 594 GenerateSerializationCode(io::Printer* printer) const { 595 printer->Print(variables_, 596 "if ($get_has$) {\n" 597 " output.write$capitalized_type$($number$, $name$_);\n" 598 "}\n"); 599 } 600 601 void AccessorPrimitiveFieldGenerator:: 602 GenerateSerializedSizeCode(io::Printer* printer) const { 603 printer->Print(variables_, 604 "if ($get_has$) {\n" 605 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 606 " .compute$capitalized_type$Size($number$, $name$_);\n" 607 "}\n"); 608 } 609 610 void AccessorPrimitiveFieldGenerator:: 611 GenerateEqualsCode(io::Printer* printer) const { 612 switch (GetJavaType(descriptor_)) { 613 // For all Java primitive types below, the equality checks match the 614 // results of BoxedType.valueOf(primitiveValue).equals(otherValue). 615 case JAVATYPE_FLOAT: 616 printer->Print(variables_, 617 "if ($different_has$\n" 618 " || java.lang.Float.floatToIntBits($name$_)\n" 619 " != java.lang.Float.floatToIntBits(other.$name$_)) {\n" 620 " return false;\n" 621 "}\n"); 622 break; 623 case JAVATYPE_DOUBLE: 624 printer->Print(variables_, 625 "if ($different_has$\n" 626 " || java.lang.Double.doubleToLongBits($name$_)\n" 627 " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n" 628 " return false;\n" 629 "}\n"); 630 break; 631 case JAVATYPE_INT: 632 case JAVATYPE_LONG: 633 case JAVATYPE_BOOLEAN: 634 printer->Print(variables_, 635 "if ($different_has$\n" 636 " || $name$_ != other.$name$_) {\n" 637 " return false;\n" 638 "}\n"); 639 break; 640 case JAVATYPE_STRING: 641 // Accessor style would guarantee $name$_ non-null 642 printer->Print(variables_, 643 "if ($different_has$\n" 644 " || !$name$_.equals(other.$name$_)) {\n" 645 " return false;\n" 646 "}\n"); 647 break; 648 case JAVATYPE_BYTES: 649 // Accessor style would guarantee $name$_ non-null 650 printer->Print(variables_, 651 "if ($different_has$\n" 652 " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n" 653 " return false;\n" 654 "}\n"); 655 break; 656 default: 657 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 658 break; 659 } 660 } 661 662 void AccessorPrimitiveFieldGenerator:: 663 GenerateHashCodeCode(io::Printer* printer) const { 664 switch (GetJavaType(descriptor_)) { 665 // For all Java primitive types below, the hash codes match the 666 // results of BoxedType.valueOf(primitiveValue).hashCode(). 667 case JAVATYPE_INT: 668 printer->Print(variables_, 669 "result = 31 * result + $name$_;\n"); 670 break; 671 case JAVATYPE_LONG: 672 printer->Print(variables_, 673 "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n"); 674 break; 675 case JAVATYPE_FLOAT: 676 printer->Print(variables_, 677 "result = 31 * result +\n" 678 " java.lang.Float.floatToIntBits($name$_);\n"); 679 break; 680 case JAVATYPE_DOUBLE: 681 printer->Print(variables_, 682 "{\n" 683 " long v = java.lang.Double.doubleToLongBits($name$_);\n" 684 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 685 "}\n"); 686 break; 687 case JAVATYPE_BOOLEAN: 688 printer->Print(variables_, 689 "result = 31 * result + ($name$_ ? 1231 : 1237);\n"); 690 break; 691 case JAVATYPE_STRING: 692 // Accessor style would guarantee $name$_ non-null 693 printer->Print(variables_, 694 "result = 31 * result + $name$_.hashCode();\n"); 695 break; 696 case JAVATYPE_BYTES: 697 // Accessor style would guarantee $name$_ non-null 698 printer->Print(variables_, 699 "result = 31 * result + java.util.Arrays.hashCode($name$_);\n"); 700 break; 701 default: 702 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 703 break; 704 } 705 } 706 707 // =================================================================== 708 709 RepeatedPrimitiveFieldGenerator:: 710 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 711 : FieldGenerator(params), descriptor_(descriptor) { 712 SetPrimitiveVariables(descriptor, params, &variables_); 713 } 714 715 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 716 717 void RepeatedPrimitiveFieldGenerator:: 718 GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const { 719 printer->Print(variables_, 720 "public $type$[] $name$;\n"); 721 } 722 723 void RepeatedPrimitiveFieldGenerator:: 724 GenerateClearCode(io::Printer* printer) const { 725 printer->Print(variables_, 726 "$name$ = $default$;\n"); 727 } 728 729 void RepeatedPrimitiveFieldGenerator:: 730 GenerateMergingCode(io::Printer* printer) const { 731 // First, figure out the length of the array, then parse. 732 printer->Print(variables_, 733 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 734 " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n" 735 "int i = this.$name$ == null ? 0 : this.$name$.length;\n"); 736 737 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { 738 printer->Print(variables_, 739 "byte[][] newArray = new byte[i + arrayLength][];\n"); 740 } else { 741 printer->Print(variables_, 742 "$type$[] newArray = new $type$[i + arrayLength];\n"); 743 } 744 printer->Print(variables_, 745 "if (i != 0) {\n" 746 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 747 "}\n" 748 "for (; i < newArray.length - 1; i++) {\n" 749 " newArray[i] = input.read$capitalized_type$();\n" 750 " input.readTag();\n" 751 "}\n" 752 "// Last one without readTag.\n" 753 "newArray[i] = input.read$capitalized_type$();\n" 754 "this.$name$ = newArray;\n"); 755 } 756 757 void RepeatedPrimitiveFieldGenerator:: 758 GenerateMergingCodeFromPacked(io::Printer* printer) const { 759 printer->Print( 760 "int length = input.readRawVarint32();\n" 761 "int limit = input.pushLimit(length);\n"); 762 763 // If we know the elements will all be of the same size, the arrayLength 764 // can be calculated much more easily. However, FixedSize() returns 1 for 765 // repeated bool fields, which are guaranteed to have the fixed size of 766 // 1 byte per value only if we control the output. On the wire they can 767 // legally appear as variable-size integers, so we need to use the slow 768 // way for repeated bool fields. 769 if (descriptor_->type() == FieldDescriptor::TYPE_BOOL 770 || FixedSize(descriptor_->type()) == -1) { 771 printer->Print(variables_, 772 "// First pass to compute array length.\n" 773 "int arrayLength = 0;\n" 774 "int startPos = input.getPosition();\n" 775 "while (input.getBytesUntilLimit() > 0) {\n" 776 " input.read$capitalized_type$();\n" 777 " arrayLength++;\n" 778 "}\n" 779 "input.rewindToPosition(startPos);\n"); 780 } else { 781 printer->Print(variables_, 782 "int arrayLength = length / $fixed_size$;\n"); 783 } 784 785 printer->Print(variables_, 786 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 787 "$type$[] newArray = new $type$[i + arrayLength];\n" 788 "if (i != 0) {\n" 789 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 790 "}\n" 791 "for (; i < newArray.length; i++) {\n" 792 " newArray[i] = input.read$capitalized_type$();\n" 793 "}\n" 794 "this.$name$ = newArray;\n" 795 "input.popLimit(limit);\n"); 796 } 797 798 void RepeatedPrimitiveFieldGenerator:: 799 GenerateRepeatedDataSizeCode(io::Printer* printer) const { 800 // Creates a variable dataSize and puts the serialized size in there. 801 // If the element type is a Java reference type, also generates 802 // dataCount which stores the number of non-null elements in the field. 803 if (IsReferenceType(GetJavaType(descriptor_))) { 804 printer->Print(variables_, 805 "int dataCount = 0;\n" 806 "int dataSize = 0;\n" 807 "for (int i = 0; i < this.$name$.length; i++) {\n" 808 " $type$ element = this.$name$[i];\n" 809 " if (element != null) {\n" 810 " dataCount++;\n" 811 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 812 " .compute$capitalized_type$SizeNoTag(element);\n" 813 " }\n" 814 "}\n"); 815 } else if (FixedSize(descriptor_->type()) == -1) { 816 printer->Print(variables_, 817 "int dataSize = 0;\n" 818 "for (int i = 0; i < this.$name$.length; i++) {\n" 819 " $type$ element = this.$name$[i];\n" 820 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 821 " .compute$capitalized_type$SizeNoTag(element);\n" 822 "}\n"); 823 } else { 824 printer->Print(variables_, 825 "int dataSize = $fixed_size$ * this.$name$.length;\n"); 826 } 827 } 828 829 void RepeatedPrimitiveFieldGenerator:: 830 GenerateSerializationCode(io::Printer* printer) const { 831 printer->Print(variables_, 832 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 833 printer->Indent(); 834 835 if (descriptor_->is_packable() && descriptor_->options().packed()) { 836 GenerateRepeatedDataSizeCode(printer); 837 printer->Print(variables_, 838 "output.writeRawVarint32($tag$);\n" 839 "output.writeRawVarint32(dataSize);\n" 840 "for (int i = 0; i < this.$name$.length; i++) {\n" 841 " output.write$capitalized_type$NoTag(this.$name$[i]);\n" 842 "}\n"); 843 } else if (IsReferenceType(GetJavaType(descriptor_))) { 844 printer->Print(variables_, 845 "for (int i = 0; i < this.$name$.length; i++) {\n" 846 " $type$ element = this.$name$[i];\n" 847 " if (element != null) {\n" 848 " output.write$capitalized_type$($number$, element);\n" 849 " }\n" 850 "}\n"); 851 } else { 852 printer->Print(variables_, 853 "for (int i = 0; i < this.$name$.length; i++) {\n" 854 " output.write$capitalized_type$($number$, this.$name$[i]);\n" 855 "}\n"); 856 } 857 858 printer->Outdent(); 859 printer->Print("}\n"); 860 } 861 862 void RepeatedPrimitiveFieldGenerator:: 863 GenerateSerializedSizeCode(io::Printer* printer) const { 864 printer->Print(variables_, 865 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 866 printer->Indent(); 867 868 GenerateRepeatedDataSizeCode(printer); 869 870 printer->Print( 871 "size += dataSize;\n"); 872 if (descriptor_->is_packable() && descriptor_->options().packed()) { 873 printer->Print(variables_, 874 "size += $tag_size$;\n" 875 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 876 " .computeRawVarint32Size(dataSize);\n"); 877 } else if (IsReferenceType(GetJavaType(descriptor_))) { 878 printer->Print(variables_, 879 "size += $tag_size$ * dataCount;\n"); 880 } else { 881 printer->Print(variables_, 882 "size += $tag_size$ * this.$name$.length;\n"); 883 } 884 885 printer->Outdent(); 886 887 printer->Print( 888 "}\n"); 889 } 890 891 void RepeatedPrimitiveFieldGenerator:: 892 GenerateEqualsCode(io::Printer* printer) const { 893 printer->Print(variables_, 894 "if (!com.google.protobuf.nano.InternalNano.equals(\n" 895 " this.$name$, other.$name$)) {\n" 896 " return false;\n" 897 "}\n"); 898 } 899 900 void RepeatedPrimitiveFieldGenerator:: 901 GenerateHashCodeCode(io::Printer* printer) const { 902 printer->Print(variables_, 903 "result = 31 * result\n" 904 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); 905 } 906 907 } // namespace javanano 908 } // namespace compiler 909 } // namespace protobuf 910 } // namespace google 911