javanano_enum_field.cc revision e03e9f4b5774c0ffe04140d83bbdb532863b1720
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 "this.$name$ = new $type$[arrayLength];\n" 273 "for (int i = 0; i < arrayLength; i++) {\n" 274 " this.$name$[i] = input.readInt32();\n" 275 "}\n" 276 "input.popLimit(limit);\n"); 277 } else { 278 printer->Print(variables_, 279 "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" 280 "int i = this.$name$.length;\n" 281 "int[] newArray = new int[i + arrayLength];\n" 282 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 283 "this.$name$ = newArray;\n" 284 "for (; i < this.$name$.length - 1; i++) {\n" 285 " this.$name$[i] = input.readInt32();\n" 286 " input.readTag();\n" 287 "}\n" 288 "// Last one without readTag.\n" 289 "this.$name$[i] = input.readInt32();\n"); 290 } 291} 292 293void RepeatedEnumFieldGenerator:: 294GenerateSerializationCode(io::Printer* printer) const { 295 printer->Print(variables_, 296 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 297 printer->Indent(); 298 299 if (descriptor_->options().packed()) { 300 printer->Print(variables_, 301 "output.writeRawVarint32($tag$);\n" 302 "output.writeRawVarint32($name$MemoizedSerializedSize);\n" 303 "for (int element : this.$name$) {\n" 304 " output.writeRawVarint32(element);\n" 305 "}\n"); 306 } else { 307 printer->Print(variables_, 308 "for (int element : this.$name$) {\n" 309 " output.writeInt32($number$, element);\n" 310 "}\n"); 311 } 312 printer->Outdent(); 313 printer->Print(variables_, 314 "}\n"); 315} 316 317void RepeatedEnumFieldGenerator:: 318GenerateSerializedSizeCode(io::Printer* printer) const { 319 printer->Print(variables_, 320 "if (this.$name$ != null && this.$name$.length > 0) {\n"); 321 printer->Indent(); 322 323 printer->Print(variables_, 324 "int dataSize = 0;\n" 325 "for (int element : this.$name$) {\n" 326 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 327 " .computeInt32SizeNoTag(element);\n" 328 "}\n"); 329 330 printer->Print( 331 "size += dataSize;\n"); 332 if (descriptor_->options().packed()) { 333 // cache the data size for packed fields. 334 printer->Print(variables_, 335 "size += $tag_size$;\n" 336 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 337 " .computeRawVarint32Size(dataSize);\n" 338 "$name$MemoizedSerializedSize = dataSize;\n"); 339 } else { 340 printer->Print(variables_, 341 "size += $tag_size$ * this.$name$.length;\n"); 342 } 343 344 printer->Outdent(); 345 346 // set cached size to 0 for empty packed fields. 347 if (descriptor_->options().packed()) { 348 printer->Print(variables_, 349 "} else {\n" 350 " $name$MemoizedSerializedSize = 0;\n" 351 "}\n"); 352 } else { 353 printer->Print( 354 "}\n"); 355 } 356} 357 358string RepeatedEnumFieldGenerator::GetBoxedType() const { 359 return ClassName(params_, descriptor_->enum_type()); 360} 361 362} // namespace javanano 363} // namespace compiler 364} // namespace protobuf 365} // namespace google 366