javanano_message.cc revision 7e02f374901ff471db5140f415de157ac6243050
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 <algorithm> 36#include <google/protobuf/stubs/hash.h> 37#include <google/protobuf/compiler/javanano/javanano_message.h> 38#include <google/protobuf/compiler/javanano/javanano_enum.h> 39#include <google/protobuf/compiler/javanano/javanano_extension.h> 40#include <google/protobuf/compiler/javanano/javanano_helpers.h> 41#include <google/protobuf/stubs/strutil.h> 42#include <google/protobuf/io/printer.h> 43#include <google/protobuf/io/coded_stream.h> 44#include <google/protobuf/wire_format.h> 45#include <google/protobuf/descriptor.pb.h> 46 47namespace google { 48namespace protobuf { 49namespace compiler { 50namespace javanano { 51 52using internal::WireFormat; 53using internal::WireFormatLite; 54 55namespace { 56 57void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { 58 // Print the field's proto-syntax definition as a comment. We don't want to 59 // print group bodies so we cut off after the first line. 60 string def = field->DebugString(); 61 printer->Print("// $def$\n", 62 "def", def.substr(0, def.find_first_of('\n'))); 63} 64 65struct FieldOrderingByNumber { 66 inline bool operator()(const FieldDescriptor* a, 67 const FieldDescriptor* b) const { 68 return a->number() < b->number(); 69 } 70}; 71 72// Sort the fields of the given Descriptor by number into a new[]'d array 73// and return it. 74const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { 75 const FieldDescriptor** fields = 76 new const FieldDescriptor*[descriptor->field_count()]; 77 for (int i = 0; i < descriptor->field_count(); i++) { 78 fields[i] = descriptor->field(i); 79 } 80 sort(fields, fields + descriptor->field_count(), 81 FieldOrderingByNumber()); 82 return fields; 83} 84 85// Get an identifier that uniquely identifies this type within the file. 86// This is used to declare static variables related to this type at the 87// outermost file scope. 88string UniqueFileScopeIdentifier(const Descriptor* descriptor) { 89 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); 90} 91 92} // namespace 93 94// =================================================================== 95 96MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params) 97 : params_(params), 98 descriptor_(descriptor), 99 field_generators_(descriptor, params) { 100} 101 102MessageGenerator::~MessageGenerator() {} 103 104void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { 105 // Generate static members for all nested types. 106 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 107 // TODO(kenton): Reuse MessageGenerator objects? 108 MessageGenerator(descriptor_->nested_type(i), params_) 109 .GenerateStaticVariables(printer); 110 } 111} 112 113void MessageGenerator::GenerateStaticVariableInitializers( 114 io::Printer* printer) { 115 // Generate static member initializers for all nested types. 116 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 117 // TODO(kenton): Reuse MessageGenerator objects? 118 MessageGenerator(descriptor_->nested_type(i), params_) 119 .GenerateStaticVariableInitializers(printer); 120 } 121} 122 123void MessageGenerator::Generate(io::Printer* printer) { 124 if (!params_.store_unknown_fields() && 125 (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) { 126 GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the " 127 "'store_unknown_fields' generator option is 'true'\n"; 128 } 129 130 const string& file_name = descriptor_->file()->name(); 131 bool is_own_file = 132 params_.java_multiple_files(file_name) 133 && descriptor_->containing_type() == NULL; 134 135 if (is_own_file) { 136 // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below) 137 // may have the same names as constants in the nested classes. This causes Java warnings, but 138 // is not fatal, so we suppress those warnings here in the top-most class declaration. 139 printer->Print( 140 "\n" 141 "@SuppressWarnings(\"hiding\")\n" 142 "public final class $classname$ extends\n", 143 "classname", descriptor_->name()); 144 } else { 145 printer->Print( 146 "\n" 147 "public static final class $classname$ extends\n", 148 "classname", descriptor_->name()); 149 } 150 if (params_.store_unknown_fields()) { 151 printer->Print( 152 " com.google.protobuf.nano.ExtendableMessageNano {\n"); 153 } else { 154 printer->Print( 155 " com.google.protobuf.nano.MessageNano {\n"); 156 } 157 printer->Indent(); 158 printer->Print( 159 "\n" 160 "public static final $classname$[] EMPTY_ARRAY = {};\n" 161 "\n" 162 "public $classname$() {\n" 163 " clear();\n" 164 "}\n", 165 "classname", descriptor_->name()); 166 167 // Nested types and extensions 168 for (int i = 0; i < descriptor_->extension_count(); i++) { 169 ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); 170 } 171 172 for (int i = 0; i < descriptor_->enum_type_count(); i++) { 173 EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer); 174 } 175 176 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 177 MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); 178 } 179 180 // Integers for bit fields 181 int totalInts = (field_generators_.total_bits() + 31) / 32; 182 if (totalInts > 0) { 183 printer->Print("\n"); 184 for (int i = 0; i < totalInts; i++) { 185 printer->Print("private int $bit_field_name$;\n", 186 "bit_field_name", GetBitFieldName(i)); 187 } 188 } 189 190 // Fields 191 for (int i = 0; i < descriptor_->field_count(); i++) { 192 printer->Print("\n"); 193 PrintFieldComment(printer, descriptor_->field(i)); 194 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); 195 } 196 197 GenerateClear(printer); 198 199 if (params_.generate_equals()) { 200 GenerateEquals(printer); 201 GenerateHashCode(printer); 202 } 203 204 GenerateMessageSerializationMethods(printer); 205 GenerateMergeFromMethods(printer); 206 GenerateParseFromMethods(printer); 207 208 printer->Outdent(); 209 printer->Print("}\n"); 210} 211 212// =================================================================== 213 214void MessageGenerator:: 215GenerateMessageSerializationMethods(io::Printer* printer) { 216 scoped_array<const FieldDescriptor*> sorted_fields( 217 SortFieldsByNumber(descriptor_)); 218 219 // writeTo only throws an exception if it contains one or more fields to write 220 if (descriptor_->field_count() > 0 || params_.store_unknown_fields()) { 221 printer->Print( 222 "\n" 223 "@Override\n" 224 "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n" 225 " throws java.io.IOException {\n"); 226 } else { 227 printer->Print( 228 "\n" 229 "@Override\n" 230 "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output) {\n"); 231 } 232 printer->Indent(); 233 234 // Output the fields in sorted order 235 for (int i = 0; i < descriptor_->field_count(); i++) { 236 GenerateSerializeOneField(printer, sorted_fields[i]); 237 } 238 239 // Write unknown fields. 240 if (params_.store_unknown_fields()) { 241 printer->Print( 242 "com.google.protobuf.nano.WireFormatNano.writeUnknownFields(\n" 243 " unknownFieldData, output);\n"); 244 } 245 246 printer->Outdent(); 247 printer->Print("}\n"); 248 249 // Rely on the parent implementation of getSerializedSize if there are no fields to 250 // serialize in this MessageNano. 251 if (descriptor_->field_count() != 0) { 252 printer->Print( 253 "\n" 254 "@Override\n" 255 "public int getSerializedSize() {\n" 256 " int size = super.getSerializedSize();\n"); 257 printer->Indent(); 258 259 for (int i = 0; i < descriptor_->field_count(); i++) { 260 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); 261 } 262 263 printer->Outdent(); 264 printer->Print( 265 " cachedSize = size;\n" 266 " return size;\n" 267 "}\n"); 268 } 269} 270 271void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { 272 scoped_array<const FieldDescriptor*> sorted_fields( 273 SortFieldsByNumber(descriptor_)); 274 275 printer->Print( 276 "\n" 277 "@Override\n" 278 "public $classname$ mergeFrom(\n" 279 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" 280 " throws java.io.IOException {\n", 281 "classname", descriptor_->name()); 282 283 printer->Indent(); 284 285 printer->Print( 286 "while (true) {\n"); 287 printer->Indent(); 288 289 printer->Print( 290 "int tag = input.readTag();\n" 291 "switch (tag) {\n"); 292 printer->Indent(); 293 294 printer->Print( 295 "case 0:\n" // zero signals EOF / limit reached 296 " return this;\n" 297 "default: {\n"); 298 299 printer->Indent(); 300 if (params_.store_unknown_fields()) { 301 printer->Print( 302 "if (unknownFieldData == null) {\n" 303 " unknownFieldData =\n" 304 " new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n" 305 "}\n" 306 "if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(\n" 307 " unknownFieldData, input, tag)) {\n" 308 " return this;\n" 309 "}\n"); 310 } else { 311 printer->Print( 312 "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" 313 " return this;\n" // it's an endgroup tag 314 "}\n"); 315 } 316 printer->Print("break;\n"); 317 printer->Outdent(); 318 printer->Print("}\n"); 319 320 for (int i = 0; i < descriptor_->field_count(); i++) { 321 const FieldDescriptor* field = sorted_fields[i]; 322 uint32 tag = WireFormatLite::MakeTag(field->number(), 323 WireFormat::WireTypeForField(field)); 324 325 printer->Print( 326 "case $tag$: {\n", 327 "tag", SimpleItoa(tag)); 328 printer->Indent(); 329 330 field_generators_.get(field).GenerateMergingCode(printer); 331 332 printer->Outdent(); 333 printer->Print( 334 " break;\n" 335 "}\n"); 336 } 337 338 printer->Outdent(); 339 printer->Outdent(); 340 printer->Outdent(); 341 printer->Print( 342 " }\n" // switch (tag) 343 " }\n" // while (true) 344 "}\n"); 345} 346 347void MessageGenerator:: 348GenerateParseFromMethods(io::Printer* printer) { 349 // Note: These are separate from GenerateMessageSerializationMethods() 350 // because they need to be generated even for messages that are optimized 351 // for code size. 352 printer->Print( 353 "\n" 354 "public static $classname$ parseFrom(byte[] data)\n" 355 " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n" 356 " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n" 357 "}\n" 358 "\n" 359 "public static $classname$ parseFrom(\n" 360 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" 361 " throws java.io.IOException {\n" 362 " return new $classname$().mergeFrom(input);\n" 363 "}\n", 364 "classname", descriptor_->name()); 365} 366 367void MessageGenerator::GenerateSerializeOneField( 368 io::Printer* printer, const FieldDescriptor* field) { 369 field_generators_.get(field).GenerateSerializationCode(printer); 370} 371 372void MessageGenerator::GenerateClear(io::Printer* printer) { 373 printer->Print( 374 "\n" 375 "public $classname$ clear() {\n", 376 "classname", descriptor_->name()); 377 printer->Indent(); 378 379 // Clear bit fields. 380 int totalInts = (field_generators_.total_bits() + 31) / 32; 381 for (int i = 0; i < totalInts; i++) { 382 printer->Print("$bit_field_name$ = 0;\n", 383 "bit_field_name", GetBitFieldName(i)); 384 } 385 386 // Call clear for all of the fields. 387 for (int i = 0; i < descriptor_->field_count(); i++) { 388 const FieldDescriptor* field = descriptor_->field(i); 389 field_generators_.get(field).GenerateClearCode(printer); 390 } 391 392 // Clear unknown fields. 393 if (params_.store_unknown_fields()) { 394 printer->Print("unknownFieldData = null;\n"); 395 } 396 397 printer->Outdent(); 398 printer->Print( 399 " cachedSize = -1;\n" 400 " return this;\n" 401 "}\n"); 402} 403 404void MessageGenerator::GenerateEquals(io::Printer* printer) { 405 // Don't override if there are no fields. We could generate an 406 // equals method that compares types, but often empty messages 407 // are used as namespaces. 408 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 409 return; 410 } 411 412 printer->Print( 413 "\n" 414 "@Override\n" 415 "public boolean equals(Object o) {\n"); 416 printer->Indent(); 417 printer->Print( 418 "if (o == this) {\n" 419 " return true;\n" 420 "}\n" 421 "if (!(o instanceof $classname$)) {\n" 422 " return false;\n" 423 "}\n" 424 "$classname$ other = ($classname$) o;\n", 425 "classname", descriptor_->name()); 426 427 for (int i = 0; i < descriptor_->field_count(); i++) { 428 const FieldDescriptor* field = descriptor_->field(i); 429 field_generators_.get(field).GenerateEqualsCode(printer); 430 } 431 432 if (params_.store_unknown_fields()) { 433 printer->Print( 434 "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" 435 " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();" 436 "} else {\n" 437 " return unknownFieldData.equals(other.unknownFieldData);\n" 438 "}\n"); 439 } else { 440 printer->Print( 441 "return true;\n"); 442 } 443 444 printer->Outdent(); 445 printer->Print("}\n"); 446} 447 448void MessageGenerator::GenerateHashCode(io::Printer* printer) { 449 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 450 return; 451 } 452 453 printer->Print( 454 "\n" 455 "@Override\n" 456 "public int hashCode() {\n"); 457 printer->Indent(); 458 459 printer->Print("int result = 17;\n"); 460 for (int i = 0; i < descriptor_->field_count(); i++) { 461 const FieldDescriptor* field = descriptor_->field(i); 462 field_generators_.get(field).GenerateHashCodeCode(printer); 463 } 464 465 if (params_.store_unknown_fields()) { 466 printer->Print( 467 "result = 31 * result + (unknownFieldData == null || unknownFieldData.isEmpty()\n" 468 " ? 0 : unknownFieldData.hashCode());\n"); 469 } 470 471 printer->Print("return result;\n"); 472 473 printer->Outdent(); 474 printer->Print("}\n"); 475} 476 477// =================================================================== 478 479} // namespace javanano 480} // namespace compiler 481} // namespace protobuf 482} // namespace google 483