javanano_message.cc revision fea3fd5cb6ff88b51da60b1f33004944d93a9fce
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::WireTypeForFieldType(field->type())); 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 if (field->is_packable()) { 338 // To make packed = true wire compatible, we generate parsing code from a 339 // packed version of this field regardless of field->options().packed(). 340 uint32 packed_tag = WireFormatLite::MakeTag(field->number(), 341 WireFormatLite::WIRETYPE_LENGTH_DELIMITED); 342 printer->Print( 343 "case $tag$: {\n", 344 "tag", SimpleItoa(packed_tag)); 345 printer->Indent(); 346 347 field_generators_.get(field).GenerateMergingCodeFromPacked(printer); 348 349 printer->Outdent(); 350 printer->Print( 351 " break;\n" 352 "}\n"); 353 } 354 } 355 356 printer->Outdent(); 357 printer->Outdent(); 358 printer->Outdent(); 359 printer->Print( 360 " }\n" // switch (tag) 361 " }\n" // while (true) 362 "}\n"); 363} 364 365void MessageGenerator:: 366GenerateParseFromMethods(io::Printer* printer) { 367 // Note: These are separate from GenerateMessageSerializationMethods() 368 // because they need to be generated even for messages that are optimized 369 // for code size. 370 printer->Print( 371 "\n" 372 "public static $classname$ parseFrom(byte[] data)\n" 373 " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n" 374 " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n" 375 "}\n" 376 "\n" 377 "public static $classname$ parseFrom(\n" 378 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" 379 " throws java.io.IOException {\n" 380 " return new $classname$().mergeFrom(input);\n" 381 "}\n", 382 "classname", descriptor_->name()); 383} 384 385void MessageGenerator::GenerateSerializeOneField( 386 io::Printer* printer, const FieldDescriptor* field) { 387 field_generators_.get(field).GenerateSerializationCode(printer); 388} 389 390void MessageGenerator::GenerateClear(io::Printer* printer) { 391 printer->Print( 392 "\n" 393 "public $classname$ clear() {\n", 394 "classname", descriptor_->name()); 395 printer->Indent(); 396 397 // Clear bit fields. 398 int totalInts = (field_generators_.total_bits() + 31) / 32; 399 for (int i = 0; i < totalInts; i++) { 400 printer->Print("$bit_field_name$ = 0;\n", 401 "bit_field_name", GetBitFieldName(i)); 402 } 403 404 // Call clear for all of the fields. 405 for (int i = 0; i < descriptor_->field_count(); i++) { 406 const FieldDescriptor* field = descriptor_->field(i); 407 field_generators_.get(field).GenerateClearCode(printer); 408 } 409 410 // Clear unknown fields. 411 if (params_.store_unknown_fields()) { 412 printer->Print("unknownFieldData = null;\n"); 413 } 414 415 printer->Outdent(); 416 printer->Print( 417 " cachedSize = -1;\n" 418 " return this;\n" 419 "}\n"); 420} 421 422void MessageGenerator::GenerateEquals(io::Printer* printer) { 423 // Don't override if there are no fields. We could generate an 424 // equals method that compares types, but often empty messages 425 // are used as namespaces. 426 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 427 return; 428 } 429 430 printer->Print( 431 "\n" 432 "@Override\n" 433 "public boolean equals(Object o) {\n"); 434 printer->Indent(); 435 printer->Print( 436 "if (o == this) {\n" 437 " return true;\n" 438 "}\n" 439 "if (!(o instanceof $classname$)) {\n" 440 " return false;\n" 441 "}\n" 442 "$classname$ other = ($classname$) o;\n", 443 "classname", descriptor_->name()); 444 445 for (int i = 0; i < descriptor_->field_count(); i++) { 446 const FieldDescriptor* field = descriptor_->field(i); 447 field_generators_.get(field).GenerateEqualsCode(printer); 448 } 449 450 if (params_.store_unknown_fields()) { 451 printer->Print( 452 "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" 453 " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();" 454 "} else {\n" 455 " return unknownFieldData.equals(other.unknownFieldData);\n" 456 "}\n"); 457 } else { 458 printer->Print( 459 "return true;\n"); 460 } 461 462 printer->Outdent(); 463 printer->Print("}\n"); 464} 465 466void MessageGenerator::GenerateHashCode(io::Printer* printer) { 467 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 468 return; 469 } 470 471 printer->Print( 472 "\n" 473 "@Override\n" 474 "public int hashCode() {\n"); 475 printer->Indent(); 476 477 printer->Print("int result = 17;\n"); 478 for (int i = 0; i < descriptor_->field_count(); i++) { 479 const FieldDescriptor* field = descriptor_->field(i); 480 field_generators_.get(field).GenerateHashCodeCode(printer); 481 } 482 483 if (params_.store_unknown_fields()) { 484 printer->Print( 485 "result = 31 * result + (unknownFieldData == null || unknownFieldData.isEmpty()\n" 486 " ? 0 : unknownFieldData.hashCode());\n"); 487 } 488 489 printer->Print("return result;\n"); 490 491 printer->Outdent(); 492 printer->Print("}\n"); 493} 494 495// =================================================================== 496 497} // namespace javanano 498} // namespace compiler 499} // namespace protobuf 500} // namespace google 501