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