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