javanano_enum_field.cc revision 286271f75aa6ff1f3746379b77d6dc55415baa16
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) 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()) { 125 printer->Print(variables_, 126 "output.writeInt32($number$, this.$name$);\n"); 127 } else { 128 if (params_.generate_has()) { 129 printer->Print(variables_, 130 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 131 } else { 132 printer->Print(variables_, 133 "if (this.$name$ != $default$) {\n"); 134 } 135 printer->Print(variables_, 136 " output.writeInt32($number$, this.$name$);\n" 137 "}\n"); 138 } 139} 140 141void EnumFieldGenerator:: 142GenerateSerializedSizeCode(io::Printer* printer) const { 143 if (descriptor_->is_required()) { 144 printer->Print(variables_, 145 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 146 " .computeInt32Size($number$, this.$name$);\n"); 147 } else { 148 if (params_.generate_has()) { 149 printer->Print(variables_, 150 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 151 } else { 152 printer->Print(variables_, 153 "if (this.$name$ != $default$) {\n"); 154 } 155 printer->Print(variables_, 156 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 157 " .computeInt32Size($number$, this.$name$);\n" 158 "}\n"); 159 } 160} 161 162string EnumFieldGenerator::GetBoxedType() const { 163 return ClassName(params_, descriptor_->enum_type()); 164} 165 166// =================================================================== 167 168AccessorEnumFieldGenerator:: 169AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, 170 const Params& params, int has_bit_index) 171 : FieldGenerator(params), descriptor_(descriptor) { 172 SetEnumVariables(params, descriptor, &variables_); 173 SetBitOperationVariables("has", has_bit_index, &variables_); 174} 175 176AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} 177 178void AccessorEnumFieldGenerator:: 179GenerateMembers(io::Printer* printer) const { 180 printer->Print(variables_, 181 "private int $name$_;\n" 182 "public int get$capitalized_name$() {\n" 183 " return $name$_;\n" 184 "}\n" 185 "public void set$capitalized_name$(int value) {\n" 186 " $name$_ = value;\n" 187 " $set_has$;\n" 188 "}\n" 189 "public boolean has$capitalized_name$() {\n" 190 " return $get_has$;\n" 191 "}\n" 192 "public void clear$capitalized_name$() {\n" 193 " $name$_ = $default$;\n" 194 " $clear_has$;\n" 195 "}\n"); 196} 197 198void AccessorEnumFieldGenerator:: 199GenerateClearCode(io::Printer* printer) const { 200 printer->Print(variables_, 201 "$name$_ = $default$;\n"); 202} 203 204void AccessorEnumFieldGenerator:: 205GenerateMergingCode(io::Printer* printer) const { 206 printer->Print(variables_, 207 "set$capitalized_name$(input.readInt32());\n"); 208} 209 210void AccessorEnumFieldGenerator:: 211GenerateSerializationCode(io::Printer* printer) const { 212 printer->Print(variables_, 213 "if (has$capitalized_name$()) {\n" 214 " output.writeInt32($number$, $name$_);\n" 215 "}\n"); 216} 217 218void AccessorEnumFieldGenerator:: 219GenerateSerializedSizeCode(io::Printer* printer) const { 220 printer->Print(variables_, 221 "if (has$capitalized_name$()) {\n" 222 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 223 " .computeInt32Size($number$, $name$_);\n" 224 "}\n"); 225} 226 227string AccessorEnumFieldGenerator::GetBoxedType() const { 228 return ClassName(params_, descriptor_->enum_type()); 229} 230 231// =================================================================== 232 233RepeatedEnumFieldGenerator:: 234RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 235 : FieldGenerator(params), descriptor_(descriptor) { 236 SetEnumVariables(params, descriptor, &variables_); 237} 238 239RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 240 241void RepeatedEnumFieldGenerator:: 242GenerateMembers(io::Printer* printer) const { 243 printer->Print(variables_, 244 "public $type$[] $name$;\n"); 245 if (descriptor_->options().packed()) { 246 printer->Print(variables_, 247 "private int $name$MemoizedSerializedSize;\n"); 248 } 249} 250 251void RepeatedEnumFieldGenerator:: 252GenerateClearCode(io::Printer* printer) const { 253 printer->Print(variables_, 254 "$name$ = $repeated_default$;\n"); 255} 256 257void RepeatedEnumFieldGenerator:: 258GenerateMergingCode(io::Printer* printer) const { 259 // First, figure out the length of the array, then parse. 260 if (descriptor_->options().packed()) { 261 printer->Print(variables_, 262 "int length = input.readRawVarint32();\n" 263 "int limit = input.pushLimit(length);\n" 264 "// First pass to compute array length.\n" 265 "int arrayLength = 0;\n" 266 "int startPos = input.getPosition();\n" 267 "while (input.getBytesUntilLimit() > 0) {\n" 268 " input.readInt32();\n" 269 " arrayLength++;\n" 270 "}\n" 271 "input.rewindToPosition(startPos);\n" 272 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 273 "int[] newArray = new int[i + arrayLength];\n" 274 "if (i != 0) {\n" 275 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 276 "}\n" 277 "for (; i < newArray.length; i++) {\n" 278 " newArray[i] = input.readInt32();\n" 279 "}\n" 280 "this.$name$ = newArray;\n" 281 "input.popLimit(limit);\n"); 282 } else { 283 printer->Print(variables_, 284 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 285 " .getRepeatedFieldArrayLength(input, $tag$);\n" 286 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 287 "int[] newArray = new int[i + arrayLength];\n" 288 "if (i != 0) {\n" 289 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 290 "}\n" 291 "for (; i < newArray.length - 1; i++) {\n" 292 " newArray[i] = input.readInt32();\n" 293 " input.readTag();\n" 294 "}\n" 295 "// Last one without readTag.\n" 296 "newArray[i] = input.readInt32();\n" 297 "this.$name$ = newArray;\n"); 298 } 299} 300 301void RepeatedEnumFieldGenerator:: 302GenerateSerializationCode(io::Printer* printer) const { 303 printer->Print(variables_, 304 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 305 printer->Indent(); 306 307 if (descriptor_->options().packed()) { 308 printer->Print(variables_, 309 "output.writeRawVarint32($tag$);\n" 310 "output.writeRawVarint32($name$MemoizedSerializedSize);\n" 311 "for (int element : this.$name$) {\n" 312 " output.writeRawVarint32(element);\n" 313 "}\n"); 314 } else { 315 printer->Print(variables_, 316 "for (int element : this.$name$) {\n" 317 " output.writeInt32($number$, element);\n" 318 "}\n"); 319 } 320 printer->Outdent(); 321 printer->Print(variables_, 322 "}\n"); 323} 324 325void RepeatedEnumFieldGenerator:: 326GenerateSerializedSizeCode(io::Printer* printer) const { 327 printer->Print(variables_, 328 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 329 printer->Indent(); 330 331 printer->Print(variables_, 332 "int dataSize = 0;\n" 333 "for (int element : this.$name$) {\n" 334 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 335 " .computeInt32SizeNoTag(element);\n" 336 "}\n"); 337 338 printer->Print( 339 "size += dataSize;\n"); 340 if (descriptor_->options().packed()) { 341 // cache the data size for packed fields. 342 printer->Print(variables_, 343 "size += $tag_size$;\n" 344 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 345 " .computeRawVarint32Size(dataSize);\n" 346 "$name$MemoizedSerializedSize = dataSize;\n"); 347 } else { 348 printer->Print(variables_, 349 "size += $tag_size$ * this.$name$.length;\n"); 350 } 351 352 printer->Outdent(); 353 354 // set cached size to 0 for empty packed fields. 355 if (descriptor_->options().packed()) { 356 printer->Print(variables_, 357 "} else {\n" 358 " $name$MemoizedSerializedSize = 0;\n" 359 "}\n"); 360 } else { 361 printer->Print( 362 "}\n"); 363 } 364} 365 366string RepeatedEnumFieldGenerator::GetBoxedType() const { 367 return ClassName(params_, descriptor_->enum_type()); 368} 369 370} // namespace javanano 371} // namespace compiler 372} // namespace protobuf 373} // namespace google 374