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 57bool 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 77bool 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 97const 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. 128int 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. 160bool 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 180bool 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 189void 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 258PrimitiveFieldGenerator:: 259PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 260 : FieldGenerator(params), descriptor_(descriptor) { 261 SetPrimitiveVariables(descriptor, params, &variables_); 262} 263 264PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 265 266bool PrimitiveFieldGenerator::SavedDefaultNeeded() const { 267 return variables_.find("default_constant") != variables_.end(); 268} 269 270void 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 277void PrimitiveFieldGenerator:: 278GenerateMembers(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 JavaType java_type = GetJavaType(descriptor_); 292 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 293 printer->Print(variables_, 294 "public $type$ $name$Buffer;\n" 295 "public int $name$Offset;\n" 296 "public int $name$Length;\n"); 297 } else { 298 printer->Print(variables_, 299 "public $type$ $name$;\n"); 300 } 301 302 if (params_.generate_has()) { 303 printer->Print(variables_, 304 "public boolean has$capitalized_name$;\n"); 305 } 306} 307 308void PrimitiveFieldGenerator:: 309GenerateClearCode(io::Printer* printer) const { 310 JavaType java_type = GetJavaType(descriptor_); 311 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 312 printer->Print(variables_, 313 "$name$Buffer = $default_copy_if_needed$;\n" 314 "$name$Offset = -1;\n" 315 "$name$Length = 0;\n"); 316 } else { 317 printer->Print(variables_, 318 "$name$ = $default_copy_if_needed$;\n"); 319 } 320 321 if (params_.generate_has()) { 322 printer->Print(variables_, 323 "has$capitalized_name$ = false;\n"); 324 } 325} 326 327void PrimitiveFieldGenerator:: 328GenerateMergingCode(io::Printer* printer) const { 329 JavaType java_type = GetJavaType(descriptor_); 330 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 331 printer->Print(variables_, 332 "this.$name$Buffer = input.getBuffer();\n" 333 "this.$name$Length = input.readRawVarint32();\n" 334 "this.$name$Offset = input.getAbsolutePosition();\n" 335 "input.skipRawBytes(this.$name$Length);\n"); 336 } else { 337 printer->Print(variables_, 338 "this.$name$ = input.read$capitalized_type$();\n"); 339 } 340 341 if (params_.generate_has()) { 342 printer->Print(variables_, 343 "has$capitalized_name$ = true;\n"); 344 } 345} 346 347void PrimitiveFieldGenerator:: 348GenerateSerializationConditional(io::Printer* printer) const { 349 if (params_.use_reference_types_for_primitives()) { 350 // For reference type mode, serialize based on equality 351 // to null. 352 printer->Print(variables_, 353 "if (this.$name$ != null) {\n"); 354 return; 355 } 356 if (params_.generate_has()) { 357 printer->Print(variables_, 358 "if (has$capitalized_name$ || "); 359 } else { 360 printer->Print(variables_, 361 "if ("); 362 } 363 JavaType java_type = GetJavaType(descriptor_); 364 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 365 printer->Print(variables_, 366 "this.$name$Offset != -1) {\n"); 367 } else if (IsArrayType(java_type)) { 368 printer->Print(variables_, 369 "!java.util.Arrays.equals(this.$name$, $default$)) {\n"); 370 } else if (IsReferenceType(java_type)) { 371 printer->Print(variables_, 372 "!this.$name$.equals($default$)) {\n"); 373 } else if (java_type == JAVATYPE_FLOAT) { 374 printer->Print(variables_, 375 "java.lang.Float.floatToIntBits(this.$name$)\n" 376 " != java.lang.Float.floatToIntBits($default$)) {\n"); 377 } else if (java_type == JAVATYPE_DOUBLE) { 378 printer->Print(variables_, 379 "java.lang.Double.doubleToLongBits(this.$name$)\n" 380 " != java.lang.Double.doubleToLongBits($default$)) {\n"); 381 } else { 382 printer->Print(variables_, 383 "this.$name$ != $default$) {\n"); 384 } 385} 386 387void PrimitiveFieldGenerator:: 388GenerateSerializationCode(io::Printer* printer) const { 389 if (descriptor_->is_required() && !params_.generate_has()) { 390 // Always serialize a required field if we don't have the 'has' signal. 391 GenerateWriteCode(printer); 392 } else { 393 GenerateSerializationConditional(printer); 394 printer->Indent(); 395 GenerateWriteCode(printer); 396 printer->Outdent(); 397 printer->Print("}\n"); 398 } 399} 400 401void PrimitiveFieldGenerator:: 402GenerateWriteCode(io::Printer* printer) const { 403 JavaType java_type = GetJavaType(descriptor_); 404 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 405 printer->Print(variables_, 406 "output.write$capitalized_type$($number$, this.$name$Buffer,\n" 407 " this.$name$Offset, this.$name$Length);\n"); 408 } else { 409 printer->Print(variables_, 410 "output.write$capitalized_type$($number$, this.$name$);\n"); 411 } 412} 413 414void PrimitiveFieldGenerator:: 415GenerateSerializedSizeCode(io::Printer* printer) const { 416 if (descriptor_->is_required() && !params_.generate_has()) { 417 GenerateComputeSizeCode(printer); 418 } else { 419 GenerateSerializationConditional(printer); 420 printer->Indent(); 421 GenerateComputeSizeCode(printer); 422 printer->Outdent(); 423 printer->Print("}\n"); 424 } 425} 426 427void PrimitiveFieldGenerator:: 428GenerateComputeSizeCode(io::Printer* printer) const { 429 JavaType java_type = GetJavaType(descriptor_); 430 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) { 431 printer->Print(variables_, 432 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 433 " .compute$capitalized_type$Size($number$, this.$name$Length);\n"); 434 } else { 435 printer->Print(variables_, 436 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 437 " .compute$capitalized_type$Size($number$, this.$name$);\n"); 438 } 439} 440 441void RepeatedPrimitiveFieldGenerator:: 442GenerateFixClonedCode(io::Printer* printer) const { 443 printer->Print(variables_, 444 "if (this.$name$ != null && this.$name$.length > 0) {\n" 445 " cloned.$name$ = this.$name$.clone();\n" 446 "}\n"); 447} 448 449void PrimitiveFieldGenerator:: 450GenerateEqualsCode(io::Printer* printer) const { 451 // We define equality as serialized form equality. If generate_has(), 452 // then if the field value equals the default value in both messages, 453 // but one's 'has' field is set and the other's is not, the serialized 454 // forms are different and we should return false. 455 JavaType java_type = GetJavaType(descriptor_); 456 if (java_type == JAVATYPE_BYTES) { 457 printer->Print(variables_, 458 "if (!java.util.Arrays.equals(this.$name$, other.$name$)"); 459 if (params_.generate_has()) { 460 printer->Print(variables_, 461 "\n" 462 " || (java.util.Arrays.equals(this.$name$, $default$)\n" 463 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 464 } 465 printer->Print(") {\n" 466 " return false;\n" 467 "}\n"); 468 } else if (java_type == JAVATYPE_STRING 469 || params_.use_reference_types_for_primitives()) { 470 printer->Print(variables_, 471 "if (this.$name$ == null) {\n" 472 " if (other.$name$ != null) {\n" 473 " return false;\n" 474 " }\n" 475 "} else if (!this.$name$.equals(other.$name$)"); 476 if (params_.generate_has()) { 477 printer->Print(variables_, 478 "\n" 479 " || (this.$name$.equals($default$)\n" 480 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 481 } 482 printer->Print(") {\n" 483 " return false;\n" 484 "}\n"); 485 } else if (java_type == JAVATYPE_FLOAT) { 486 printer->Print(variables_, 487 "{\n" 488 " int bits = java.lang.Float.floatToIntBits(this.$name$);\n" 489 " if (bits != java.lang.Float.floatToIntBits(other.$name$)"); 490 if (params_.generate_has()) { 491 printer->Print(variables_, 492 "\n" 493 " || (bits == java.lang.Float.floatToIntBits($default$)\n" 494 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 495 } 496 printer->Print(") {\n" 497 " return false;\n" 498 " }\n" 499 "}\n"); 500 } else if (java_type == JAVATYPE_DOUBLE) { 501 printer->Print(variables_, 502 "{\n" 503 " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n" 504 " if (bits != java.lang.Double.doubleToLongBits(other.$name$)"); 505 if (params_.generate_has()) { 506 printer->Print(variables_, 507 "\n" 508 " || (bits == java.lang.Double.doubleToLongBits($default$)\n" 509 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 510 } 511 printer->Print(") {\n" 512 " return false;\n" 513 " }\n" 514 "}\n"); 515 } else { 516 printer->Print(variables_, 517 "if (this.$name$ != other.$name$"); 518 if (params_.generate_has()) { 519 printer->Print(variables_, 520 "\n" 521 " || (this.$name$ == $default$\n" 522 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 523 } 524 printer->Print(") {\n" 525 " return false;\n" 526 "}\n"); 527 } 528} 529 530void PrimitiveFieldGenerator:: 531GenerateHashCodeCode(io::Printer* printer) const { 532 JavaType java_type = GetJavaType(descriptor_); 533 if (java_type == JAVATYPE_BYTES) { 534 printer->Print(variables_, 535 "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n"); 536 } else if (java_type == JAVATYPE_STRING 537 || params_.use_reference_types_for_primitives()) { 538 printer->Print(variables_, 539 "result = 31 * result\n" 540 " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); 541 } else { 542 switch (java_type) { 543 // For all Java primitive types below, the hash codes match the 544 // results of BoxedType.valueOf(primitiveValue).hashCode(). 545 case JAVATYPE_INT: 546 printer->Print(variables_, 547 "result = 31 * result + this.$name$;\n"); 548 break; 549 case JAVATYPE_LONG: 550 printer->Print(variables_, 551 "result = 31 * result\n" 552 " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n"); 553 break; 554 case JAVATYPE_FLOAT: 555 printer->Print(variables_, 556 "result = 31 * result\n" 557 " + java.lang.Float.floatToIntBits(this.$name$);\n"); 558 break; 559 case JAVATYPE_DOUBLE: 560 printer->Print(variables_, 561 "{\n" 562 " long v = java.lang.Double.doubleToLongBits(this.$name$);\n" 563 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 564 "}\n"); 565 break; 566 case JAVATYPE_BOOLEAN: 567 printer->Print(variables_, 568 "result = 31 * result + (this.$name$ ? 1231 : 1237);\n"); 569 break; 570 default: 571 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 572 break; 573 } 574 } 575} 576 577// =================================================================== 578 579AccessorPrimitiveFieldGenerator:: 580AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, 581 const Params& params, int has_bit_index) 582 : FieldGenerator(params), descriptor_(descriptor) { 583 SetPrimitiveVariables(descriptor, params, &variables_); 584 SetBitOperationVariables("has", has_bit_index, &variables_); 585} 586 587AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} 588 589bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const { 590 return variables_.find("default_constant") != variables_.end(); 591} 592 593void AccessorPrimitiveFieldGenerator:: 594GenerateInitSavedDefaultCode(io::Printer* printer) const { 595 if (variables_.find("default_constant") != variables_.end()) { 596 printer->Print(variables_, 597 "$default_constant$ = $default_constant_value$;\n"); 598 } 599} 600 601void AccessorPrimitiveFieldGenerator:: 602GenerateMembers(io::Printer* printer, bool lazy_init) const { 603 if (variables_.find("default_constant") != variables_.end()) { 604 // Those primitive types that need a saved default. 605 if (lazy_init) { 606 printer->Print(variables_, 607 "private static $type$ $default_constant$;\n"); 608 } else { 609 printer->Print(variables_, 610 "private static final $type$ $default_constant$ =\n" 611 " $default_constant_value$;\n"); 612 } 613 } 614 printer->Print(variables_, 615 "private $type$ $name$_;\n" 616 "public $type$ get$capitalized_name$() {\n" 617 " return $name$_;\n" 618 "}\n" 619 "public $message_name$ set$capitalized_name$($type$ value) {\n"); 620 if (IsReferenceType(GetJavaType(descriptor_))) { 621 printer->Print(variables_, 622 " if (value == null) {\n" 623 " throw new java.lang.NullPointerException();\n" 624 " }\n"); 625 } 626 printer->Print(variables_, 627 " $name$_ = value;\n" 628 " $set_has$;\n" 629 " return this;\n" 630 "}\n" 631 "public boolean has$capitalized_name$() {\n" 632 " return $get_has$;\n" 633 "}\n" 634 "public $message_name$ clear$capitalized_name$() {\n" 635 " $name$_ = $default_copy_if_needed$;\n" 636 " $clear_has$;\n" 637 " return this;\n" 638 "}\n"); 639} 640 641void AccessorPrimitiveFieldGenerator:: 642GenerateClearCode(io::Printer* printer) const { 643 644 printer->Print(variables_, 645 "$name$_ = $default_copy_if_needed$;\n"); 646} 647 648void AccessorPrimitiveFieldGenerator:: 649GenerateMergingCode(io::Printer* printer) const { 650 printer->Print(variables_, 651 "$name$_ = input.read$capitalized_type$();\n" 652 "$set_has$;\n"); 653} 654 655void AccessorPrimitiveFieldGenerator:: 656GenerateSerializationCode(io::Printer* printer) const { 657 printer->Print(variables_, 658 "if ($get_has$) {\n" 659 " output.write$capitalized_type$($number$, $name$_);\n" 660 "}\n"); 661} 662 663void AccessorPrimitiveFieldGenerator:: 664GenerateSerializedSizeCode(io::Printer* printer) const { 665 printer->Print(variables_, 666 "if ($get_has$) {\n" 667 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 668 " .compute$capitalized_type$Size($number$, $name$_);\n" 669 "}\n"); 670} 671 672void AccessorPrimitiveFieldGenerator:: 673GenerateEqualsCode(io::Printer* printer) const { 674 switch (GetJavaType(descriptor_)) { 675 // For all Java primitive types below, the equality checks match the 676 // results of BoxedType.valueOf(primitiveValue).equals(otherValue). 677 case JAVATYPE_FLOAT: 678 printer->Print(variables_, 679 "if ($different_has$\n" 680 " || java.lang.Float.floatToIntBits($name$_)\n" 681 " != java.lang.Float.floatToIntBits(other.$name$_)) {\n" 682 " return false;\n" 683 "}\n"); 684 break; 685 case JAVATYPE_DOUBLE: 686 printer->Print(variables_, 687 "if ($different_has$\n" 688 " || java.lang.Double.doubleToLongBits($name$_)\n" 689 " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n" 690 " return false;\n" 691 "}\n"); 692 break; 693 case JAVATYPE_INT: 694 case JAVATYPE_LONG: 695 case JAVATYPE_BOOLEAN: 696 printer->Print(variables_, 697 "if ($different_has$\n" 698 " || $name$_ != other.$name$_) {\n" 699 " return false;\n" 700 "}\n"); 701 break; 702 case JAVATYPE_STRING: 703 // Accessor style would guarantee $name$_ non-null 704 printer->Print(variables_, 705 "if ($different_has$\n" 706 " || !$name$_.equals(other.$name$_)) {\n" 707 " return false;\n" 708 "}\n"); 709 break; 710 case JAVATYPE_BYTES: 711 // Accessor style would guarantee $name$_ non-null 712 printer->Print(variables_, 713 "if ($different_has$\n" 714 " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n" 715 " return false;\n" 716 "}\n"); 717 break; 718 default: 719 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 720 break; 721 } 722} 723 724void AccessorPrimitiveFieldGenerator:: 725GenerateHashCodeCode(io::Printer* printer) const { 726 switch (GetJavaType(descriptor_)) { 727 // For all Java primitive types below, the hash codes match the 728 // results of BoxedType.valueOf(primitiveValue).hashCode(). 729 case JAVATYPE_INT: 730 printer->Print(variables_, 731 "result = 31 * result + $name$_;\n"); 732 break; 733 case JAVATYPE_LONG: 734 printer->Print(variables_, 735 "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n"); 736 break; 737 case JAVATYPE_FLOAT: 738 printer->Print(variables_, 739 "result = 31 * result +\n" 740 " java.lang.Float.floatToIntBits($name$_);\n"); 741 break; 742 case JAVATYPE_DOUBLE: 743 printer->Print(variables_, 744 "{\n" 745 " long v = java.lang.Double.doubleToLongBits($name$_);\n" 746 " result = 31 * result + (int) (v ^ (v >>> 32));\n" 747 "}\n"); 748 break; 749 case JAVATYPE_BOOLEAN: 750 printer->Print(variables_, 751 "result = 31 * result + ($name$_ ? 1231 : 1237);\n"); 752 break; 753 case JAVATYPE_STRING: 754 // Accessor style would guarantee $name$_ non-null 755 printer->Print(variables_, 756 "result = 31 * result + $name$_.hashCode();\n"); 757 break; 758 case JAVATYPE_BYTES: 759 // Accessor style would guarantee $name$_ non-null 760 printer->Print(variables_, 761 "result = 31 * result + java.util.Arrays.hashCode($name$_);\n"); 762 break; 763 default: 764 GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; 765 break; 766 } 767} 768 769// =================================================================== 770 771RepeatedPrimitiveFieldGenerator:: 772RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 773 : FieldGenerator(params), descriptor_(descriptor) { 774 SetPrimitiveVariables(descriptor, params, &variables_); 775} 776 777RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 778 779void RepeatedPrimitiveFieldGenerator:: 780GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const { 781 printer->Print(variables_, 782 "public $type$[] $name$;\n"); 783} 784 785void RepeatedPrimitiveFieldGenerator:: 786GenerateClearCode(io::Printer* printer) const { 787 printer->Print(variables_, 788 "$name$ = $default$;\n"); 789} 790 791void RepeatedPrimitiveFieldGenerator:: 792GenerateMergingCode(io::Printer* printer) const { 793 // First, figure out the length of the array, then parse. 794 printer->Print(variables_, 795 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 796 " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n" 797 "int i = this.$name$ == null ? 0 : this.$name$.length;\n"); 798 799 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { 800 printer->Print(variables_, 801 "byte[][] newArray = new byte[i + arrayLength][];\n"); 802 } else { 803 printer->Print(variables_, 804 "$type$[] newArray = new $type$[i + arrayLength];\n"); 805 } 806 printer->Print(variables_, 807 "if (i != 0) {\n" 808 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 809 "}\n" 810 "for (; i < newArray.length - 1; i++) {\n" 811 " newArray[i] = input.read$capitalized_type$();\n" 812 " input.readTag();\n" 813 "}\n" 814 "// Last one without readTag.\n" 815 "newArray[i] = input.read$capitalized_type$();\n" 816 "this.$name$ = newArray;\n"); 817} 818 819void RepeatedPrimitiveFieldGenerator:: 820GenerateMergingCodeFromPacked(io::Printer* printer) const { 821 printer->Print( 822 "int length = input.readRawVarint32();\n" 823 "int limit = input.pushLimit(length);\n"); 824 825 // If we know the elements will all be of the same size, the arrayLength 826 // can be calculated much more easily. However, FixedSize() returns 1 for 827 // repeated bool fields, which are guaranteed to have the fixed size of 828 // 1 byte per value only if we control the output. On the wire they can 829 // legally appear as variable-size integers, so we need to use the slow 830 // way for repeated bool fields. 831 if (descriptor_->type() == FieldDescriptor::TYPE_BOOL 832 || FixedSize(descriptor_->type()) == -1) { 833 printer->Print(variables_, 834 "// First pass to compute array length.\n" 835 "int arrayLength = 0;\n" 836 "int startPos = input.getPosition();\n" 837 "while (input.getBytesUntilLimit() > 0) {\n" 838 " input.read$capitalized_type$();\n" 839 " arrayLength++;\n" 840 "}\n" 841 "input.rewindToPosition(startPos);\n"); 842 } else { 843 printer->Print(variables_, 844 "int arrayLength = length / $fixed_size$;\n"); 845 } 846 847 printer->Print(variables_, 848 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 849 "$type$[] newArray = new $type$[i + arrayLength];\n" 850 "if (i != 0) {\n" 851 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 852 "}\n" 853 "for (; i < newArray.length; i++) {\n" 854 " newArray[i] = input.read$capitalized_type$();\n" 855 "}\n" 856 "this.$name$ = newArray;\n" 857 "input.popLimit(limit);\n"); 858} 859 860void RepeatedPrimitiveFieldGenerator:: 861GenerateRepeatedDataSizeCode(io::Printer* printer) const { 862 // Creates a variable dataSize and puts the serialized size in there. 863 // If the element type is a Java reference type, also generates 864 // dataCount which stores the number of non-null elements in the field. 865 if (IsReferenceType(GetJavaType(descriptor_))) { 866 printer->Print(variables_, 867 "int dataCount = 0;\n" 868 "int dataSize = 0;\n" 869 "for (int i = 0; i < this.$name$.length; i++) {\n" 870 " $type$ element = this.$name$[i];\n" 871 " if (element != null) {\n" 872 " dataCount++;\n" 873 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 874 " .compute$capitalized_type$SizeNoTag(element);\n" 875 " }\n" 876 "}\n"); 877 } else if (FixedSize(descriptor_->type()) == -1) { 878 printer->Print(variables_, 879 "int dataSize = 0;\n" 880 "for (int i = 0; i < this.$name$.length; i++) {\n" 881 " $type$ element = this.$name$[i];\n" 882 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 883 " .compute$capitalized_type$SizeNoTag(element);\n" 884 "}\n"); 885 } else { 886 printer->Print(variables_, 887 "int dataSize = $fixed_size$ * this.$name$.length;\n"); 888 } 889} 890 891void RepeatedPrimitiveFieldGenerator:: 892GenerateSerializationCode(io::Printer* printer) const { 893 printer->Print(variables_, 894 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 895 printer->Indent(); 896 897 if (descriptor_->is_packable() && descriptor_->options().packed()) { 898 GenerateRepeatedDataSizeCode(printer); 899 printer->Print(variables_, 900 "output.writeRawVarint32($tag$);\n" 901 "output.writeRawVarint32(dataSize);\n" 902 "for (int i = 0; i < this.$name$.length; i++) {\n" 903 " output.write$capitalized_type$NoTag(this.$name$[i]);\n" 904 "}\n"); 905 } else if (IsReferenceType(GetJavaType(descriptor_))) { 906 printer->Print(variables_, 907 "for (int i = 0; i < this.$name$.length; i++) {\n" 908 " $type$ element = this.$name$[i];\n" 909 " if (element != null) {\n" 910 " output.write$capitalized_type$($number$, element);\n" 911 " }\n" 912 "}\n"); 913 } else { 914 printer->Print(variables_, 915 "for (int i = 0; i < this.$name$.length; i++) {\n" 916 " output.write$capitalized_type$($number$, this.$name$[i]);\n" 917 "}\n"); 918 } 919 920 printer->Outdent(); 921 printer->Print("}\n"); 922} 923 924void RepeatedPrimitiveFieldGenerator:: 925GenerateSerializedSizeCode(io::Printer* printer) const { 926 printer->Print(variables_, 927 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 928 printer->Indent(); 929 930 GenerateRepeatedDataSizeCode(printer); 931 932 printer->Print( 933 "size += dataSize;\n"); 934 if (descriptor_->is_packable() && descriptor_->options().packed()) { 935 printer->Print(variables_, 936 "size += $tag_size$;\n" 937 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 938 " .computeRawVarint32Size(dataSize);\n"); 939 } else if (IsReferenceType(GetJavaType(descriptor_))) { 940 printer->Print(variables_, 941 "size += $tag_size$ * dataCount;\n"); 942 } else { 943 printer->Print(variables_, 944 "size += $tag_size$ * this.$name$.length;\n"); 945 } 946 947 printer->Outdent(); 948 949 printer->Print( 950 "}\n"); 951} 952 953void RepeatedPrimitiveFieldGenerator:: 954GenerateEqualsCode(io::Printer* printer) const { 955 printer->Print(variables_, 956 "if (!com.google.protobuf.nano.InternalNano.equals(\n" 957 " this.$name$, other.$name$)) {\n" 958 " return false;\n" 959 "}\n"); 960} 961 962void RepeatedPrimitiveFieldGenerator:: 963GenerateHashCodeCode(io::Printer* printer) const { 964 printer->Print(variables_, 965 "result = 31 * result\n" 966 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); 967} 968 969} // namespace javanano 970} // namespace compiler 971} // namespace protobuf 972} // namespace google 973