javanano_enum_field.cc revision e74fe623e115237968a3de1143d7cdb4df710858
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 (*variables)["type"] = "int"; 62 (*variables)["default"] = DefaultValue(params, descriptor); 63 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); 64 (*variables)["tag_size"] = SimpleItoa( 65 internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); 66 (*variables)["message_name"] = descriptor->containing_type()->name(); 67} 68 69} // namespace 70 71// =================================================================== 72 73EnumFieldGenerator:: 74EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 75 : FieldGenerator(params), descriptor_(descriptor) { 76 SetEnumVariables(params, descriptor, &variables_); 77} 78 79EnumFieldGenerator::~EnumFieldGenerator() {} 80 81void EnumFieldGenerator:: 82GenerateMembers(io::Printer* printer) const { 83 printer->Print(variables_, 84 "public int $name$ = $default$;\n"); 85 86 if (params_.generate_has()) { 87 printer->Print(variables_, 88 "public boolean has$capitalized_name$ = false;\n"); 89 } 90} 91 92void EnumFieldGenerator:: 93GenerateClearCode(io::Printer* printer) const { 94 printer->Print(variables_, 95 "$name$ = $default$;\n"); 96 97 if (params_.generate_has()) { 98 printer->Print(variables_, 99 "has$capitalized_name$ = false;\n"); 100 } 101} 102 103void EnumFieldGenerator:: 104GenerateMergingCode(io::Printer* printer) const { 105 printer->Print(variables_, 106 " this.$name$ = input.readInt32();\n"); 107 108 if (params_.generate_has()) { 109 printer->Print(variables_, 110 " has$capitalized_name$ = true;\n"); 111 } 112} 113 114void EnumFieldGenerator:: 115GenerateSerializationCode(io::Printer* printer) const { 116 if (descriptor_->is_required()) { 117 printer->Print(variables_, 118 "output.writeInt32($number$, this.$name$);\n"); 119 } else { 120 if (params_.generate_has()) { 121 printer->Print(variables_, 122 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 123 } else { 124 printer->Print(variables_, 125 "if (this.$name$ != $default$) {\n"); 126 } 127 printer->Print(variables_, 128 " output.writeInt32($number$, this.$name$);\n" 129 "}\n"); 130 } 131} 132 133void EnumFieldGenerator:: 134GenerateSerializedSizeCode(io::Printer* printer) const { 135 if (descriptor_->is_required()) { 136 printer->Print(variables_, 137 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 138 " .computeInt32Size($number$, this.$name$);\n"); 139 } else { 140 if (params_.generate_has()) { 141 printer->Print(variables_, 142 "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); 143 } else { 144 printer->Print(variables_, 145 "if (this.$name$ != $default$) {\n"); 146 } 147 printer->Print(variables_, 148 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 149 " .computeInt32Size($number$, this.$name$);\n" 150 "}\n"); 151 } 152} 153 154string EnumFieldGenerator::GetBoxedType() const { 155 return ClassName(params_, descriptor_->enum_type()); 156} 157 158// =================================================================== 159 160AccessorEnumFieldGenerator:: 161AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, 162 const Params& params, int has_bit_index) 163 : FieldGenerator(params), descriptor_(descriptor) { 164 SetEnumVariables(params, descriptor, &variables_); 165 SetBitOperationVariables("has", has_bit_index, &variables_); 166} 167 168AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} 169 170void AccessorEnumFieldGenerator:: 171GenerateMembers(io::Printer* printer) const { 172 printer->Print(variables_, 173 "private int $name$_ = $default$;\n" 174 "public int get$capitalized_name$() {\n" 175 " return $name$_;\n" 176 "}\n" 177 "public void set$capitalized_name$(int value) {\n" 178 " $name$_ = value;\n" 179 " $set_has$;\n" 180 "}\n" 181 "public boolean has$capitalized_name$() {\n" 182 " return $get_has$;\n" 183 "}\n" 184 "public void clear$capitalized_name$() {\n" 185 " $name$_ = $default$;\n" 186 " $clear_has$;\n" 187 "}\n"); 188} 189 190void AccessorEnumFieldGenerator:: 191GenerateClearCode(io::Printer* printer) const { 192 printer->Print(variables_, 193 "$name$_ = $default$;\n"); 194} 195 196void AccessorEnumFieldGenerator:: 197GenerateMergingCode(io::Printer* printer) const { 198 printer->Print(variables_, 199 "set$capitalized_name$(input.readInt32());\n"); 200} 201 202void AccessorEnumFieldGenerator:: 203GenerateSerializationCode(io::Printer* printer) const { 204 printer->Print(variables_, 205 "if (has$capitalized_name$()) {\n" 206 " output.writeInt32($number$, $name$_);\n" 207 "}\n"); 208} 209 210void AccessorEnumFieldGenerator:: 211GenerateSerializedSizeCode(io::Printer* printer) const { 212 printer->Print(variables_, 213 "if (has$capitalized_name$()) {\n" 214 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 215 " .computeInt32Size($number$, $name$_);\n" 216 "}\n"); 217} 218 219string AccessorEnumFieldGenerator::GetBoxedType() const { 220 return ClassName(params_, descriptor_->enum_type()); 221} 222 223// =================================================================== 224 225RepeatedEnumFieldGenerator:: 226RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 227 : FieldGenerator(params), descriptor_(descriptor) { 228 SetEnumVariables(params, descriptor, &variables_); 229} 230 231RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 232 233void RepeatedEnumFieldGenerator:: 234GenerateMembers(io::Printer* printer) const { 235 printer->Print(variables_, 236 "public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); 237 if (descriptor_->options().packed()) { 238 printer->Print(variables_, 239 "private int $name$MemoizedSerializedSize;\n"); 240 } 241} 242 243void RepeatedEnumFieldGenerator:: 244GenerateClearCode(io::Printer* printer) const { 245 printer->Print(variables_, 246 "$name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); 247} 248 249void RepeatedEnumFieldGenerator:: 250GenerateMergingCode(io::Printer* printer) const { 251 // First, figure out the length of the array, then parse. 252 if (descriptor_->options().packed()) { 253 printer->Print(variables_, 254 "int length = input.readRawVarint32();\n" 255 "int limit = input.pushLimit(length);\n" 256 "// First pass to compute array length.\n" 257 "int arrayLength = 0;\n" 258 "int startPos = input.getPosition();\n" 259 "while (input.getBytesUntilLimit() > 0) {\n" 260 " input.readInt32();\n" 261 " arrayLength++;\n" 262 "}\n" 263 "input.rewindToPosition(startPos);\n" 264 "this.$name$ = new $type$[arrayLength];\n" 265 "for (int i = 0; i < arrayLength; i++) {\n" 266 " this.$name$[i] = input.readInt32();\n" 267 "}\n" 268 "input.popLimit(limit);\n"); 269 } else { 270 printer->Print(variables_, 271 "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" 272 "int i = this.$name$.length;\n" 273 "int[] newArray = new int[i + arrayLength];\n" 274 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 275 "this.$name$ = newArray;\n" 276 "for (; i < this.$name$.length - 1; i++) {\n" 277 " this.$name$[i] = input.readInt32();\n" 278 " input.readTag();\n" 279 "}\n" 280 "// Last one without readTag.\n" 281 "this.$name$[i] = input.readInt32();\n"); 282 } 283} 284 285void RepeatedEnumFieldGenerator:: 286GenerateSerializationCode(io::Printer* printer) const { 287 printer->Print(variables_, 288 "if (this.$name$.length > 0) {\n"); 289 printer->Indent(); 290 291 if (descriptor_->options().packed()) { 292 printer->Print(variables_, 293 "output.writeRawVarint32($tag$);\n" 294 "output.writeRawVarint32($name$MemoizedSerializedSize);\n" 295 "for (int element : this.$name$) {\n" 296 " output.writeRawVarint32(element);\n" 297 "}\n"); 298 } else { 299 printer->Print(variables_, 300 "for (int element : this.$name$) {\n" 301 " output.writeInt32($number$, element);\n" 302 "}\n"); 303 } 304 printer->Outdent(); 305 printer->Print(variables_, 306 "}\n"); 307} 308 309void RepeatedEnumFieldGenerator:: 310GenerateSerializedSizeCode(io::Printer* printer) const { 311 printer->Print(variables_, 312 "if (this.$name$.length > 0) {\n"); 313 printer->Indent(); 314 315 printer->Print(variables_, 316 "int dataSize = 0;\n" 317 "for (int element : this.$name$) {\n" 318 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 319 " .computeInt32SizeNoTag(element);\n" 320 "}\n"); 321 322 printer->Print( 323 "size += dataSize;\n"); 324 if (descriptor_->options().packed()) { 325 // cache the data size for packed fields. 326 printer->Print(variables_, 327 "size += $tag_size$;\n" 328 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 329 " .computeRawVarint32Size(dataSize);\n" 330 "$name$MemoizedSerializedSize = dataSize;\n"); 331 } else { 332 printer->Print(variables_, 333 "size += $tag_size$ * this.$name$.length;\n"); 334 } 335 336 printer->Outdent(); 337 338 // set cached size to 0 for empty packed fields. 339 if (descriptor_->options().packed()) { 340 printer->Print(variables_, 341 "} else {\n" 342 " $name$MemoizedSerializedSize = 0;\n" 343 "}\n"); 344 } else { 345 printer->Print( 346 "}\n"); 347 } 348} 349 350string RepeatedEnumFieldGenerator::GetBoxedType() const { 351 return ClassName(params_, descriptor_->enum_type()); 352} 353 354} // namespace javanano 355} // namespace compiler 356} // namespace protobuf 357} // namespace google 358