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 (at) 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_message_field.h> 39 #include <google/protobuf/compiler/javanano/javanano_helpers.h> 40 #include <google/protobuf/io/printer.h> 41 #include <google/protobuf/wire_format.h> 42 #include <google/protobuf/stubs/strutil.h> 43 44 namespace google { 45 namespace protobuf { 46 namespace compiler { 47 namespace javanano { 48 49 using internal::WireFormat; 50 using internal::WireFormatLite; 51 52 namespace { 53 54 // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of 55 // repeat code between this and the other field types. 56 void SetMessageVariables(const Params& params, 57 const FieldDescriptor* descriptor, map<string, string>* variables) { 58 (*variables)["name"] = 59 RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); 60 (*variables)["capitalized_name"] = 61 RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); 62 (*variables)["number"] = SimpleItoa(descriptor->number()); 63 (*variables)["type"] = ClassName(params, descriptor->message_type()); 64 (*variables)["group_or_message"] = 65 (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? 66 "Group" : "Message"; 67 (*variables)["message_name"] = descriptor->containing_type()->name(); 68 //(*variables)["message_type"] = descriptor->message_type()->name(); 69 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); 70 } 71 72 } // namespace 73 74 // =================================================================== 75 76 MessageFieldGenerator:: 77 MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) 78 : FieldGenerator(params), descriptor_(descriptor) { 79 SetMessageVariables(params, descriptor, &variables_); 80 } 81 82 MessageFieldGenerator::~MessageFieldGenerator() {} 83 84 void MessageFieldGenerator:: 85 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 86 printer->Print(variables_, 87 "public $type$ $name$;\n"); 88 } 89 90 void MessageFieldGenerator:: 91 GenerateClearCode(io::Printer* printer) const { 92 printer->Print(variables_, 93 "$name$ = null;\n"); 94 } 95 96 void MessageFieldGenerator:: 97 GenerateMergingCode(io::Printer* printer) const { 98 printer->Print(variables_, 99 "if (this.$name$ == null) {\n" 100 " this.$name$ = new $type$();\n" 101 "}\n"); 102 103 if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { 104 printer->Print(variables_, 105 "input.readGroup(this.$name$, $number$);\n"); 106 } else { 107 printer->Print(variables_, 108 "input.readMessage(this.$name$);\n"); 109 } 110 } 111 112 void MessageFieldGenerator:: 113 GenerateSerializationCode(io::Printer* printer) const { 114 printer->Print(variables_, 115 "if (this.$name$ != null) {\n" 116 " output.write$group_or_message$($number$, this.$name$);\n" 117 "}\n"); 118 } 119 120 void MessageFieldGenerator:: 121 GenerateSerializedSizeCode(io::Printer* printer) const { 122 printer->Print(variables_, 123 "if (this.$name$ != null) {\n" 124 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 125 " .compute$group_or_message$Size($number$, this.$name$);\n" 126 "}\n"); 127 } 128 129 void MessageFieldGenerator:: 130 GenerateFixClonedCode(io::Printer* printer) const { 131 printer->Print(variables_, 132 "if (this.$name$ != null) {\n" 133 " cloned.$name$ = this.$name$.clone();\n" 134 "}\n"); 135 } 136 137 void MessageFieldGenerator:: 138 GenerateEqualsCode(io::Printer* printer) const { 139 printer->Print(variables_, 140 "if (this.$name$ == null) { \n" 141 " if (other.$name$ != null) {\n" 142 " return false;\n" 143 " }\n" 144 "} else {\n" 145 " if (!this.$name$.equals(other.$name$)) {\n" 146 " return false;\n" 147 " }\n" 148 "}\n"); 149 } 150 151 void MessageFieldGenerator:: 152 GenerateHashCodeCode(io::Printer* printer) const { 153 printer->Print(variables_, 154 "result = 31 * result +\n" 155 " (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); 156 } 157 // =================================================================== 158 159 MessageOneofFieldGenerator::MessageOneofFieldGenerator( 160 const FieldDescriptor* descriptor, const Params& params) 161 : FieldGenerator(params), descriptor_(descriptor) { 162 SetMessageVariables(params, descriptor, &variables_); 163 SetCommonOneofVariables(descriptor, &variables_); 164 } 165 166 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} 167 168 void MessageOneofFieldGenerator:: 169 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 170 printer->Print(variables_, 171 "public boolean has$capitalized_name$() {\n" 172 " return $has_oneof_case$;\n" 173 "}\n" 174 "public $type$ get$capitalized_name$() {\n" 175 " if ($has_oneof_case$) {\n" 176 " return ($type$) this.$oneof_name$_;\n" 177 " }\n" 178 " return null;\n" 179 "}\n" 180 "public $message_name$ set$capitalized_name$($type$ value) {\n" 181 " if (value == null) { throw new java.lang.NullPointerException(); }\n" 182 " $set_oneof_case$;\n" 183 " this.$oneof_name$_ = value;\n" 184 " return this;\n" 185 "}\n"); 186 } 187 188 void MessageOneofFieldGenerator:: 189 GenerateClearCode(io::Printer* printer) const { 190 // No clear method for oneof fields. 191 } 192 193 void MessageOneofFieldGenerator:: 194 GenerateMergingCode(io::Printer* printer) const { 195 printer->Print(variables_, 196 "if (!($has_oneof_case$)) {\n" 197 " this.$oneof_name$_ = new $type$();\n" 198 "}\n" 199 "input.readMessage(\n" 200 " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" 201 "$set_oneof_case$;\n"); 202 } 203 204 void MessageOneofFieldGenerator:: 205 GenerateSerializationCode(io::Printer* printer) const { 206 printer->Print(variables_, 207 "if ($has_oneof_case$) {\n" 208 " output.writeMessage($number$,\n" 209 " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" 210 "}\n"); 211 } 212 213 void MessageOneofFieldGenerator:: 214 GenerateSerializedSizeCode(io::Printer* printer) const { 215 printer->Print(variables_, 216 "if ($has_oneof_case$) {\n" 217 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 218 " .computeMessageSize($number$,\n" 219 " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" 220 "}\n"); 221 } 222 223 void MessageOneofFieldGenerator:: 224 GenerateFixClonedCode(io::Printer* printer) const { 225 printer->Print(variables_, 226 "if (this.$oneof_name$ != null) {\n" 227 " cloned.$oneof_name$ = this.$oneof_name$.clone();\n" 228 "}\n"); 229 } 230 231 void MessageOneofFieldGenerator:: 232 GenerateEqualsCode(io::Printer* printer) const { 233 GenerateOneofFieldEquals(descriptor_, variables_, printer); 234 } 235 236 void MessageOneofFieldGenerator:: 237 GenerateHashCodeCode(io::Printer* printer) const { 238 GenerateOneofFieldHashCode(descriptor_, variables_, printer); 239 } 240 241 // =================================================================== 242 243 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( 244 const FieldDescriptor* descriptor, const Params& params) 245 : FieldGenerator(params), descriptor_(descriptor) { 246 SetMessageVariables(params, descriptor, &variables_); 247 } 248 249 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} 250 251 void RepeatedMessageFieldGenerator:: 252 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { 253 printer->Print(variables_, 254 "public $type$[] $name$;\n"); 255 } 256 257 void RepeatedMessageFieldGenerator:: 258 GenerateClearCode(io::Printer* printer) const { 259 printer->Print(variables_, 260 "$name$ = $type$.emptyArray();\n"); 261 } 262 263 void RepeatedMessageFieldGenerator:: 264 GenerateMergingCode(io::Printer* printer) const { 265 // First, figure out the length of the array, then parse. 266 printer->Print(variables_, 267 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" 268 " .getRepeatedFieldArrayLength(input, $tag$);\n" 269 "int i = this.$name$ == null ? 0 : this.$name$.length;\n" 270 "$type$[] newArray =\n" 271 " new $type$[i + arrayLength];\n" 272 "if (i != 0) {\n" 273 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" 274 "}\n" 275 "for (; i < newArray.length - 1; i++) {\n" 276 " newArray[i] = new $type$();\n"); 277 278 if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { 279 printer->Print(variables_, 280 " input.readGroup(newArray[i], $number$);\n"); 281 } else { 282 printer->Print(variables_, 283 " input.readMessage(newArray[i]);\n"); 284 } 285 286 printer->Print(variables_, 287 " input.readTag();\n" 288 "}\n" 289 "// Last one without readTag.\n" 290 "newArray[i] = new $type$();\n"); 291 292 if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { 293 printer->Print(variables_, 294 "input.readGroup(newArray[i], $number$);\n"); 295 } else { 296 printer->Print(variables_, 297 "input.readMessage(newArray[i]);\n"); 298 } 299 300 printer->Print(variables_, 301 "this.$name$ = newArray;\n"); 302 } 303 304 void RepeatedMessageFieldGenerator:: 305 GenerateSerializationCode(io::Printer* printer) const { 306 printer->Print(variables_, 307 "if (this.$name$ != null && this.$name$.length > 0) {\n" 308 " for (int i = 0; i < this.$name$.length; i++) {\n" 309 " $type$ element = this.$name$[i];\n" 310 " if (element != null) {\n" 311 " output.write$group_or_message$($number$, element);\n" 312 " }\n" 313 " }\n" 314 "}\n"); 315 } 316 317 void RepeatedMessageFieldGenerator:: 318 GenerateSerializedSizeCode(io::Printer* printer) const { 319 printer->Print(variables_, 320 "if (this.$name$ != null && this.$name$.length > 0) {\n" 321 " for (int i = 0; i < this.$name$.length; i++) {\n" 322 " $type$ element = this.$name$[i];\n" 323 " if (element != null) {\n" 324 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" 325 " .compute$group_or_message$Size($number$, element);\n" 326 " }\n" 327 " }\n" 328 "}\n"); 329 } 330 331 void RepeatedMessageFieldGenerator:: 332 GenerateFixClonedCode(io::Printer* printer) const { 333 printer->Print(variables_, 334 "if (this.$name$ != null && this.$name$.length > 0) {\n" 335 " cloned.$name$ = new $type$[this.$name$.length];\n" 336 " for (int i = 0; i < this.$name$.length; i++) {\n" 337 " if (this.$name$[i] != null) {\n" 338 " cloned.$name$[i] = this.$name$[i].clone();\n" 339 " }\n" 340 " }\n" 341 "}\n"); 342 } 343 344 void RepeatedMessageFieldGenerator:: 345 GenerateEqualsCode(io::Printer* printer) const { 346 printer->Print(variables_, 347 "if (!com.google.protobuf.nano.InternalNano.equals(\n" 348 " this.$name$, other.$name$)) {\n" 349 " return false;\n" 350 "}\n"); 351 } 352 353 void RepeatedMessageFieldGenerator:: 354 GenerateHashCodeCode(io::Printer* printer) const { 355 printer->Print(variables_, 356 "result = 31 * result\n" 357 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); 358 } 359 360 } // namespace javanano 361 } // namespace compiler 362 } // namespace protobuf 363 } // namespace google 364