javanano_enum_field.cc revision 0f1c4eb967517e21701a3b425d115baff5d15b4f
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 UnderscoresToCamelCase(descriptor); 58 (*variables)["capitalized_name"] = 59 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 "this.$name$ = java.util.Arrays.copyOf(this.$name$, this.$name$.length + arrayLength);\n" 170 "for (; i < this.$name$.length - 1; i++) {\n" 171 " this.$name$[i] = input.readInt32();\n" 172 " input.readTag();\n" 173 "}\n" 174 "// Last one without readTag.\n" 175 "this.$name$[i] = input.readInt32();\n"); 176 } 177} 178 179void RepeatedEnumFieldGenerator:: 180GenerateSerializationCode(io::Printer* printer) const { 181 printer->Print(variables_, 182 "if (this.$name$.length > 0) {\n"); 183 printer->Indent(); 184 185 if (descriptor_->options().packed()) { 186 printer->Print(variables_, 187 "output.writeRawVarint32($tag$);\n" 188 "output.writeRawVarint32($name$MemoizedSerializedSize);\n" 189 "for (int element : this.$name$) {\n" 190 " output.writeRawVarint32(element);\n" 191 "}\n"); 192 } else { 193 printer->Print(variables_, 194 "for (int element : this.$name$) {\n" 195 " output.writeInt32($number$, element);\n" 196 "}\n"); 197 } 198 printer->Outdent(); 199 printer->Print(variables_, 200 "}\n"); 201} 202 203void RepeatedEnumFieldGenerator:: 204GenerateSerializedSizeCode(io::Printer* printer) const { 205 printer->Print(variables_, 206 "if (this.$name$.length > 0) {\n"); 207 printer->Indent(); 208 209 printer->Print(variables_, 210 "int dataSize = 0;\n" 211 "for (int element : this.$name$) {\n" 212 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 213 " .computeInt32SizeNoTag(element);\n" 214 "}\n"); 215 216 printer->Print( 217 "size += dataSize;\n"); 218 if (descriptor_->options().packed()) { 219 // cache the data size for packed fields. 220 printer->Print(variables_, 221 "size += $tag_size$;\n" 222 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 223 " .computeRawVarint32Size(dataSize);\n" 224 "$name$MemoizedSerializedSize = dataSize;\n"); 225 } else { 226 printer->Print(variables_, 227 "size += $tag_size$ * this.$name$.length;\n"); 228 } 229 230 printer->Outdent(); 231 232 // set cached size to 0 for empty packed fields. 233 if (descriptor_->options().packed()) { 234 printer->Print(variables_, 235 "} else {\n" 236 " $name$MemoizedSerializedSize = 0;\n" 237 "}\n"); 238 } else { 239 printer->Print( 240 "}\n"); 241 } 242} 243 244string RepeatedEnumFieldGenerator::GetBoxedType() const { 245 return ClassName(params_, descriptor_->enum_type()); 246} 247 248} // namespace javanano 249} // namespace compiler 250} // namespace protobuf 251} // namespace google 252