Line data Source code
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 0 : inline bool operator()(const FieldDescriptor* a,
60 0 : const FieldDescriptor* b) const {
61 0 : return a->number() < b->number();
62 : }
63 : };
64 :
65 0 : 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 0 : if (descriptor->is_repeated()) {
87 : return 3;
88 : }
89 :
90 0 : 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 0 : 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 0 : return 2;
117 :
118 : // 1 byte.
119 : case FieldDescriptor::TYPE_BOOL:
120 0 : 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 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
126 0 : return 0;
127 : }
128 :
129 : struct FieldOrderingByStorageSize {
130 0 : inline bool operator()(const FieldDescriptor* a,
131 0 : const FieldDescriptor* b) const {
132 : // Order by grouping.
133 0 : const int order_group_a = OrderGroupForFieldDescriptor(a);
134 0 : const int order_group_b = OrderGroupForFieldDescriptor(b);
135 0 : if (order_group_a != order_group_b) {
136 0 : return order_group_a < order_group_b;
137 : }
138 : // Within the group, order by field number (provides stable ordering).
139 0 : 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 0 : const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
153 : const FieldDescriptor** fields =
154 0 : new const FieldDescriptor* [descriptor->field_count()];
155 0 : for (int i = 0; i < descriptor->field_count(); i++) {
156 0 : fields[i] = descriptor->field(i);
157 : }
158 0 : sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
159 0 : 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 0 : const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
165 : const FieldDescriptor** fields =
166 0 : new const FieldDescriptor* [descriptor->field_count()];
167 0 : for (int i = 0; i < descriptor->field_count(); i++) {
168 0 : fields[i] = descriptor->field(i);
169 : }
170 0 : sort(fields, fields + descriptor->field_count(),
171 0 : FieldOrderingByStorageSize());
172 0 : return fields;
173 : }
174 : } // namespace
175 :
176 0 : MessageGenerator::MessageGenerator(const string& root_classname,
177 : const Descriptor* descriptor)
178 : : root_classname_(root_classname),
179 : descriptor_(descriptor),
180 : field_generators_(descriptor),
181 0 : class_name_(ClassName(descriptor_)) {
182 0 : for (int i = 0; i < descriptor_->extension_count(); i++) {
183 : extension_generators_.push_back(
184 0 : new ExtensionGenerator(class_name_, descriptor_->extension(i)));
185 : }
186 :
187 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
188 0 : OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
189 0 : oneof_generators_.push_back(generator);
190 : }
191 :
192 0 : for (int i = 0; i < descriptor_->enum_type_count(); i++) {
193 0 : EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
194 0 : enum_generators_.push_back(generator);
195 : }
196 :
197 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
198 : MessageGenerator* generator =
199 0 : new MessageGenerator(root_classname_, descriptor_->nested_type(i));
200 0 : nested_message_generators_.push_back(generator);
201 : }
202 0 : }
203 :
204 0 : MessageGenerator::~MessageGenerator() {
205 : STLDeleteContainerPointers(extension_generators_.begin(),
206 0 : extension_generators_.end());
207 0 : STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
208 : STLDeleteContainerPointers(nested_message_generators_.begin(),
209 0 : nested_message_generators_.end());
210 : STLDeleteContainerPointers(oneof_generators_.begin(),
211 0 : oneof_generators_.end());
212 0 : }
213 :
214 0 : void MessageGenerator::GenerateStaticVariablesInitialization(
215 : io::Printer* printer) {
216 0 : for (vector<ExtensionGenerator*>::iterator iter =
217 0 : extension_generators_.begin();
218 0 : iter != extension_generators_.end(); ++iter) {
219 0 : (*iter)->GenerateStaticVariablesInitialization(printer);
220 : }
221 :
222 0 : for (vector<MessageGenerator*>::iterator iter =
223 0 : nested_message_generators_.begin();
224 0 : iter != nested_message_generators_.end(); ++iter) {
225 0 : (*iter)->GenerateStaticVariablesInitialization(printer);
226 : }
227 0 : }
228 :
229 0 : void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
230 0 : if (!IsMapEntryMessage(descriptor_)) {
231 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
232 0 : 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 0 : if (fieldDescriptor->is_repeated()) {
236 : continue;
237 : }
238 0 : field_generators_.get(fieldDescriptor)
239 0 : .DetermineForwardDeclarations(fwd_decls);
240 : }
241 : }
242 :
243 0 : for (vector<MessageGenerator*>::iterator iter =
244 0 : nested_message_generators_.begin();
245 0 : iter != nested_message_generators_.end(); ++iter) {
246 0 : (*iter)->DetermineForwardDeclarations(fwd_decls);
247 : }
248 0 : }
249 :
250 0 : void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
251 0 : for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
252 0 : iter != enum_generators_.end(); ++iter) {
253 0 : (*iter)->GenerateHeader(printer);
254 : }
255 :
256 0 : for (vector<MessageGenerator*>::iterator iter =
257 0 : nested_message_generators_.begin();
258 0 : iter != nested_message_generators_.end(); ++iter) {
259 0 : (*iter)->GenerateEnumHeader(printer);
260 : }
261 0 : }
262 :
263 0 : void MessageGenerator::GenerateExtensionRegistrationSource(
264 : io::Printer* printer) {
265 0 : for (vector<ExtensionGenerator*>::iterator iter =
266 0 : extension_generators_.begin();
267 0 : iter != extension_generators_.end(); ++iter) {
268 0 : (*iter)->GenerateRegistrationSource(printer);
269 : }
270 :
271 0 : for (vector<MessageGenerator*>::iterator iter =
272 0 : nested_message_generators_.begin();
273 0 : iter != nested_message_generators_.end(); ++iter) {
274 0 : (*iter)->GenerateExtensionRegistrationSource(printer);
275 : }
276 0 : }
277 :
278 0 : void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
279 : // This a a map entry message, just recurse and do nothing directly.
280 0 : if (IsMapEntryMessage(descriptor_)) {
281 0 : for (vector<MessageGenerator*>::iterator iter =
282 0 : nested_message_generators_.begin();
283 0 : iter != nested_message_generators_.end(); ++iter) {
284 0 : (*iter)->GenerateMessageHeader(printer);
285 : }
286 0 : return;
287 : }
288 :
289 : printer->Print(
290 : "#pragma mark - $classname$\n"
291 : "\n",
292 0 : "classname", class_name_);
293 :
294 0 : if (descriptor_->field_count()) {
295 : scoped_array<const FieldDescriptor*> sorted_fields(
296 0 : SortFieldsByNumber(descriptor_));
297 :
298 : printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
299 0 : "classname", class_name_);
300 0 : printer->Indent();
301 :
302 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
303 0 : field_generators_.get(sorted_fields[i])
304 0 : .GenerateFieldNumberConstant(printer);
305 : }
306 :
307 0 : printer->Outdent();
308 0 : printer->Print("};\n\n");
309 : }
310 :
311 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
312 0 : iter != oneof_generators_.end(); ++iter) {
313 0 : (*iter)->GenerateCaseEnum(printer);
314 : }
315 :
316 : string message_comments;
317 0 : SourceLocation location;
318 0 : if (descriptor_->GetSourceLocation(&location)) {
319 0 : 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 0 : "comments", message_comments);
328 :
329 0 : vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
330 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
331 0 : const FieldDescriptor* field = descriptor_->field(i);
332 0 : if (field->containing_oneof() != NULL) {
333 0 : const int oneof_index = field->containing_oneof()->index();
334 0 : if (!seen_oneofs[oneof_index]) {
335 0 : seen_oneofs[oneof_index] = 1;
336 0 : oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
337 0 : printer);
338 : }
339 : }
340 0 : field_generators_.get(field).GeneratePropertyDeclaration(printer);
341 : }
342 :
343 0 : printer->Print("@end\n\n");
344 :
345 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
346 0 : field_generators_.get(descriptor_->field(i))
347 0 : .GenerateCFunctionDeclarations(printer);
348 : }
349 :
350 0 : if (!oneof_generators_.empty()) {
351 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
352 0 : iter != oneof_generators_.end(); ++iter) {
353 0 : (*iter)->GenerateClearFunctionDeclaration(printer);
354 : }
355 0 : printer->Print("\n");
356 : }
357 :
358 0 : if (descriptor_->extension_count() > 0) {
359 : printer->Print("@interface $classname$ (DynamicMethods)\n\n",
360 0 : "classname", class_name_);
361 0 : for (vector<ExtensionGenerator*>::iterator iter =
362 0 : extension_generators_.begin();
363 0 : iter != extension_generators_.end(); ++iter) {
364 0 : (*iter)->GenerateMembersHeader(printer);
365 : }
366 0 : printer->Print("@end\n\n");
367 : }
368 :
369 0 : for (vector<MessageGenerator*>::iterator iter =
370 0 : nested_message_generators_.begin();
371 0 : iter != nested_message_generators_.end(); ++iter) {
372 0 : (*iter)->GenerateMessageHeader(printer);
373 : }
374 : }
375 :
376 0 : void MessageGenerator::GenerateSource(io::Printer* printer) {
377 0 : if (!IsMapEntryMessage(descriptor_)) {
378 : printer->Print(
379 : "#pragma mark - $classname$\n"
380 : "\n",
381 0 : "classname", class_name_);
382 :
383 : printer->Print("@implementation $classname$\n\n",
384 0 : "classname", class_name_);
385 :
386 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
387 0 : iter != oneof_generators_.end(); ++iter) {
388 0 : (*iter)->GeneratePropertyImplementation(printer);
389 : }
390 :
391 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
392 0 : field_generators_.get(descriptor_->field(i))
393 0 : .GeneratePropertyImplementation(printer);
394 : }
395 :
396 : scoped_array<const FieldDescriptor*> sorted_fields(
397 0 : SortFieldsByNumber(descriptor_));
398 : scoped_array<const FieldDescriptor*> size_order_fields(
399 0 : SortFieldsByStorageSize(descriptor_));
400 :
401 : vector<const Descriptor::ExtensionRange*> sorted_extensions;
402 0 : for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
403 0 : sorted_extensions.push_back(descriptor_->extension_range(i));
404 : }
405 :
406 : sort(sorted_extensions.begin(), sorted_extensions.end(),
407 0 : 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 0 : size_t num_has_bits = descriptor_->field_count();
427 0 : size_t sizeof_has_storage = (num_has_bits + 31) / 32;
428 : // Tell all the fields the oneof base.
429 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
430 0 : iter != oneof_generators_.end(); ++iter) {
431 0 : (*iter)->SetOneofIndexBase(sizeof_has_storage);
432 : }
433 0 : field_generators_.SetOneofIndexBase(sizeof_has_storage);
434 : // Add an int32 for each oneof to store which is set.
435 0 : 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 0 : "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
443 0 : printer->Indent();
444 :
445 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
446 0 : field_generators_.get(size_order_fields[i])
447 0 : .GenerateFieldStorageDeclaration(printer);
448 : }
449 0 : printer->Outdent();
450 :
451 0 : 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 0 : " if (!descriptor) {\n");
460 :
461 0 : bool has_oneofs = oneof_generators_.size();
462 0 : if (has_oneofs) {
463 : printer->Print(
464 0 : " static GPBMessageOneofDescription oneofs[] = {\n");
465 0 : printer->Indent();
466 0 : printer->Indent();
467 0 : printer->Indent();
468 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
469 0 : iter != oneof_generators_.end(); ++iter) {
470 0 : (*iter)->GenerateDescription(printer);
471 : }
472 0 : printer->Outdent();
473 0 : printer->Outdent();
474 0 : printer->Outdent();
475 : printer->Print(
476 0 : " };\n");
477 : }
478 :
479 : TextFormatDecodeData text_format_decode_data;
480 0 : bool has_fields = descriptor_->field_count() > 0;
481 0 : 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 0 : " static GPBMessageFieldDescription fields[] = {\n");
495 0 : printer->Indent();
496 0 : printer->Indent();
497 0 : printer->Indent();
498 0 : for (int i = 0; i < descriptor_->field_count(); ++i) {
499 : const FieldGenerator& field_generator =
500 0 : field_generators_.get(sorted_fields[i]);
501 0 : field_generator.GenerateFieldDescription(printer);
502 0 : if (field_generator.needs_textformat_name_support()) {
503 0 : text_format_decode_data.AddString(sorted_fields[i]->number(),
504 : field_generator.generated_objc_name(),
505 0 : field_generator.raw_field_name());
506 : }
507 : }
508 0 : printer->Outdent();
509 0 : printer->Outdent();
510 0 : printer->Outdent();
511 : printer->Print(
512 0 : " };\n");
513 : }
514 :
515 0 : bool has_enums = enum_generators_.size();
516 0 : if (has_enums) {
517 : printer->Print(
518 0 : " static GPBMessageEnumDescription enums[] = {\n");
519 0 : printer->Indent();
520 0 : printer->Indent();
521 0 : printer->Indent();
522 0 : for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
523 0 : iter != enum_generators_.end(); ++iter) {
524 : printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
525 0 : "name", (*iter)->name());
526 : }
527 0 : printer->Outdent();
528 0 : printer->Outdent();
529 0 : printer->Outdent();
530 : printer->Print(
531 0 : " };\n");
532 : }
533 :
534 0 : bool has_extensions = sorted_extensions.size();
535 0 : if (has_extensions) {
536 : printer->Print(
537 0 : " static GPBExtensionRange ranges[] = {\n");
538 0 : printer->Indent();
539 0 : printer->Indent();
540 0 : printer->Indent();
541 0 : for (int i = 0; i < sorted_extensions.size(); i++) {
542 : printer->Print("{ .start = $start$, .end = $end$ },\n",
543 0 : "start", SimpleItoa(sorted_extensions[i]->start),
544 0 : "end", SimpleItoa(sorted_extensions[i]->end));
545 : }
546 0 : printer->Outdent();
547 0 : printer->Outdent();
548 0 : printer->Outdent();
549 : printer->Print(
550 0 : " };\n");
551 : }
552 :
553 : map<string, string> vars;
554 0 : vars["classname"] = class_name_;
555 0 : vars["rootclassname"] = root_classname_;
556 0 : vars["fields"] = has_fields ? "fields" : "NULL";
557 0 : vars["fields_count"] =
558 : has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
559 0 : vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
560 0 : vars["oneof_count"] =
561 : has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
562 0 : vars["enums"] = has_enums ? "enums" : "NULL";
563 0 : vars["enum_count"] =
564 : has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
565 0 : vars["ranges"] = has_extensions ? "ranges" : "NULL";
566 0 : vars["range_count"] =
567 : has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
568 0 : vars["wireformat"] =
569 0 : descriptor_->options().message_set_wire_format() ? "YES" : "NO";
570 :
571 0 : 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$_FileDescriptor()\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$__storage_)\n"
587 0 : " wireFormat:$wireformat$];\n");
588 : } else {
589 0 : 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$_FileDescriptor()\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$__storage_)\n"
610 : " wireFormat:$wireformat$\n"
611 0 : " 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 0 : "@end\n\n");
620 :
621 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
622 0 : field_generators_.get(descriptor_->field(i))
623 0 : .GenerateCFunctionImplementations(printer);
624 : }
625 :
626 0 : for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
627 0 : iter != oneof_generators_.end(); ++iter) {
628 0 : (*iter)->GenerateClearFunctionImplementation(printer);
629 : }
630 : }
631 :
632 0 : for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
633 0 : iter != enum_generators_.end(); ++iter) {
634 0 : (*iter)->GenerateSource(printer);
635 : }
636 :
637 0 : for (vector<MessageGenerator*>::iterator iter =
638 0 : nested_message_generators_.begin();
639 0 : iter != nested_message_generators_.end(); ++iter) {
640 0 : (*iter)->GenerateSource(printer);
641 : }
642 0 : }
643 :
644 : } // namespace objectivec
645 : } // namespace compiler
646 : } // namespace protobuf
647 51 : } // namespace google
|