javanano_enum_field.cc revision f4e01452f159ae6b53f5edd25fa647ca2919ae10
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 87void EnumFieldGenerator:: 88GenerateParsingCode(io::Printer* printer) const { 89 printer->Print(variables_, 90 " this.$name$ = input.readInt32();\n"); 91} 92 93void EnumFieldGenerator:: 94GenerateSerializationCode(io::Printer* printer) const { 95 if (descriptor_->is_required()) { 96 printer->Print(variables_, 97 "output.writeInt32($number$, this.$name$);\n"); 98 } else { 99 printer->Print(variables_, 100 "if (this.$name$ != $default$) {\n" 101 " output.writeInt32($number$, this.$name$);\n" 102 "}\n"); 103 } 104} 105 106void EnumFieldGenerator:: 107GenerateSerializedSizeCode(io::Printer* printer) const { 108 if (descriptor_->is_required()) { 109 printer->Print(variables_, 110 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 111 " .computeInt32Size($number$, this.$name$);\n"); 112 } else { 113 printer->Print(variables_, 114 "if (this.$name$ != $default$) {\n" 115 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 116 " .computeInt32Size($number$, this.$name$);\n" 117 "}\n"); 118 } 119} 120 121string EnumFieldGenerator::GetBoxedType() const { 122 return ClassName(params_, descriptor_->enum_type()); 123} 124 125// =================================================================== 126 127RepeatedEnumFieldGenerator:: 128RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 129 : FieldGenerator(params), descriptor_(descriptor) { 130 SetEnumVariables(params, descriptor, &variables_); 131} 132 133RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 134 135void RepeatedEnumFieldGenerator:: 136GenerateMembers(io::Printer* printer) const { 137 printer->Print(variables_, 138 "public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); 139 if (descriptor_->options().packed()) { 140 printer->Print(variables_, 141 "private int $name$MemoizedSerializedSize;\n"); 142 } 143} 144 145void RepeatedEnumFieldGenerator:: 146GenerateParsingCode(io::Printer* printer) const { 147 // First, figure out the length of the array, then parse. 148 if (descriptor_->options().packed()) { 149 printer->Print(variables_, 150 "int length = input.readRawVarint32();\n" 151 "int limit = input.pushLimit(length);\n" 152 "// First pass to compute array length.\n" 153 "int arrayLength = 0;\n" 154 "int startPos = input.getPosition();\n" 155 "while (input.getBytesUntilLimit() > 0) {\n" 156 " input.readInt32();\n" 157 " arrayLength++;\n" 158 "}\n" 159 "input.rewindToPosition(startPos);\n" 160 "this.$name$ = new $type$[arrayLength];\n" 161 "for (int i = 0; i < arrayLength; i++) {\n" 162 " this.$name$[i] = input.readInt32();\n" 163 "}\n" 164 "input.popLimit(limit);\n"); 165 } else { 166 printer->Print(variables_, 167 "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" 168 "int i = this.$name$.length;\n" 169 "int[] newArray = new int[i + arrayLength];\n" 170 "System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 171 "this.$name$ = newArray;\n" 172 "for (; i < this.$name$.length - 1; i++) {\n" 173 " this.$name$[i] = input.readInt32();\n" 174 " input.readTag();\n" 175 "}\n" 176 "// Last one without readTag.\n" 177 "this.$name$[i] = input.readInt32();\n"); 178 } 179} 180 181void RepeatedEnumFieldGenerator:: 182GenerateSerializationCode(io::Printer* printer) const { 183 printer->Print(variables_, 184 "if (this.$name$.length > 0) {\n"); 185 printer->Indent(); 186 187 if (descriptor_->options().packed()) { 188 printer->Print(variables_, 189 "output.writeRawVarint32($tag$);\n" 190 "output.writeRawVarint32($name$MemoizedSerializedSize);\n" 191 "for (int element : this.$name$) {\n" 192 " output.writeRawVarint32(element);\n" 193 "}\n"); 194 } else { 195 printer->Print(variables_, 196 "for (int element : this.$name$) {\n" 197 " output.writeInt32($number$, element);\n" 198 "}\n"); 199 } 200 printer->Outdent(); 201 printer->Print(variables_, 202 "}\n"); 203} 204 205void RepeatedEnumFieldGenerator:: 206GenerateSerializedSizeCode(io::Printer* printer) const { 207 printer->Print(variables_, 208 "if (this.$name$.length > 0) {\n"); 209 printer->Indent(); 210 211 printer->Print(variables_, 212 "int dataSize = 0;\n" 213 "for (int element : this.$name$) {\n" 214 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 215 " .computeInt32SizeNoTag(element);\n" 216 "}\n"); 217 218 printer->Print( 219 "size += dataSize;\n"); 220 if (descriptor_->options().packed()) { 221 // cache the data size for packed fields. 222 printer->Print(variables_, 223 "size += $tag_size$;\n" 224 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 225 " .computeRawVarint32Size(dataSize);\n" 226 "$name$MemoizedSerializedSize = dataSize;\n"); 227 } else { 228 printer->Print(variables_, 229 "size += $tag_size$ * this.$name$.length;\n"); 230 } 231 232 printer->Outdent(); 233 234 // set cached size to 0 for empty packed fields. 235 if (descriptor_->options().packed()) { 236 printer->Print(variables_, 237 "} else {\n" 238 " $name$MemoizedSerializedSize = 0;\n" 239 "}\n"); 240 } else { 241 printer->Print( 242 "}\n"); 243 } 244} 245 246string RepeatedEnumFieldGenerator::GetBoxedType() const { 247 return ClassName(params_, descriptor_->enum_type()); 248} 249 250} // namespace javanano 251} // namespace compiler 252} // namespace protobuf 253} // namespace google 254