Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698