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