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/javamicro/javamicro_enum_field.h> 39#include <google/protobuf/stubs/common.h> 40#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro { 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 "private boolean has$capitalized_name$;\n" 85 "private int $name$_ = $default$;\n" 86 "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" 87 "public int get$capitalized_name$() { return $name$_; }\n" 88 "public $message_name$ set$capitalized_name$(int value) {\n" 89 " has$capitalized_name$ = true;\n" 90 " $name$_ = value;\n" 91 " return this;\n" 92 "}\n" 93 "public $message_name$ clear$capitalized_name$() {\n" 94 " has$capitalized_name$ = false;\n" 95 " $name$_ = $default$;\n" 96 " return this;\n" 97 "}\n"); 98} 99 100void EnumFieldGenerator:: 101GenerateMergingCode(io::Printer* printer) const { 102 printer->Print(variables_, 103 "what is other??" 104 "if (other.has$capitalized_name$()) {\n" 105 " set$capitalized_name$(other.get$capitalized_name$());\n" 106 "}\n"); 107} 108 109void EnumFieldGenerator:: 110GenerateParsingCode(io::Printer* printer) const { 111 printer->Print(variables_, 112 " set$capitalized_name$(input.readInt32());\n"); 113} 114 115void EnumFieldGenerator:: 116GenerateSerializationCode(io::Printer* printer) const { 117 printer->Print(variables_, 118 "if (has$capitalized_name$()) {\n" 119 " output.writeInt32($number$, get$capitalized_name$());\n" 120 "}\n"); 121} 122 123void EnumFieldGenerator:: 124GenerateSerializedSizeCode(io::Printer* printer) const { 125 printer->Print(variables_, 126 "if (has$capitalized_name$()) {\n" 127 " size += com.google.protobuf.micro.CodedOutputStreamMicro\n" 128 " .computeInt32Size($number$, get$capitalized_name$());\n" 129 "}\n"); 130} 131 132string EnumFieldGenerator::GetBoxedType() const { 133 return ClassName(params_, descriptor_->enum_type()); 134} 135 136// =================================================================== 137 138RepeatedEnumFieldGenerator:: 139RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 140 : FieldGenerator(params), descriptor_(descriptor) { 141 SetEnumVariables(params, descriptor, &variables_); 142 if (descriptor_->options().packed()) { 143 GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed"; 144 } 145} 146 147RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 148 149void RepeatedEnumFieldGenerator:: 150GenerateMembers(io::Printer* printer) const { 151 if (params_.java_use_vector()) { 152 printer->Print(variables_, 153 "private java.util.Vector $name$_ = new java.util.Vector();\n" 154 "public java.util.Vector get$capitalized_name$List() {\n" 155 " return $name$_;\n" 156 "}\n" 157 "public int get$capitalized_name$Count() { return $name$_.size(); }\n" 158 "public int get$capitalized_name$(int index) {\n" 159 " return ((Integer)$name$_.elementAt(index)).intValue();\n" 160 "}\n" 161 "public $message_name$ set$capitalized_name$(int index, int value) {\n" 162 " $name$_.setElementAt(new Integer(value), index);\n" 163 " return this;\n" 164 "}\n" 165 "public $message_name$ add$capitalized_name$(int value) {\n" 166 " $name$_.addElement(new Integer(value));\n" 167 " return this;\n" 168 "}\n" 169 "public $message_name$ clear$capitalized_name$() {\n" 170 " $name$_.removeAllElements();\n" 171 " return this;\n" 172 "}\n"); 173 } else { 174 printer->Print(variables_, 175 "private java.util.List<Integer> $name$_ =\n" 176 " java.util.Collections.emptyList();\n" 177 "public java.util.List<Integer> get$capitalized_name$List() {\n" 178 " return $name$_;\n" // note: unmodifiable list 179 "}\n" 180 "public int get$capitalized_name$Count() { return $name$_.size(); }\n" 181 "public int get$capitalized_name$(int index) {\n" 182 " return $name$_.get(index);\n" 183 "}\n" 184 "public $message_name$ set$capitalized_name$(int index, int value) {\n" 185 " $name$_.set(index, value);\n" 186 " return this;\n" 187 "}\n" 188 "public $message_name$ add$capitalized_name$(int value) {\n" 189 " if ($name$_.isEmpty()) {\n" 190 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n" 191 " }\n" 192 " $name$_.add(value);\n" 193 " return this;\n" 194 "}\n" 195 "public $message_name$ clear$capitalized_name$() {\n" 196 " $name$_ = java.util.Collections.emptyList();\n" 197 " return this;\n" 198 "}\n"); 199 } 200 if (descriptor_->options().packed()) { 201 printer->Print(variables_, 202 "private int $name$MemoizedSerializedSize;\n"); 203 } 204} 205 206void RepeatedEnumFieldGenerator:: 207GenerateMergingCode(io::Printer* printer) const { 208 if (params_.java_use_vector()) { 209 printer->Print(variables_, 210 "if (other.$name$_.size() != 0) {\n" 211 " for (int i = 0; i < other.$name$_.size(); i++)) {\n" 212 " result.$name$_.addElement(other.$name$_.elementAt(i));\n" 213 " }\n" 214 "}\n"); 215 } else { 216 printer->Print(variables_, 217 "if (!other.$name$_.isEmpty()) {\n" 218 " if (result.$name$_.isEmpty()) {\n" 219 " result.$name$_ = new java.util.ArrayList<java.lang.Integer>();\n" 220 " }\n" 221 " result.$name$_.addAll(other.$name$_);\n" 222 "}\n"); 223 } 224} 225 226void RepeatedEnumFieldGenerator:: 227GenerateParsingCode(io::Printer* printer) const { 228 // If packed, set up the while loop 229 if (descriptor_->options().packed()) { 230 printer->Print(variables_, 231 "int length = input.readRawVarint32();\n" 232 "int oldLimit = input.pushLimit(length);\n" 233 "while(input.getBytesUntilLimit() > 0) {\n"); 234 printer->Indent(); 235 } 236 237 // Read and store the enum 238 printer->Print(variables_, 239 " add$capitalized_name$(input.readInt32());\n"); 240 241 if (descriptor_->options().packed()) { 242 printer->Outdent(); 243 printer->Print(variables_, 244 "}\n" 245 "input.popLimit(oldLimit);\n"); 246 } 247} 248 249void RepeatedEnumFieldGenerator:: 250GenerateSerializationCode(io::Printer* printer) const { 251 if (descriptor_->options().packed()) { 252 printer->Print(variables_, 253 "if (get$capitalized_name$List().size() > 0) {\n" 254 " output.writeRawVarint32($tag$);\n" 255 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 256 "}\n"); 257 if (params_.java_use_vector()) { 258 printer->Print(variables_, 259 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n" 260 " output.writeRawVarint32(get$capitalized_name$(i));\n" 261 "}\n"); 262 } else { 263 printer->Print(variables_, 264 "for ($type$ element : get$capitalized_name$List()) {\n" 265 " output.writeRawVarint32(element.getNumber());\n" 266 "}\n"); 267 } 268 } else { 269 if (params_.java_use_vector()) { 270 printer->Print(variables_, 271 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n" 272 " output.writeInt32($number$, (int)get$capitalized_name$(i));\n" 273 "}\n"); 274 } else { 275 printer->Print(variables_, 276 "for (java.lang.Integer element : get$capitalized_name$List()) {\n" 277 " output.writeInt32($number$, element);\n" 278 "}\n"); 279 } 280 } 281} 282 283void RepeatedEnumFieldGenerator:: 284GenerateSerializedSizeCode(io::Printer* printer) const { 285 printer->Print(variables_, 286 "{\n" 287 " int dataSize = 0;\n"); 288 printer->Indent(); 289 if (params_.java_use_vector()) { 290 printer->Print(variables_, 291 "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n" 292 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n" 293 " .computeInt32SizeNoTag(get$capitalized_name$(i));\n" 294 "}\n"); 295 } else { 296 printer->Print(variables_, 297 "for (java.lang.Integer element : get$capitalized_name$List()) {\n" 298 " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n" 299 " .computeInt32SizeNoTag(element);\n" 300 "}\n"); 301 } 302 printer->Print( 303 "size += dataSize;\n"); 304 if (descriptor_->options().packed()) { 305 printer->Print(variables_, 306 "if (get$capitalized_name$List().size() != 0) {" 307 " size += $tag_size$;\n" 308 " size += com.google.protobuf.micro.CodedOutputStreamMicro\n" 309 " .computeRawVarint32Size(dataSize);\n" 310 "}"); 311 } else { 312 printer->Print(variables_, 313 "size += $tag_size$ * get$capitalized_name$List().size();\n"); 314 } 315 316 // cache the data size for packed fields. 317 if (descriptor_->options().packed()) { 318 printer->Print(variables_, 319 "$name$MemoizedSerializedSize = dataSize;\n"); 320 } 321 322 printer->Outdent(); 323 printer->Print("}\n"); 324} 325 326string RepeatedEnumFieldGenerator::GetBoxedType() const { 327 return ClassName(params_, descriptor_->enum_type()); 328} 329 330} // namespace javamicro 331} // namespace compiler 332} // namespace protobuf 333} // namespace google 334