• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <iostream>
32 
33 #include <google/protobuf/compiler/objectivec/objectivec_field.h>
34 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
35 #include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
36 #include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
37 #include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
38 #include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
39 #include <google/protobuf/io/printer.h>
40 #include <google/protobuf/wire_format.h>
41 #include <google/protobuf/stubs/common.h>
42 #include <google/protobuf/stubs/strutil.h>
43 
44 namespace google {
45 namespace protobuf {
46 namespace compiler {
47 namespace objectivec {
48 
49 namespace {
50 
SetCommonFieldVariables(const FieldDescriptor * descriptor,map<string,string> * variables)51 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
52                              map<string, string>* variables) {
53   string camel_case_name = FieldName(descriptor);
54   string raw_field_name;
55   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
56     raw_field_name = descriptor->message_type()->name();
57   } else {
58     raw_field_name = descriptor->name();
59   }
60   // The logic here has to match -[GGPBFieldDescriptor textFormatName].
61   const string un_camel_case_name(
62       UnCamelCaseFieldName(camel_case_name, descriptor));
63   const bool needs_custom_name = (raw_field_name != un_camel_case_name);
64 
65   SourceLocation location;
66   if (descriptor->GetSourceLocation(&location)) {
67     (*variables)["comments"] = BuildCommentsString(location);
68   } else {
69     (*variables)["comments"] = "\n";
70   }
71   const string& classname = ClassName(descriptor->containing_type());
72   (*variables)["classname"] = classname;
73   (*variables)["name"] = camel_case_name;
74   const string& capitalized_name = FieldNameCapitalized(descriptor);
75   (*variables)["capitalized_name"] = capitalized_name;
76   (*variables)["raw_field_name"] = raw_field_name;
77   (*variables)["field_number_name"] =
78       classname + "_FieldNumber_" + capitalized_name;
79   (*variables)["field_number"] = SimpleItoa(descriptor->number());
80   (*variables)["field_type"] = GetCapitalizedType(descriptor);
81   (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
82   std::vector<string> field_flags;
83   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
84   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
85   if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
86   if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
87 
88   // ObjC custom flags.
89   if (descriptor->has_default_value())
90     field_flags.push_back("GPBFieldHasDefaultValue");
91   if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
92   if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
93     field_flags.push_back("GPBFieldHasEnumDescriptor");
94   }
95 
96   (*variables)["fieldflags"] = BuildFlagsString(field_flags);
97 
98   (*variables)["default"] = DefaultValue(descriptor);
99   (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
100 
101   (*variables)["dataTypeSpecific_name"] = "className";
102   (*variables)["dataTypeSpecific_value"] = "NULL";
103 
104   (*variables)["storage_offset_value"] =
105       "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
106   (*variables)["storage_offset_comment"] = "";
107 
108   // Clear some common things so they can be set just when needed.
109   (*variables)["storage_attribute"] = "";
110 }
111 
112 }  // namespace
113 
Make(const FieldDescriptor * field,const Options & options)114 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
115                                      const Options& options) {
116   FieldGenerator* result = NULL;
117   if (field->is_repeated()) {
118     switch (GetObjectiveCType(field)) {
119       case OBJECTIVECTYPE_MESSAGE: {
120         if (field->is_map()) {
121           result = new MapFieldGenerator(field, options);
122         } else {
123           result = new RepeatedMessageFieldGenerator(field, options);
124         }
125         break;
126       }
127       case OBJECTIVECTYPE_ENUM:
128         result = new RepeatedEnumFieldGenerator(field, options);
129         break;
130       default:
131         result = new RepeatedPrimitiveFieldGenerator(field, options);
132         break;
133     }
134   } else {
135     switch (GetObjectiveCType(field)) {
136       case OBJECTIVECTYPE_MESSAGE: {
137         result = new MessageFieldGenerator(field, options);
138         break;
139       }
140       case OBJECTIVECTYPE_ENUM:
141         result = new EnumFieldGenerator(field, options);
142         break;
143       default:
144         if (IsReferenceType(field)) {
145           result = new PrimitiveObjFieldGenerator(field, options);
146         } else {
147           result = new PrimitiveFieldGenerator(field, options);
148         }
149         break;
150     }
151   }
152   result->FinishInitialization();
153   return result;
154 }
155 
FieldGenerator(const FieldDescriptor * descriptor,const Options & options)156 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
157                                const Options& options)
158     : descriptor_(descriptor) {
159   SetCommonFieldVariables(descriptor, &variables_);
160 }
161 
~FieldGenerator()162 FieldGenerator::~FieldGenerator() {}
163 
GenerateFieldNumberConstant(io::Printer * printer) const164 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
165   printer->Print(
166       variables_,
167       "$field_number_name$ = $field_number$,\n");
168 }
169 
GenerateCFunctionDeclarations(io::Printer * printer) const170 void FieldGenerator::GenerateCFunctionDeclarations(
171     io::Printer* printer) const {
172   // Nothing
173 }
174 
GenerateCFunctionImplementations(io::Printer * printer) const175 void FieldGenerator::GenerateCFunctionImplementations(
176     io::Printer* printer) const {
177   // Nothing
178 }
179 
DetermineForwardDeclarations(set<string> * fwd_decls) const180 void FieldGenerator::DetermineForwardDeclarations(
181     set<string>* fwd_decls) const {
182   // Nothing
183 }
184 
GenerateFieldDescription(io::Printer * printer,bool include_default) const185 void FieldGenerator::GenerateFieldDescription(
186     io::Printer* printer, bool include_default) const {
187   // Printed in the same order as the structure decl.
188   if (include_default) {
189     printer->Print(
190         variables_,
191         "{\n"
192         "  .defaultValue.$default_name$ = $default$,\n"
193         "  .core.name = \"$name$\",\n"
194         "  .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
195         "  .core.number = $field_number_name$,\n"
196         "  .core.hasIndex = $has_index$,\n"
197         "  .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
198         "  .core.flags = $fieldflags$,\n"
199         "  .core.dataType = GPBDataType$field_type$,\n"
200         "},\n");
201   } else {
202     printer->Print(
203         variables_,
204         "{\n"
205         "  .name = \"$name$\",\n"
206         "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
207         "  .number = $field_number_name$,\n"
208         "  .hasIndex = $has_index$,\n"
209         "  .offset = $storage_offset_value$,$storage_offset_comment$\n"
210         "  .flags = $fieldflags$,\n"
211         "  .dataType = GPBDataType$field_type$,\n"
212         "},\n");
213   }
214 }
215 
SetRuntimeHasBit(int has_index)216 void FieldGenerator::SetRuntimeHasBit(int has_index) {
217   variables_["has_index"] = SimpleItoa(has_index);
218 }
219 
SetNoHasBit(void)220 void FieldGenerator::SetNoHasBit(void) {
221   variables_["has_index"] = "GPBNoHasBit";
222 }
223 
ExtraRuntimeHasBitsNeeded(void) const224 int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
225   return 0;
226 }
227 
SetExtraRuntimeHasBitsBase(int index_base)228 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
229   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
230   // error cases, so it seems to be ok to use as a back door for errors.
231   cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
232   cerr.flush();
233   abort();
234 }
235 
SetOneofIndexBase(int index_base)236 void FieldGenerator::SetOneofIndexBase(int index_base) {
237   if (descriptor_->containing_oneof() != NULL) {
238     int index = descriptor_->containing_oneof()->index() + index_base;
239     // Flip the sign to mark it as a oneof.
240     variables_["has_index"] = SimpleItoa(-index);
241   }
242 }
243 
FinishInitialization(void)244 void FieldGenerator::FinishInitialization(void) {
245   // If "property_type" wasn't set, make it "storage_type".
246   if ((variables_.find("property_type") == variables_.end()) &&
247       (variables_.find("storage_type") != variables_.end())) {
248     variables_["property_type"] = variable("storage_type");
249   }
250 }
251 
SingleFieldGenerator(const FieldDescriptor * descriptor,const Options & options)252 SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
253                                            const Options& options)
254     : FieldGenerator(descriptor, options) {
255   // Nothing
256 }
257 
~SingleFieldGenerator()258 SingleFieldGenerator::~SingleFieldGenerator() {}
259 
GenerateFieldStorageDeclaration(io::Printer * printer) const260 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
261     io::Printer* printer) const {
262   printer->Print(variables_, "$storage_type$ $name$;\n");
263 }
264 
GeneratePropertyDeclaration(io::Printer * printer) const265 void SingleFieldGenerator::GeneratePropertyDeclaration(
266     io::Printer* printer) const {
267   printer->Print(variables_, "$comments$");
268   printer->Print(
269       variables_,
270       "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
271       "\n");
272   if (WantsHasProperty()) {
273     printer->Print(
274         variables_,
275         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
276   }
277 }
278 
GeneratePropertyImplementation(io::Printer * printer) const279 void SingleFieldGenerator::GeneratePropertyImplementation(
280     io::Printer* printer) const {
281   if (WantsHasProperty()) {
282     printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
283   } else {
284     printer->Print(variables_, "@dynamic $name$;\n");
285   }
286 }
287 
WantsHasProperty(void) const288 bool SingleFieldGenerator::WantsHasProperty(void) const {
289   if (descriptor_->containing_oneof() != NULL) {
290     // If in a oneof, it uses the oneofcase instead of a has bit.
291     return false;
292   }
293   if (HasFieldPresence(descriptor_->file())) {
294     // In proto1/proto2, every field has a has_$name$() method.
295     return true;
296   }
297   return false;
298 }
299 
RuntimeUsesHasBit(void) const300 bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
301   if (descriptor_->containing_oneof() != NULL) {
302     // The oneof tracks what is set instead.
303     return false;
304   }
305   return true;
306 }
307 
ObjCObjFieldGenerator(const FieldDescriptor * descriptor,const Options & options)308 ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
309                                              const Options& options)
310     : SingleFieldGenerator(descriptor, options) {
311   variables_["property_storage_attribute"] = "strong";
312   if (IsRetainedName(variables_["name"])) {
313     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
314   }
315 }
316 
~ObjCObjFieldGenerator()317 ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
318 
GenerateFieldStorageDeclaration(io::Printer * printer) const319 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
320     io::Printer* printer) const {
321   printer->Print(variables_, "$storage_type$ *$name$;\n");
322 }
323 
GeneratePropertyDeclaration(io::Printer * printer) const324 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
325     io::Printer* printer) const {
326 
327   // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
328   // it uses pointers and deals with Objective C's rules around storage name
329   // conventions (init*, new*, etc.)
330 
331   printer->Print(variables_, "$comments$");
332   printer->Print(
333       variables_,
334       "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
335   if (WantsHasProperty()) {
336     printer->Print(
337         variables_,
338         "/// Test to see if @c $name$ has been set.\n"
339         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
340   }
341   if (IsInitName(variables_.find("name")->second)) {
342     // If property name starts with init we need to annotate it to get past ARC.
343     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
344     printer->Print(variables_,
345                    "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
346   }
347   printer->Print("\n");
348 }
349 
RepeatedFieldGenerator(const FieldDescriptor * descriptor,const Options & options)350 RepeatedFieldGenerator::RepeatedFieldGenerator(
351     const FieldDescriptor* descriptor, const Options& options)
352     : ObjCObjFieldGenerator(descriptor, options) {
353   // Default to no comment and let the cases needing it fill it in.
354   variables_["array_comment"] = "";
355 }
356 
~RepeatedFieldGenerator()357 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
358 
FinishInitialization(void)359 void RepeatedFieldGenerator::FinishInitialization(void) {
360   FieldGenerator::FinishInitialization();
361   if (variables_.find("array_property_type") == variables_.end()) {
362     variables_["array_property_type"] = variable("array_storage_type");
363   }
364 }
365 
GenerateFieldStorageDeclaration(io::Printer * printer) const366 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
367     io::Printer* printer) const {
368   printer->Print(variables_, "$array_storage_type$ *$name$;\n");
369 }
370 
GeneratePropertyImplementation(io::Printer * printer) const371 void RepeatedFieldGenerator::GeneratePropertyImplementation(
372     io::Printer* printer) const {
373   printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
374 }
375 
GeneratePropertyDeclaration(io::Printer * printer) const376 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
377     io::Printer* printer) const {
378 
379   // Repeated fields don't need the has* properties, but they do expose a
380   // *Count (to check without autocreation).  So for the field property we need
381   // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
382   // dealing with needing Objective C's rules around storage name conventions
383   // (init*, new*, etc.)
384 
385   printer->Print(
386       variables_,
387       "$comments$"
388       "$array_comment$"
389       "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
390       "/// The number of items in @c $name$ without causing the array to be created.\n"
391       "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
392   if (IsInitName(variables_.find("name")->second)) {
393     // If property name starts with init we need to annotate it to get past ARC.
394     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
395     printer->Print(variables_,
396                    "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
397   }
398   printer->Print("\n");
399 }
400 
WantsHasProperty(void) const401 bool RepeatedFieldGenerator::WantsHasProperty(void) const {
402   // Consumer check the array size/existance rather than a has bit.
403   return false;
404 }
405 
RuntimeUsesHasBit(void) const406 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
407   return false;  // The array having anything is what is used.
408 }
409 
FieldGeneratorMap(const Descriptor * descriptor,const Options & options)410 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
411                                      const Options& options)
412     : descriptor_(descriptor),
413       field_generators_(
414           new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
415       extension_generators_(
416           new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
417   // Construct all the FieldGenerators.
418   for (int i = 0; i < descriptor->field_count(); i++) {
419     field_generators_[i].reset(
420         FieldGenerator::Make(descriptor->field(i), options));
421   }
422   for (int i = 0; i < descriptor->extension_count(); i++) {
423     extension_generators_[i].reset(
424         FieldGenerator::Make(descriptor->extension(i), options));
425   }
426 }
427 
~FieldGeneratorMap()428 FieldGeneratorMap::~FieldGeneratorMap() {}
429 
get(const FieldDescriptor * field) const430 const FieldGenerator& FieldGeneratorMap::get(
431     const FieldDescriptor* field) const {
432   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
433   return *field_generators_[field->index()];
434 }
435 
get_extension(int index) const436 const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
437   return *extension_generators_[index];
438 }
439 
CalculateHasBits(void)440 int FieldGeneratorMap::CalculateHasBits(void) {
441   int total_bits = 0;
442   for (int i = 0; i < descriptor_->field_count(); i++) {
443     if (field_generators_[i]->RuntimeUsesHasBit()) {
444       field_generators_[i]->SetRuntimeHasBit(total_bits);
445       ++total_bits;
446     } else {
447       field_generators_[i]->SetNoHasBit();
448     }
449     int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
450     if (extra_bits) {
451       field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
452       total_bits += extra_bits;
453     }
454   }
455   return total_bits;
456 }
457 
SetOneofIndexBase(int index_base)458 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
459   for (int i = 0; i < descriptor_->field_count(); i++) {
460     field_generators_[i]->SetOneofIndexBase(index_base);
461   }
462 }
463 
DoesAnyFieldHaveNonZeroDefault(void) const464 bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
465   for (int i = 0; i < descriptor_->field_count(); i++) {
466     if (HasNonZeroDefaultValue(descriptor_->field(i))) {
467       return true;
468     }
469   }
470 
471   return false;
472 }
473 
474 }  // namespace objectivec
475 }  // namespace compiler
476 }  // namespace protobuf
477 }  // namespace google
478