java_primitive_field.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
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 <string> 37 38#include <google/protobuf/compiler/java/java_primitive_field.h> 39#include <google/protobuf/stubs/common.h> 40#include <google/protobuf/compiler/java/java_helpers.h> 41#include <google/protobuf/io/printer.h> 42#include <google/protobuf/wire_format.h> 43#include <google/protobuf/stubs/strutil.h> 44 45namespace google { 46namespace protobuf { 47namespace compiler { 48namespace java { 49 50using internal::WireFormat; 51using internal::WireFormatLite; 52 53namespace { 54 55const char* PrimitiveTypeName(JavaType type) { 56 switch (type) { 57 case JAVATYPE_INT : return "int"; 58 case JAVATYPE_LONG : return "long"; 59 case JAVATYPE_FLOAT : return "float"; 60 case JAVATYPE_DOUBLE : return "double"; 61 case JAVATYPE_BOOLEAN: return "boolean"; 62 case JAVATYPE_STRING : return "java.lang.String"; 63 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; 64 case JAVATYPE_ENUM : return NULL; 65 case JAVATYPE_MESSAGE: return NULL; 66 67 // No default because we want the compiler to complain if any new 68 // JavaTypes are added. 69 } 70 71 GOOGLE_LOG(FATAL) << "Can't get here."; 72 return NULL; 73} 74 75bool IsReferenceType(JavaType type) { 76 switch (type) { 77 case JAVATYPE_INT : return false; 78 case JAVATYPE_LONG : return false; 79 case JAVATYPE_FLOAT : return false; 80 case JAVATYPE_DOUBLE : return false; 81 case JAVATYPE_BOOLEAN: return false; 82 case JAVATYPE_STRING : return true; 83 case JAVATYPE_BYTES : return true; 84 case JAVATYPE_ENUM : return true; 85 case JAVATYPE_MESSAGE: return true; 86 87 // No default because we want the compiler to complain if any new 88 // JavaTypes are added. 89 } 90 91 GOOGLE_LOG(FATAL) << "Can't get here."; 92 return false; 93} 94 95const char* GetCapitalizedType(const FieldDescriptor* field) { 96 switch (field->type()) { 97 case FieldDescriptor::TYPE_INT32 : return "Int32" ; 98 case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; 99 case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; 100 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; 101 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; 102 case FieldDescriptor::TYPE_INT64 : return "Int64" ; 103 case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; 104 case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; 105 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; 106 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; 107 case FieldDescriptor::TYPE_FLOAT : return "Float" ; 108 case FieldDescriptor::TYPE_DOUBLE : return "Double" ; 109 case FieldDescriptor::TYPE_BOOL : return "Bool" ; 110 case FieldDescriptor::TYPE_STRING : return "String" ; 111 case FieldDescriptor::TYPE_BYTES : return "Bytes" ; 112 case FieldDescriptor::TYPE_ENUM : return "Enum" ; 113 case FieldDescriptor::TYPE_GROUP : return "Group" ; 114 case FieldDescriptor::TYPE_MESSAGE : return "Message" ; 115 116 // No default because we want the compiler to complain if any new 117 // types are added. 118 } 119 120 GOOGLE_LOG(FATAL) << "Can't get here."; 121 return NULL; 122} 123 124// For encodings with fixed sizes, returns that size in bytes. Otherwise 125// returns -1. 126int FixedSize(FieldDescriptor::Type type) { 127 switch (type) { 128 case FieldDescriptor::TYPE_INT32 : return -1; 129 case FieldDescriptor::TYPE_INT64 : return -1; 130 case FieldDescriptor::TYPE_UINT32 : return -1; 131 case FieldDescriptor::TYPE_UINT64 : return -1; 132 case FieldDescriptor::TYPE_SINT32 : return -1; 133 case FieldDescriptor::TYPE_SINT64 : return -1; 134 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; 135 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; 136 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; 137 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; 138 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; 139 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; 140 141 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; 142 case FieldDescriptor::TYPE_ENUM : return -1; 143 144 case FieldDescriptor::TYPE_STRING : return -1; 145 case FieldDescriptor::TYPE_BYTES : return -1; 146 case FieldDescriptor::TYPE_GROUP : return -1; 147 case FieldDescriptor::TYPE_MESSAGE : return -1; 148 149 // No default because we want the compiler to complain if any new 150 // types are added. 151 } 152 GOOGLE_LOG(FATAL) << "Can't get here."; 153 return -1; 154} 155 156void SetPrimitiveVariables(const FieldDescriptor* descriptor, 157 map<string, string>* variables) { 158 (*variables)["name"] = 159 UnderscoresToCamelCase(descriptor); 160 (*variables)["capitalized_name"] = 161 UnderscoresToCapitalizedCamelCase(descriptor); 162 (*variables)["number"] = SimpleItoa(descriptor->number()); 163 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); 164 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); 165 (*variables)["default"] = DefaultValue(descriptor); 166 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); 167 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 168 (*variables)["tag_size"] = SimpleItoa( 169 WireFormat::TagSize(descriptor->number(), descriptor->type())); 170 if (IsReferenceType(GetJavaType(descriptor))) { 171 (*variables)["null_check"] = 172 " if (value == null) {\n" 173 " throw new NullPointerException();\n" 174 " }\n"; 175 } else { 176 (*variables)["null_check"] = ""; 177 } 178 int fixed_size = FixedSize(descriptor->type()); 179 if (fixed_size != -1) { 180 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 181 } 182} 183} // namespace 184 185// =================================================================== 186 187PrimitiveFieldGenerator:: 188PrimitiveFieldGenerator(const FieldDescriptor* descriptor) 189 : descriptor_(descriptor) { 190 SetPrimitiveVariables(descriptor, &variables_); 191} 192 193PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 194 195void PrimitiveFieldGenerator:: 196GenerateMembers(io::Printer* printer) const { 197 printer->Print(variables_, 198 "private boolean has$capitalized_name$;\n" 199 "private $type$ $name$_ = $default$;\n" 200 "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" 201 "public $type$ get$capitalized_name$() { return $name$_; }\n"); 202} 203 204void PrimitiveFieldGenerator:: 205GenerateBuilderMembers(io::Printer* printer) const { 206 printer->Print(variables_, 207 "public boolean has$capitalized_name$() {\n" 208 " return result.has$capitalized_name$();\n" 209 "}\n" 210 "public $type$ get$capitalized_name$() {\n" 211 " return result.get$capitalized_name$();\n" 212 "}\n" 213 "public Builder set$capitalized_name$($type$ value) {\n" 214 "$null_check$" 215 " result.has$capitalized_name$ = true;\n" 216 " result.$name$_ = value;\n" 217 " return this;\n" 218 "}\n" 219 "public Builder clear$capitalized_name$() {\n" 220 " result.has$capitalized_name$ = false;\n"); 221 if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { 222 // The default value is not a simple literal so we want to avoid executing 223 // it multiple times. Instead, get the default out of the default instance. 224 printer->Print(variables_, 225 " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); 226 } else { 227 printer->Print(variables_, 228 " result.$name$_ = $default$;\n"); 229 } 230 printer->Print(variables_, 231 " return this;\n" 232 "}\n"); 233} 234 235void PrimitiveFieldGenerator:: 236GenerateMergingCode(io::Printer* printer) const { 237 printer->Print(variables_, 238 "if (other.has$capitalized_name$()) {\n" 239 " set$capitalized_name$(other.get$capitalized_name$());\n" 240 "}\n"); 241} 242 243void PrimitiveFieldGenerator:: 244GenerateBuildingCode(io::Printer* printer) const { 245 // Nothing to do here for primitive types. 246} 247 248void PrimitiveFieldGenerator:: 249GenerateParsingCode(io::Printer* printer) const { 250 printer->Print(variables_, 251 "set$capitalized_name$(input.read$capitalized_type$());\n"); 252} 253 254void PrimitiveFieldGenerator:: 255GenerateSerializationCode(io::Printer* printer) const { 256 printer->Print(variables_, 257 "if (has$capitalized_name$()) {\n" 258 " output.write$capitalized_type$($number$, get$capitalized_name$());\n" 259 "}\n"); 260} 261 262void PrimitiveFieldGenerator:: 263GenerateSerializedSizeCode(io::Printer* printer) const { 264 printer->Print(variables_, 265 "if (has$capitalized_name$()) {\n" 266 " size += com.google.protobuf.CodedOutputStream\n" 267 " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" 268 "}\n"); 269} 270 271string PrimitiveFieldGenerator::GetBoxedType() const { 272 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 273} 274 275// =================================================================== 276 277RepeatedPrimitiveFieldGenerator:: 278RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) 279 : descriptor_(descriptor) { 280 SetPrimitiveVariables(descriptor, &variables_); 281} 282 283RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 284 285void RepeatedPrimitiveFieldGenerator:: 286GenerateMembers(io::Printer* printer) const { 287 printer->Print(variables_, 288 "private java.util.List<$boxed_type$> $name$_ =\n" 289 " java.util.Collections.emptyList();\n" 290 "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" 291 " return $name$_;\n" // note: unmodifiable list 292 "}\n" 293 "public int get$capitalized_name$Count() { return $name$_.size(); }\n" 294 "public $type$ get$capitalized_name$(int index) {\n" 295 " return $name$_.get(index);\n" 296 "}\n"); 297 298 if (descriptor_->options().packed() && 299 HasGeneratedMethods(descriptor_->containing_type())) { 300 printer->Print(variables_, 301 "private int $name$MemoizedSerializedSize;\n"); 302 } 303} 304 305void RepeatedPrimitiveFieldGenerator:: 306GenerateBuilderMembers(io::Printer* printer) const { 307 printer->Print(variables_, 308 // Note: We return an unmodifiable list because otherwise the caller 309 // could hold on to the returned list and modify it after the message 310 // has been built, thus mutating the message which is supposed to be 311 // immutable. 312 "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" 313 " return java.util.Collections.unmodifiableList(result.$name$_);\n" 314 "}\n" 315 "public int get$capitalized_name$Count() {\n" 316 " return result.get$capitalized_name$Count();\n" 317 "}\n" 318 "public $type$ get$capitalized_name$(int index) {\n" 319 " return result.get$capitalized_name$(index);\n" 320 "}\n" 321 "public Builder set$capitalized_name$(int index, $type$ value) {\n" 322 "$null_check$" 323 " result.$name$_.set(index, value);\n" 324 " return this;\n" 325 "}\n" 326 "public Builder add$capitalized_name$($type$ value) {\n" 327 "$null_check$" 328 " if (result.$name$_.isEmpty()) {\n" 329 " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" 330 " }\n" 331 " result.$name$_.add(value);\n" 332 " return this;\n" 333 "}\n" 334 "public Builder addAll$capitalized_name$(\n" 335 " java.lang.Iterable<? extends $boxed_type$> values) {\n" 336 " if (result.$name$_.isEmpty()) {\n" 337 " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" 338 " }\n" 339 " super.addAll(values, result.$name$_);\n" 340 " return this;\n" 341 "}\n" 342 "public Builder clear$capitalized_name$() {\n" 343 " result.$name$_ = java.util.Collections.emptyList();\n" 344 " return this;\n" 345 "}\n"); 346} 347 348void RepeatedPrimitiveFieldGenerator:: 349GenerateMergingCode(io::Printer* printer) const { 350 printer->Print(variables_, 351 "if (!other.$name$_.isEmpty()) {\n" 352 " if (result.$name$_.isEmpty()) {\n" 353 " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" 354 " }\n" 355 " result.$name$_.addAll(other.$name$_);\n" 356 "}\n"); 357} 358 359void RepeatedPrimitiveFieldGenerator:: 360GenerateBuildingCode(io::Printer* printer) const { 361 printer->Print(variables_, 362 "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" 363 " result.$name$_ =\n" 364 " java.util.Collections.unmodifiableList(result.$name$_);\n" 365 "}\n"); 366} 367 368void RepeatedPrimitiveFieldGenerator:: 369GenerateParsingCode(io::Printer* printer) const { 370 if (descriptor_->options().packed()) { 371 printer->Print(variables_, 372 "int length = input.readRawVarint32();\n" 373 "int limit = input.pushLimit(length);\n" 374 "while (input.getBytesUntilLimit() > 0) {\n" 375 " add$capitalized_name$(input.read$capitalized_type$());\n" 376 "}\n" 377 "input.popLimit(limit);\n"); 378 } else { 379 printer->Print(variables_, 380 "add$capitalized_name$(input.read$capitalized_type$());\n"); 381 } 382} 383 384void RepeatedPrimitiveFieldGenerator:: 385GenerateSerializationCode(io::Printer* printer) const { 386 if (descriptor_->options().packed()) { 387 printer->Print(variables_, 388 "if (get$capitalized_name$List().size() > 0) {\n" 389 " output.writeRawVarint32($tag$);\n" 390 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 391 "}\n" 392 "for ($type$ element : get$capitalized_name$List()) {\n" 393 " output.write$capitalized_type$NoTag(element);\n" 394 "}\n"); 395 } else { 396 printer->Print(variables_, 397 "for ($type$ element : get$capitalized_name$List()) {\n" 398 " output.write$capitalized_type$($number$, element);\n" 399 "}\n"); 400 } 401} 402 403void RepeatedPrimitiveFieldGenerator:: 404GenerateSerializedSizeCode(io::Printer* printer) const { 405 printer->Print(variables_, 406 "{\n" 407 " int dataSize = 0;\n"); 408 printer->Indent(); 409 410 if (FixedSize(descriptor_->type()) == -1) { 411 printer->Print(variables_, 412 "for ($type$ element : get$capitalized_name$List()) {\n" 413 " dataSize += com.google.protobuf.CodedOutputStream\n" 414 " .compute$capitalized_type$SizeNoTag(element);\n" 415 "}\n"); 416 } else { 417 printer->Print(variables_, 418 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); 419 } 420 421 printer->Print( 422 "size += dataSize;\n"); 423 424 if (descriptor_->options().packed()) { 425 printer->Print(variables_, 426 "if (!get$capitalized_name$List().isEmpty()) {\n" 427 " size += $tag_size$;\n" 428 " size += com.google.protobuf.CodedOutputStream\n" 429 " .computeInt32SizeNoTag(dataSize);\n" 430 "}\n"); 431 } else { 432 printer->Print(variables_, 433 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 434 } 435 436 // cache the data size for packed fields. 437 if (descriptor_->options().packed()) { 438 printer->Print(variables_, 439 "$name$MemoizedSerializedSize = dataSize;\n"); 440 } 441 442 printer->Outdent(); 443 printer->Print("}\n"); 444} 445 446string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { 447 return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); 448} 449 450} // namespace java 451} // namespace compiler 452} // namespace protobuf 453} // namespace google 454