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