OLD | NEW |
(Empty) | |
| 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ |
| 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 #include <algorithm> |
| 32 #include <iostream> |
| 33 #include <sstream> |
| 34 |
| 35 #include <google/protobuf/stubs/hash.h> |
| 36 #include <google/protobuf/compiler/objectivec/objectivec_message.h> |
| 37 #include <google/protobuf/compiler/objectivec/objectivec_enum.h> |
| 38 #include <google/protobuf/compiler/objectivec/objectivec_extension.h> |
| 39 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> |
| 40 #include <google/protobuf/stubs/stl_util.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/io/zero_copy_stream_impl.h> |
| 45 #include <google/protobuf/wire_format.h> |
| 46 #include <google/protobuf/wire_format_lite_inl.h> |
| 47 #include <google/protobuf/descriptor.pb.h> |
| 48 |
| 49 namespace google { |
| 50 namespace protobuf { |
| 51 namespace compiler { |
| 52 namespace objectivec { |
| 53 |
| 54 using internal::WireFormat; |
| 55 using internal::WireFormatLite; |
| 56 |
| 57 namespace { |
| 58 struct FieldOrderingByNumber { |
| 59 inline bool operator()(const FieldDescriptor* a, |
| 60 const FieldDescriptor* b) const { |
| 61 return a->number() < b->number(); |
| 62 } |
| 63 }; |
| 64 |
| 65 int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { |
| 66 // The first item in the object structure is our uint32[] for has bits. |
| 67 // We then want to order things to make the instances as small as |
| 68 // possible. So we follow the has bits with: |
| 69 // 1. Bools (1 byte) |
| 70 // 2. Anything always 4 bytes - float, *32, enums |
| 71 // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit |
| 72 // builds and 4 bytes on 32bit builds. |
| 73 // 4. Anything always 8 bytes - double, *64 |
| 74 // |
| 75 // Why? Using 64bit builds as an example, this means worse case, we have |
| 76 // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes |
| 77 // are wasted before the 4 byte values. Then if we have an odd number of |
| 78 // those 4 byte values, the 8 byte values will be pushed down by 32bits to |
| 79 // keep them aligned. But the structure will end 8 byte aligned, so no |
| 80 // waste on the end. If you did the reverse order, you could waste 4 bytes |
| 81 // before the first 8 byte value (after the has array), then a single |
| 82 // bool on the end would need 7 bytes of padding to make the overall |
| 83 // structure 8 byte aligned; so 11 bytes, wasted total. |
| 84 |
| 85 // Anything repeated is a GPB*Array/NSArray, so pointer. |
| 86 if (descriptor->is_repeated()) { |
| 87 return 3; |
| 88 } |
| 89 |
| 90 switch (descriptor->type()) { |
| 91 // All always 8 bytes. |
| 92 case FieldDescriptor::TYPE_DOUBLE: |
| 93 case FieldDescriptor::TYPE_INT64: |
| 94 case FieldDescriptor::TYPE_SINT64: |
| 95 case FieldDescriptor::TYPE_UINT64: |
| 96 case FieldDescriptor::TYPE_SFIXED64: |
| 97 case FieldDescriptor::TYPE_FIXED64: |
| 98 return 4; |
| 99 |
| 100 // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes |
| 101 // depending on the build architecture. |
| 102 case FieldDescriptor::TYPE_GROUP: |
| 103 case FieldDescriptor::TYPE_MESSAGE: |
| 104 case FieldDescriptor::TYPE_STRING: |
| 105 case FieldDescriptor::TYPE_BYTES: |
| 106 return 3; |
| 107 |
| 108 // All always 4 bytes (enums are int32s). |
| 109 case FieldDescriptor::TYPE_FLOAT: |
| 110 case FieldDescriptor::TYPE_INT32: |
| 111 case FieldDescriptor::TYPE_SINT32: |
| 112 case FieldDescriptor::TYPE_UINT32: |
| 113 case FieldDescriptor::TYPE_SFIXED32: |
| 114 case FieldDescriptor::TYPE_FIXED32: |
| 115 case FieldDescriptor::TYPE_ENUM: |
| 116 return 2; |
| 117 |
| 118 // 1 byte. |
| 119 case FieldDescriptor::TYPE_BOOL: |
| 120 return 1; |
| 121 } |
| 122 |
| 123 // Some compilers report reaching end of function even though all cases of |
| 124 // the enum are handed in the switch. |
| 125 GOOGLE_LOG(FATAL) << "Can't get here."; |
| 126 return 0; |
| 127 } |
| 128 |
| 129 struct FieldOrderingByStorageSize { |
| 130 inline bool operator()(const FieldDescriptor* a, |
| 131 const FieldDescriptor* b) const { |
| 132 // Order by grouping. |
| 133 const int order_group_a = OrderGroupForFieldDescriptor(a); |
| 134 const int order_group_b = OrderGroupForFieldDescriptor(b); |
| 135 if (order_group_a != order_group_b) { |
| 136 return order_group_a < order_group_b; |
| 137 } |
| 138 // Within the group, order by field number (provides stable ordering). |
| 139 return a->number() < b->number(); |
| 140 } |
| 141 }; |
| 142 |
| 143 struct ExtensionRangeOrdering { |
| 144 bool operator()(const Descriptor::ExtensionRange* a, |
| 145 const Descriptor::ExtensionRange* b) const { |
| 146 return a->start < b->start; |
| 147 } |
| 148 }; |
| 149 |
| 150 // Sort the fields of the given Descriptor by number into a new[]'d array |
| 151 // and return it. |
| 152 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { |
| 153 const FieldDescriptor** fields = |
| 154 new const FieldDescriptor* [descriptor->field_count()]; |
| 155 for (int i = 0; i < descriptor->field_count(); i++) { |
| 156 fields[i] = descriptor->field(i); |
| 157 } |
| 158 sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber()); |
| 159 return fields; |
| 160 } |
| 161 |
| 162 // Sort the fields of the given Descriptor by storage size into a new[]'d |
| 163 // array and return it. |
| 164 const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { |
| 165 const FieldDescriptor** fields = |
| 166 new const FieldDescriptor* [descriptor->field_count()]; |
| 167 for (int i = 0; i < descriptor->field_count(); i++) { |
| 168 fields[i] = descriptor->field(i); |
| 169 } |
| 170 sort(fields, fields + descriptor->field_count(), |
| 171 FieldOrderingByStorageSize()); |
| 172 return fields; |
| 173 } |
| 174 } // namespace |
| 175 |
| 176 MessageGenerator::MessageGenerator(const string& root_classname, |
| 177 const Descriptor* descriptor) |
| 178 : root_classname_(root_classname), |
| 179 descriptor_(descriptor), |
| 180 field_generators_(descriptor), |
| 181 class_name_(ClassName(descriptor_)) { |
| 182 for (int i = 0; i < descriptor_->extension_count(); i++) { |
| 183 extension_generators_.push_back( |
| 184 new ExtensionGenerator(class_name_, descriptor_->extension(i))); |
| 185 } |
| 186 |
| 187 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 188 OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); |
| 189 oneof_generators_.push_back(generator); |
| 190 } |
| 191 |
| 192 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 193 EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); |
| 194 enum_generators_.push_back(generator); |
| 195 } |
| 196 |
| 197 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 198 MessageGenerator* generator = |
| 199 new MessageGenerator(root_classname_, descriptor_->nested_type(i)); |
| 200 nested_message_generators_.push_back(generator); |
| 201 } |
| 202 } |
| 203 |
| 204 MessageGenerator::~MessageGenerator() { |
| 205 STLDeleteContainerPointers(extension_generators_.begin(), |
| 206 extension_generators_.end()); |
| 207 STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); |
| 208 STLDeleteContainerPointers(nested_message_generators_.begin(), |
| 209 nested_message_generators_.end()); |
| 210 STLDeleteContainerPointers(oneof_generators_.begin(), |
| 211 oneof_generators_.end()); |
| 212 } |
| 213 |
| 214 void MessageGenerator::GenerateStaticVariablesInitialization( |
| 215 io::Printer* printer) { |
| 216 for (vector<ExtensionGenerator*>::iterator iter = |
| 217 extension_generators_.begin(); |
| 218 iter != extension_generators_.end(); ++iter) { |
| 219 (*iter)->GenerateStaticVariablesInitialization(printer); |
| 220 } |
| 221 |
| 222 for (vector<MessageGenerator*>::iterator iter = |
| 223 nested_message_generators_.begin(); |
| 224 iter != nested_message_generators_.end(); ++iter) { |
| 225 (*iter)->GenerateStaticVariablesInitialization(printer); |
| 226 } |
| 227 } |
| 228 |
| 229 void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) { |
| 230 if (!IsMapEntryMessage(descriptor_)) { |
| 231 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 232 const FieldDescriptor* fieldDescriptor = descriptor_->field(i); |
| 233 // If it is a the field is repeated, the type will be and *Array, and we |
| 234 // don't need any forward decl. |
| 235 if (fieldDescriptor->is_repeated()) { |
| 236 continue; |
| 237 } |
| 238 field_generators_.get(fieldDescriptor) |
| 239 .DetermineForwardDeclarations(fwd_decls); |
| 240 } |
| 241 } |
| 242 |
| 243 for (vector<MessageGenerator*>::iterator iter = |
| 244 nested_message_generators_.begin(); |
| 245 iter != nested_message_generators_.end(); ++iter) { |
| 246 (*iter)->DetermineForwardDeclarations(fwd_decls); |
| 247 } |
| 248 } |
| 249 |
| 250 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { |
| 251 for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); |
| 252 iter != enum_generators_.end(); ++iter) { |
| 253 (*iter)->GenerateHeader(printer); |
| 254 } |
| 255 |
| 256 for (vector<MessageGenerator*>::iterator iter = |
| 257 nested_message_generators_.begin(); |
| 258 iter != nested_message_generators_.end(); ++iter) { |
| 259 (*iter)->GenerateEnumHeader(printer); |
| 260 } |
| 261 } |
| 262 |
| 263 void MessageGenerator::GenerateExtensionRegistrationSource( |
| 264 io::Printer* printer) { |
| 265 for (vector<ExtensionGenerator*>::iterator iter = |
| 266 extension_generators_.begin(); |
| 267 iter != extension_generators_.end(); ++iter) { |
| 268 (*iter)->GenerateRegistrationSource(printer); |
| 269 } |
| 270 |
| 271 for (vector<MessageGenerator*>::iterator iter = |
| 272 nested_message_generators_.begin(); |
| 273 iter != nested_message_generators_.end(); ++iter) { |
| 274 (*iter)->GenerateExtensionRegistrationSource(printer); |
| 275 } |
| 276 } |
| 277 |
| 278 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { |
| 279 // This a a map entry message, just recurse and do nothing directly. |
| 280 if (IsMapEntryMessage(descriptor_)) { |
| 281 for (vector<MessageGenerator*>::iterator iter = |
| 282 nested_message_generators_.begin(); |
| 283 iter != nested_message_generators_.end(); ++iter) { |
| 284 (*iter)->GenerateMessageHeader(printer); |
| 285 } |
| 286 return; |
| 287 } |
| 288 |
| 289 printer->Print( |
| 290 "#pragma mark - $classname$\n" |
| 291 "\n", |
| 292 "classname", class_name_); |
| 293 |
| 294 if (descriptor_->field_count()) { |
| 295 scoped_array<const FieldDescriptor*> sorted_fields( |
| 296 SortFieldsByNumber(descriptor_)); |
| 297 |
| 298 printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", |
| 299 "classname", class_name_); |
| 300 printer->Indent(); |
| 301 |
| 302 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 303 field_generators_.get(sorted_fields[i]) |
| 304 .GenerateFieldNumberConstant(printer); |
| 305 } |
| 306 |
| 307 printer->Outdent(); |
| 308 printer->Print("};\n\n"); |
| 309 } |
| 310 |
| 311 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 312 iter != oneof_generators_.end(); ++iter) { |
| 313 (*iter)->GenerateCaseEnum(printer); |
| 314 } |
| 315 |
| 316 string message_comments; |
| 317 SourceLocation location; |
| 318 if (descriptor_->GetSourceLocation(&location)) { |
| 319 message_comments = BuildCommentsString(location); |
| 320 } else { |
| 321 message_comments = ""; |
| 322 } |
| 323 |
| 324 printer->Print( |
| 325 "$comments$@interface $classname$ : GPBMessage\n\n", |
| 326 "classname", class_name_, |
| 327 "comments", message_comments); |
| 328 |
| 329 vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0); |
| 330 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 331 const FieldDescriptor* field = descriptor_->field(i); |
| 332 if (field->containing_oneof() != NULL) { |
| 333 const int oneof_index = field->containing_oneof()->index(); |
| 334 if (!seen_oneofs[oneof_index]) { |
| 335 seen_oneofs[oneof_index] = 1; |
| 336 oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( |
| 337 printer); |
| 338 } |
| 339 } |
| 340 field_generators_.get(field).GeneratePropertyDeclaration(printer); |
| 341 } |
| 342 |
| 343 printer->Print("@end\n\n"); |
| 344 |
| 345 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 346 field_generators_.get(descriptor_->field(i)) |
| 347 .GenerateCFunctionDeclarations(printer); |
| 348 } |
| 349 |
| 350 if (!oneof_generators_.empty()) { |
| 351 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 352 iter != oneof_generators_.end(); ++iter) { |
| 353 (*iter)->GenerateClearFunctionDeclaration(printer); |
| 354 } |
| 355 printer->Print("\n"); |
| 356 } |
| 357 |
| 358 if (descriptor_->extension_count() > 0) { |
| 359 printer->Print("@interface $classname$ (DynamicMethods)\n\n", |
| 360 "classname", class_name_); |
| 361 for (vector<ExtensionGenerator*>::iterator iter = |
| 362 extension_generators_.begin(); |
| 363 iter != extension_generators_.end(); ++iter) { |
| 364 (*iter)->GenerateMembersHeader(printer); |
| 365 } |
| 366 printer->Print("@end\n\n"); |
| 367 } |
| 368 |
| 369 for (vector<MessageGenerator*>::iterator iter = |
| 370 nested_message_generators_.begin(); |
| 371 iter != nested_message_generators_.end(); ++iter) { |
| 372 (*iter)->GenerateMessageHeader(printer); |
| 373 } |
| 374 } |
| 375 |
| 376 void MessageGenerator::GenerateSource(io::Printer* printer) { |
| 377 if (!IsMapEntryMessage(descriptor_)) { |
| 378 printer->Print( |
| 379 "#pragma mark - $classname$\n" |
| 380 "\n", |
| 381 "classname", class_name_); |
| 382 |
| 383 printer->Print("@implementation $classname$\n\n", |
| 384 "classname", class_name_); |
| 385 |
| 386 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 387 iter != oneof_generators_.end(); ++iter) { |
| 388 (*iter)->GeneratePropertyImplementation(printer); |
| 389 } |
| 390 |
| 391 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 392 field_generators_.get(descriptor_->field(i)) |
| 393 .GeneratePropertyImplementation(printer); |
| 394 } |
| 395 |
| 396 scoped_array<const FieldDescriptor*> sorted_fields( |
| 397 SortFieldsByNumber(descriptor_)); |
| 398 scoped_array<const FieldDescriptor*> size_order_fields( |
| 399 SortFieldsByStorageSize(descriptor_)); |
| 400 |
| 401 vector<const Descriptor::ExtensionRange*> sorted_extensions; |
| 402 for (int i = 0; i < descriptor_->extension_range_count(); ++i) { |
| 403 sorted_extensions.push_back(descriptor_->extension_range(i)); |
| 404 } |
| 405 |
| 406 sort(sorted_extensions.begin(), sorted_extensions.end(), |
| 407 ExtensionRangeOrdering()); |
| 408 |
| 409 // TODO(thomasvl): Finish optimizing has bit. The current behavior is as |
| 410 // follows: |
| 411 // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index |
| 412 // to the field's index in the list of fields. |
| 413 // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to |
| 414 // GPBNoHasBit because repeated fields & map<> fields don't use the has |
| 415 // bit. |
| 416 // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative |
| 417 // index that groups all the elements on of the oneof. |
| 418 // So in has_storage, we need enough bits for the single fields that aren't |
| 419 // in any oneof, and then one int32 for each oneof (to store the field |
| 420 // number). So we could save a little space by not using the field's index |
| 421 // and instead make a second pass only assigning indexes for the fields |
| 422 // that would need it. The only savings would come when messages have over |
| 423 // a multiple of 32 fields with some number being repeated or in oneofs to |
| 424 // drop the count below that 32 multiple; so it hasn't seemed worth doing |
| 425 // at the moment. |
| 426 size_t num_has_bits = descriptor_->field_count(); |
| 427 size_t sizeof_has_storage = (num_has_bits + 31) / 32; |
| 428 // Tell all the fields the oneof base. |
| 429 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 430 iter != oneof_generators_.end(); ++iter) { |
| 431 (*iter)->SetOneofIndexBase(sizeof_has_storage); |
| 432 } |
| 433 field_generators_.SetOneofIndexBase(sizeof_has_storage); |
| 434 // Add an int32 for each oneof to store which is set. |
| 435 sizeof_has_storage += descriptor_->oneof_decl_count(); |
| 436 |
| 437 printer->Print( |
| 438 "\n" |
| 439 "typedef struct $classname$__storage_ {\n" |
| 440 " uint32_t _has_storage_[$sizeof_has_storage$];\n", |
| 441 "classname", class_name_, |
| 442 "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); |
| 443 printer->Indent(); |
| 444 |
| 445 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 446 field_generators_.get(size_order_fields[i]) |
| 447 .GenerateFieldStorageDeclaration(printer); |
| 448 } |
| 449 printer->Outdent(); |
| 450 |
| 451 printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); |
| 452 |
| 453 |
| 454 printer->Print( |
| 455 "// This method is threadsafe because it is initially called\n" |
| 456 "// in +initialize for each subclass.\n" |
| 457 "+ (GPBDescriptor *)descriptor {\n" |
| 458 " static GPBDescriptor *descriptor = nil;\n" |
| 459 " if (!descriptor) {\n"); |
| 460 |
| 461 bool has_oneofs = oneof_generators_.size(); |
| 462 if (has_oneofs) { |
| 463 printer->Print( |
| 464 " static GPBMessageOneofDescription oneofs[] = {\n"); |
| 465 printer->Indent(); |
| 466 printer->Indent(); |
| 467 printer->Indent(); |
| 468 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 469 iter != oneof_generators_.end(); ++iter) { |
| 470 (*iter)->GenerateDescription(printer); |
| 471 } |
| 472 printer->Outdent(); |
| 473 printer->Outdent(); |
| 474 printer->Outdent(); |
| 475 printer->Print( |
| 476 " };\n"); |
| 477 } |
| 478 |
| 479 TextFormatDecodeData text_format_decode_data; |
| 480 bool has_fields = descriptor_->field_count() > 0; |
| 481 if (has_fields) { |
| 482 // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription() |
| 483 // wraps the fieldOptions's value of this structure in an CPP gate so |
| 484 // they can be compiled away; but that still results in a const char* in |
| 485 // the structure for a NULL pointer for every message field. If the |
| 486 // fieldOptions are moved to a separate payload like the TextFormat extra |
| 487 // data is, then it would shrink that static data shrinking the binaries |
| 488 // a little more. |
| 489 // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the |
| 490 // structure because primitive types are always zero. If we add a second |
| 491 // structure and a different initializer, we can avoid the wasted static |
| 492 // storage for every field in a proto3 message. |
| 493 printer->Print( |
| 494 " static GPBMessageFieldDescription fields[] = {\n"); |
| 495 printer->Indent(); |
| 496 printer->Indent(); |
| 497 printer->Indent(); |
| 498 for (int i = 0; i < descriptor_->field_count(); ++i) { |
| 499 const FieldGenerator& field_generator = |
| 500 field_generators_.get(sorted_fields[i]); |
| 501 field_generator.GenerateFieldDescription(printer); |
| 502 if (field_generator.needs_textformat_name_support()) { |
| 503 text_format_decode_data.AddString(sorted_fields[i]->number(), |
| 504 field_generator.generated_objc_name(
), |
| 505 field_generator.raw_field_name()); |
| 506 } |
| 507 } |
| 508 printer->Outdent(); |
| 509 printer->Outdent(); |
| 510 printer->Outdent(); |
| 511 printer->Print( |
| 512 " };\n"); |
| 513 } |
| 514 |
| 515 bool has_enums = enum_generators_.size(); |
| 516 if (has_enums) { |
| 517 printer->Print( |
| 518 " static GPBMessageEnumDescription enums[] = {\n"); |
| 519 printer->Indent(); |
| 520 printer->Indent(); |
| 521 printer->Indent(); |
| 522 for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); |
| 523 iter != enum_generators_.end(); ++iter) { |
| 524 printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n", |
| 525 "name", (*iter)->name()); |
| 526 } |
| 527 printer->Outdent(); |
| 528 printer->Outdent(); |
| 529 printer->Outdent(); |
| 530 printer->Print( |
| 531 " };\n"); |
| 532 } |
| 533 |
| 534 bool has_extensions = sorted_extensions.size(); |
| 535 if (has_extensions) { |
| 536 printer->Print( |
| 537 " static GPBExtensionRange ranges[] = {\n"); |
| 538 printer->Indent(); |
| 539 printer->Indent(); |
| 540 printer->Indent(); |
| 541 for (int i = 0; i < sorted_extensions.size(); i++) { |
| 542 printer->Print("{ .start = $start$, .end = $end$ },\n", |
| 543 "start", SimpleItoa(sorted_extensions[i]->start), |
| 544 "end", SimpleItoa(sorted_extensions[i]->end)); |
| 545 } |
| 546 printer->Outdent(); |
| 547 printer->Outdent(); |
| 548 printer->Outdent(); |
| 549 printer->Print( |
| 550 " };\n"); |
| 551 } |
| 552 |
| 553 map<string, string> vars; |
| 554 vars["classname"] = class_name_; |
| 555 vars["rootclassname"] = root_classname_; |
| 556 vars["fields"] = has_fields ? "fields" : "NULL"; |
| 557 vars["fields_count"] = |
| 558 has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0"
; |
| 559 vars["oneofs"] = has_oneofs ? "oneofs" : "NULL"; |
| 560 vars["oneof_count"] = |
| 561 has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0"
; |
| 562 vars["enums"] = has_enums ? "enums" : "NULL"; |
| 563 vars["enum_count"] = |
| 564 has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0"; |
| 565 vars["ranges"] = has_extensions ? "ranges" : "NULL"; |
| 566 vars["range_count"] = |
| 567 has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0"; |
| 568 vars["wireformat"] = |
| 569 descriptor_->options().message_set_wire_format() ? "YES" : "NO"; |
| 570 |
| 571 if (text_format_decode_data.num_entries() == 0) { |
| 572 printer->Print( |
| 573 vars, |
| 574 " GPBDescriptor *localDescriptor =\n" |
| 575 " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" |
| 576 " rootClass:[$rootclassname$ class
]\n" |
| 577 " file:$rootclassname$_FileDe
scriptor()\n" |
| 578 " fields:$fields$\n" |
| 579 " fieldCount:$fields_count$\n" |
| 580 " oneofs:$oneofs$\n" |
| 581 " oneofCount:$oneof_count$\n" |
| 582 " enums:$enums$\n" |
| 583 " enumCount:$enum_count$\n" |
| 584 " ranges:$ranges$\n" |
| 585 " rangeCount:$range_count$\n" |
| 586 " storageSize:sizeof($classname$__st
orage_)\n" |
| 587 " wireFormat:$wireformat$];\n"); |
| 588 } else { |
| 589 vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data()); |
| 590 printer->Print( |
| 591 vars, |
| 592 "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" |
| 593 " const char *extraTextFormatInfo = NULL;\n" |
| 594 "#else\n" |
| 595 " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\
";\n" |
| 596 "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" |
| 597 " GPBDescriptor *localDescriptor =\n" |
| 598 " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" |
| 599 " rootClass:[$rootclassname$ class
]\n" |
| 600 " file:$rootclassname$_FileDe
scriptor()\n" |
| 601 " fields:$fields$\n" |
| 602 " fieldCount:$fields_count$\n" |
| 603 " oneofs:$oneofs$\n" |
| 604 " oneofCount:$oneof_count$\n" |
| 605 " enums:$enums$\n" |
| 606 " enumCount:$enum_count$\n" |
| 607 " ranges:$ranges$\n" |
| 608 " rangeCount:$range_count$\n" |
| 609 " storageSize:sizeof($classname$__st
orage_)\n" |
| 610 " wireFormat:$wireformat$\n" |
| 611 " extraTextFormatInfo:extraTextFormatInfo];\
n"); |
| 612 } |
| 613 printer->Print( |
| 614 " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" |
| 615 " descriptor = localDescriptor;\n" |
| 616 " }\n" |
| 617 " return descriptor;\n" |
| 618 "}\n\n" |
| 619 "@end\n\n"); |
| 620 |
| 621 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 622 field_generators_.get(descriptor_->field(i)) |
| 623 .GenerateCFunctionImplementations(printer); |
| 624 } |
| 625 |
| 626 for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); |
| 627 iter != oneof_generators_.end(); ++iter) { |
| 628 (*iter)->GenerateClearFunctionImplementation(printer); |
| 629 } |
| 630 } |
| 631 |
| 632 for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); |
| 633 iter != enum_generators_.end(); ++iter) { |
| 634 (*iter)->GenerateSource(printer); |
| 635 } |
| 636 |
| 637 for (vector<MessageGenerator*>::iterator iter = |
| 638 nested_message_generators_.begin(); |
| 639 iter != nested_message_generators_.end(); ++iter) { |
| 640 (*iter)->GenerateSource(printer); |
| 641 } |
| 642 } |
| 643 |
| 644 } // namespace objectivec |
| 645 } // namespace compiler |
| 646 } // namespace protobuf |
| 647 } // namespace google |
OLD | NEW |