javanano_enum_field.cc revision f84177299a76759be1eb925093b059aef246fc0e
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/javanano/javanano_enum_field.h> 39#include <google/protobuf/stubs/common.h> 40#include <google/protobuf/compiler/javanano/javanano_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 javanano { 49 50namespace { 51 52// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of 53// repeat code between this and the other field types. 54void SetEnumVariables(const Params& params, 55 const FieldDescriptor* descriptor, map<string, string>* variables) { 56 (*variables)["name"] = 57 RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); 58 (*variables)["capitalized_name"] = 59 RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); 60 (*variables)["number"] = SimpleItoa(descriptor->number()); 61 if (params.use_reference_types_for_primitives() 62 && !descriptor->is_repeated()) { 63 (*variables)["type"] = "java.lang.Integer"; 64 (*variables)["default"] = "null"; 65 } else { 66 (*variables)["type"] = "int"; 67 (*variables)["default"] = DefaultValue(params, descriptor); 68 } 69 (*variables)["repeated_default"] = 70 "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; 71 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); 72 (*variables)["tag_size"] = SimpleItoa( 73 internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); 74 (*variables)["message_name"] = descriptor->containing_type()->name(); 75} 76 77} // namespace 78 79// =================================================================== 80 81EnumFieldGenerator:: 82EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 83 : FieldGenerator(params), descriptor_(descriptor) { 84 SetEnumVariables(params, descriptor, &variables_); 85} 86 87EnumFieldGenerator::~EnumFieldGenerator() {} 88 89void EnumFieldGenerator:: 90GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 91 printer->Print(variables_, 92 "public $type$ $name$;\n"); 93 94 if (params_.generate_has()) { 95 printer->Print(variables_, 96 "public boolean has$capitalized_name$;\n"); 97 } 98} 99 100void EnumFieldGenerator:: 101GenerateClearCode(io::Printer* printer) const { 102 printer->Print(variables_, 103 "$name$ = $default$;\n"); 104 105 if (params_.generate_has()) { 106 printer->Print(variables_, 107 "has$capitalized_name$ = false;\n"); 108 } 109} 110 111void EnumFieldGenerator:: 112GenerateMergingCode(io::Printer* printer) const { 113 printer->Print(variables_, 114 "this.$name$ = input.readInt32();\n"); 115 116 if (params_.generate_has()) { 117 printer->Print(variables_, 118 "has$capitalized_name$ = true;\n"); 119 } 120} 121 122void EnumFieldGenerator:: 123GenerateSerializationCode(io::Printer* printer) const { 124 if (descriptor_->is_required() && !params_.generate_has()) { 125 // Always serialize a required field if we don't have the 'has' signal. 126 printer->Print(variables_, 127 "output.writeInt32($number$, this.$name$);\n"); 128 } else { 129 if (params_.generate_has()) { 130 printer->Print(variables_, 131 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 132 } else { 133 printer->Print(variables_, 134 "if (this.$name$ != $default$) {\n"); 135 } 136 printer->Print(variables_, 137 " output.writeInt32($number$, this.$name$);\n" 138 "}\n"); 139 } 140} 141 142void EnumFieldGenerator:: 143GenerateSerializedSizeCode(io::Printer* printer) const { 144 if (descriptor_->is_required() && !params_.generate_has()) { 145 printer->Print(variables_, 146 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 147 " .computeInt32Size($number$, this.$name$);\n"); 148 } else { 149 if (params_.generate_has()) { 150 printer->Print(variables_, 151 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 152 } else { 153 printer->Print(variables_, 154 "if (this.$name$ != $default$) {\n"); 155 } 156 printer->Print(variables_, 157 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 158 " .computeInt32Size($number$, this.$name$);\n" 159 "}\n"); 160 } 161} 162 163void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { 164 if (params_.use_reference_types_for_primitives()) { 165 printer->Print(variables_, 166 "if (this.$name$ == null) {\n" 167 " if (other.$name$ != null) {\n" 168 " return false;\n" 169 " }\n" 170 "} else if (!this.$name$.equals(other.$name$)) {\n" 171 " return false;" 172 "}\n"); 173 } else { 174 // We define equality as serialized form equality. If generate_has(), 175 // then if the field value equals the default value in both messages, 176 // but one's 'has' field is set and the other's is not, the serialized 177 // forms are different and we should return false. 178 printer->Print(variables_, 179 "if (this.$name$ != other.$name$"); 180 if (params_.generate_has()) { 181 printer->Print(variables_, 182 "\n" 183 " || (this.$name$ == $default$\n" 184 " && this.has$capitalized_name$ != other.has$capitalized_name$)"); 185 } 186 printer->Print(") {\n" 187 " return false;\n" 188 "}\n"); 189 } 190} 191 192void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const { 193 printer->Print( 194 "result = 31 * result + "); 195 if (params_.use_reference_types_for_primitives()) { 196 printer->Print(variables_, 197 "(this.$name$ == null ? 0 : this.$name$)"); 198 } else { 199 printer->Print(variables_, 200 "this.$name$"); 201 } 202 printer->Print(";\n"); 203} 204 205// =================================================================== 206 207AccessorEnumFieldGenerator:: 208AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, 209 const Params& params, int has_bit_index) 210 : FieldGenerator(params), descriptor_(descriptor) { 211 SetEnumVariables(params, descriptor, &variables_); 212 SetBitOperationVariables("has", has_bit_index, &variables_); 213} 214 215AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} 216 217void AccessorEnumFieldGenerator:: 218GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 219 printer->Print(variables_, 220 "private int $name$_;\n" 221 "public int get$capitalized_name$() {\n" 222 " return $name$_;\n" 223 "}\n" 224 "public $message_name$ set$capitalized_name$(int value) {\n" 225 " $name$_ = value;\n" 226 " $set_has$;\n" 227 " return this;\n" 228 "}\n" 229 "public boolean has$capitalized_name$() {\n" 230 " return $get_has$;\n" 231 "}\n" 232 "public $message_name$ clear$capitalized_name$() {\n" 233 " $name$_ = $default$;\n" 234 " $clear_has$;\n" 235 " return this;\n" 236 "}\n"); 237} 238 239void AccessorEnumFieldGenerator:: 240GenerateClearCode(io::Printer* printer) const { 241 printer->Print(variables_, 242 "$name$_ = $default$;\n"); 243} 244 245void AccessorEnumFieldGenerator:: 246GenerateMergingCode(io::Printer* printer) const { 247 printer->Print(variables_, 248 "$name$_ = input.readInt32();\n" 249 "$set_has$;\n"); 250} 251 252void AccessorEnumFieldGenerator:: 253GenerateSerializationCode(io::Printer* printer) const { 254 printer->Print(variables_, 255 "if ($get_has$) {\n" 256 " output.writeInt32($number$, $name$_);\n" 257 "}\n"); 258} 259 260void AccessorEnumFieldGenerator:: 261GenerateSerializedSizeCode(io::Printer* printer) const { 262 printer->Print(variables_, 263 "if ($get_has$) {\n" 264 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 265 " .computeInt32Size($number$, $name$_);\n" 266 "}\n"); 267} 268 269void AccessorEnumFieldGenerator:: 270GenerateEqualsCode(io::Printer* printer) const { 271 printer->Print(variables_, 272 "if ($different_has$\n" 273 " || $name$_ != other.$name$_) {\n" 274 " return false;\n" 275 "}\n"); 276} 277 278void AccessorEnumFieldGenerator:: 279GenerateHashCodeCode(io::Printer* printer) const { 280 printer->Print(variables_, 281 "result = 31 * result + $name$_;\n"); 282} 283 284// =================================================================== 285 286RepeatedEnumFieldGenerator:: 287RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 288 : FieldGenerator(params), descriptor_(descriptor) { 289 SetEnumVariables(params, descriptor, &variables_); 290} 291 292RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 293 294void RepeatedEnumFieldGenerator:: 295GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 296 printer->Print(variables_, 297 "public $type$[] $name$;\n"); 298} 299 300void RepeatedEnumFieldGenerator:: 301GenerateClearCode(io::Printer* printer) const { 302 printer->Print(variables_, 303 "$name$ = $repeated_default$;\n"); 304} 305 306void RepeatedEnumFieldGenerator:: 307GenerateMergingCode(io::Printer* printer) const { 308 // First, figure out the length of the array, then parse. 309 printer->Print(variables_, 310 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 311 " .getRepeatedFieldArrayLength(input, $tag$);\n" 312 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 313 "int[] newArray = new int[i + arrayLength];\n" 314 "if (i != 0) {\n" 315 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 316 "}\n" 317 "for (; i < newArray.length - 1; i++) {\n" 318 " newArray[i] = input.readInt32();\n" 319 " input.readTag();\n" 320 "}\n" 321 "// Last one without readTag.\n" 322 "newArray[i] = input.readInt32();\n" 323 "this.$name$ = newArray;\n"); 324} 325 326void RepeatedEnumFieldGenerator:: 327GenerateMergingCodeFromPacked(io::Printer* printer) const { 328 printer->Print(variables_, 329 "int length = input.readRawVarint32();\n" 330 "int limit = input.pushLimit(length);\n" 331 "// First pass to compute array length.\n" 332 "int arrayLength = 0;\n" 333 "int startPos = input.getPosition();\n" 334 "while (input.getBytesUntilLimit() > 0) {\n" 335 " input.readInt32();\n" 336 " arrayLength++;\n" 337 "}\n" 338 "input.rewindToPosition(startPos);\n" 339 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 340 "int[] newArray = new int[i + arrayLength];\n" 341 "if (i != 0) {\n" 342 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 343 "}\n" 344 "for (; i < newArray.length; i++) {\n" 345 " newArray[i] = input.readInt32();\n" 346 "}\n" 347 "this.$name$ = newArray;\n" 348 "input.popLimit(limit);\n"); 349} 350 351void RepeatedEnumFieldGenerator:: 352GenerateRepeatedDataSizeCode(io::Printer* printer) const { 353 // Creates a variable dataSize and puts the serialized size in there. 354 printer->Print(variables_, 355 "int dataSize = 0;\n" 356 "for (int i = 0; i < this.$name$.length; i++) {\n" 357 " int element = this.$name$[i];\n" 358 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 359 " .computeInt32SizeNoTag(element);\n" 360 "}\n"); 361} 362 363void RepeatedEnumFieldGenerator:: 364GenerateSerializationCode(io::Printer* printer) const { 365 printer->Print(variables_, 366 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 367 printer->Indent(); 368 369 if (descriptor_->options().packed()) { 370 GenerateRepeatedDataSizeCode(printer); 371 printer->Print(variables_, 372 "output.writeRawVarint32($tag$);\n" 373 "output.writeRawVarint32(dataSize);\n" 374 "for (int i = 0; i < this.$name$.length; i++) {\n" 375 " output.writeRawVarint32(this.$name$[i]);\n" 376 "}\n"); 377 } else { 378 printer->Print(variables_, 379 "for (int i = 0; i < this.$name$.length; i++) {\n" 380 " output.writeInt32($number$, this.$name$[i]);\n" 381 "}\n"); 382 } 383 384 printer->Outdent(); 385 printer->Print(variables_, 386 "}\n"); 387} 388 389void RepeatedEnumFieldGenerator:: 390GenerateSerializedSizeCode(io::Printer* printer) const { 391 printer->Print(variables_, 392 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 393 printer->Indent(); 394 395 GenerateRepeatedDataSizeCode(printer); 396 397 printer->Print( 398 "size += dataSize;\n"); 399 if (descriptor_->options().packed()) { 400 printer->Print(variables_, 401 "size += $tag_size$;\n" 402 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 403 " .computeRawVarint32Size(dataSize);\n"); 404 } else { 405 printer->Print(variables_, 406 "size += $tag_size$ * this.$name$.length;\n"); 407 } 408 409 printer->Outdent(); 410 411 printer->Print( 412 "}\n"); 413} 414 415void RepeatedEnumFieldGenerator:: 416GenerateEqualsCode(io::Printer* printer) const { 417 printer->Print(variables_, 418 "if (!com.google.protobuf.nano.InternalNano.equals(\n" 419 " this.$name$, other.$name$)) {\n" 420 " return false;\n" 421 "}\n"); 422} 423 424void RepeatedEnumFieldGenerator:: 425GenerateHashCodeCode(io::Printer* printer) const { 426 printer->Print(variables_, 427 "result = 31 * result\n" 428 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); 429} 430 431} // namespace javanano 432} // namespace compiler 433} // namespace protobuf 434} // namespace google 435