• 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<std::string,std::string> * variables)50 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
51                              std::map<std::string, std::string>* variables) {
52   std::string camel_case_name = FieldName(descriptor);
53   std::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 std::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 std::string& classname = ClassName(descriptor->containing_type());
71   (*variables)["classname"] = classname;
72   (*variables)["name"] = camel_case_name;
73   const std::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<std::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)121 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
122   FieldGenerator* result = NULL;
123   if (field->is_repeated()) {
124     switch (GetObjectiveCType(field)) {
125       case OBJECTIVECTYPE_MESSAGE: {
126         if (field->is_map()) {
127           result = new MapFieldGenerator(field);
128         } else {
129           result = new RepeatedMessageFieldGenerator(field);
130         }
131         break;
132       }
133       case OBJECTIVECTYPE_ENUM:
134         result = new RepeatedEnumFieldGenerator(field);
135         break;
136       default:
137         result = new RepeatedPrimitiveFieldGenerator(field);
138         break;
139     }
140   } else {
141     switch (GetObjectiveCType(field)) {
142       case OBJECTIVECTYPE_MESSAGE: {
143         result = new MessageFieldGenerator(field);
144         break;
145       }
146       case OBJECTIVECTYPE_ENUM:
147         result = new EnumFieldGenerator(field);
148         break;
149       default:
150         if (IsReferenceType(field)) {
151           result = new PrimitiveObjFieldGenerator(field);
152         } else {
153           result = new PrimitiveFieldGenerator(field);
154         }
155         break;
156     }
157   }
158   result->FinishInitialization();
159   return result;
160 }
161 
FieldGenerator(const FieldDescriptor * descriptor)162 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
163     : descriptor_(descriptor) {
164   SetCommonFieldVariables(descriptor, &variables_);
165 }
166 
~FieldGenerator()167 FieldGenerator::~FieldGenerator() {}
168 
GenerateFieldNumberConstant(io::Printer * printer) const169 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
170   printer->Print(
171       variables_,
172       "$field_number_name$ = $field_number$,\n");
173 }
174 
GenerateCFunctionDeclarations(io::Printer * printer) const175 void FieldGenerator::GenerateCFunctionDeclarations(
176     io::Printer* printer) const {
177   // Nothing
178 }
179 
GenerateCFunctionImplementations(io::Printer * printer) const180 void FieldGenerator::GenerateCFunctionImplementations(
181     io::Printer* printer) const {
182   // Nothing
183 }
184 
DetermineForwardDeclarations(std::set<std::string> * fwd_decls,bool include_external_types) const185 void FieldGenerator::DetermineForwardDeclarations(
186     std::set<std::string>* fwd_decls,
187     bool include_external_types) const {
188   // Nothing
189 }
190 
DetermineObjectiveCClassDefinitions(std::set<std::string> * fwd_decls) const191 void FieldGenerator::DetermineObjectiveCClassDefinitions(
192     std::set<std::string>* fwd_decls) const {
193   // Nothing
194 }
195 
GenerateFieldDescription(io::Printer * printer,bool include_default) const196 void FieldGenerator::GenerateFieldDescription(
197     io::Printer* printer, bool include_default) const {
198   // Printed in the same order as the structure decl.
199   if (include_default) {
200     printer->Print(
201         variables_,
202         "{\n"
203         "  .defaultValue.$default_name$ = $default$,\n"
204         "  .core.name = \"$name$\",\n"
205         "  .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
206         "  .core.number = $field_number_name$,\n"
207         "  .core.hasIndex = $has_index$,\n"
208         "  .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
209         "  .core.flags = $fieldflags$,\n"
210         "  .core.dataType = GPBDataType$field_type$,\n"
211         "},\n");
212   } else {
213     printer->Print(
214         variables_,
215         "{\n"
216         "  .name = \"$name$\",\n"
217         "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
218         "  .number = $field_number_name$,\n"
219         "  .hasIndex = $has_index$,\n"
220         "  .offset = $storage_offset_value$,$storage_offset_comment$\n"
221         "  .flags = $fieldflags$,\n"
222         "  .dataType = GPBDataType$field_type$,\n"
223         "},\n");
224   }
225 }
226 
SetRuntimeHasBit(int has_index)227 void FieldGenerator::SetRuntimeHasBit(int has_index) {
228   variables_["has_index"] = StrCat(has_index);
229 }
230 
SetNoHasBit(void)231 void FieldGenerator::SetNoHasBit(void) {
232   variables_["has_index"] = "GPBNoHasBit";
233 }
234 
ExtraRuntimeHasBitsNeeded(void) const235 int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
236   return 0;
237 }
238 
SetExtraRuntimeHasBitsBase(int index_base)239 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
240   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
241   // error cases, so it seems to be ok to use as a back door for errors.
242   std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
243   std::cerr.flush();
244   abort();
245 }
246 
SetOneofIndexBase(int index_base)247 void FieldGenerator::SetOneofIndexBase(int index_base) {
248   const OneofDescriptor* oneof = descriptor_->real_containing_oneof();
249   if (oneof != NULL) {
250     int index = oneof->index() + index_base;
251     // Flip the sign to mark it as a oneof.
252     variables_["has_index"] = StrCat(-index);
253   }
254 }
255 
WantsHasProperty(void) const256 bool FieldGenerator::WantsHasProperty(void) const {
257   return descriptor_->has_presence() && !descriptor_->real_containing_oneof();
258 }
259 
FinishInitialization(void)260 void FieldGenerator::FinishInitialization(void) {
261   // If "property_type" wasn't set, make it "storage_type".
262   if ((variables_.find("property_type") == variables_.end()) &&
263       (variables_.find("storage_type") != variables_.end())) {
264     variables_["property_type"] = variable("storage_type");
265   }
266 }
267 
SingleFieldGenerator(const FieldDescriptor * descriptor)268 SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor)
269     : FieldGenerator(descriptor) {
270   // Nothing
271 }
272 
~SingleFieldGenerator()273 SingleFieldGenerator::~SingleFieldGenerator() {}
274 
GenerateFieldStorageDeclaration(io::Printer * printer) const275 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
276     io::Printer* printer) const {
277   printer->Print(variables_, "$storage_type$ $name$;\n");
278 }
279 
GeneratePropertyDeclaration(io::Printer * printer) const280 void SingleFieldGenerator::GeneratePropertyDeclaration(
281     io::Printer* printer) const {
282   printer->Print(variables_, "$comments$");
283   printer->Print(
284       variables_,
285       "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
286       "\n");
287   if (WantsHasProperty()) {
288     printer->Print(
289         variables_,
290         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
291   }
292 }
293 
GeneratePropertyImplementation(io::Printer * printer) const294 void SingleFieldGenerator::GeneratePropertyImplementation(
295     io::Printer* printer) const {
296   if (WantsHasProperty()) {
297     printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
298   } else {
299     printer->Print(variables_, "@dynamic $name$;\n");
300   }
301 }
302 
RuntimeUsesHasBit(void) const303 bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
304   if (descriptor_->real_containing_oneof()) {
305     // The oneof tracks what is set instead.
306     return false;
307   }
308   return true;
309 }
310 
ObjCObjFieldGenerator(const FieldDescriptor * descriptor)311 ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor)
312     : SingleFieldGenerator(descriptor) {
313   variables_["property_storage_attribute"] = "strong";
314   if (IsRetainedName(variables_["name"])) {
315     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
316   }
317 }
318 
~ObjCObjFieldGenerator()319 ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
320 
GenerateFieldStorageDeclaration(io::Printer * printer) const321 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
322     io::Printer* printer) const {
323   printer->Print(variables_, "$storage_type$ *$name$;\n");
324 }
325 
GeneratePropertyDeclaration(io::Printer * printer) const326 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
327     io::Printer* printer) const {
328 
329   // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
330   // it uses pointers and deals with Objective C's rules around storage name
331   // conventions (init*, new*, etc.)
332 
333   printer->Print(variables_, "$comments$");
334   printer->Print(
335       variables_,
336       "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
337   if (WantsHasProperty()) {
338     printer->Print(
339         variables_,
340         "/** Test to see if @c $name$ has been set. */\n"
341         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
342   }
343   if (IsInitName(variables_.find("name")->second)) {
344     // If property name starts with init we need to annotate it to get past ARC.
345     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
346     printer->Print(variables_,
347                    "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
348   }
349   printer->Print("\n");
350 }
351 
RepeatedFieldGenerator(const FieldDescriptor * descriptor)352 RepeatedFieldGenerator::RepeatedFieldGenerator(
353     const FieldDescriptor* descriptor)
354     : ObjCObjFieldGenerator(descriptor) {
355   // Default to no comment and let the cases needing it fill it in.
356   variables_["array_comment"] = "";
357 }
358 
~RepeatedFieldGenerator()359 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
360 
FinishInitialization(void)361 void RepeatedFieldGenerator::FinishInitialization(void) {
362   FieldGenerator::FinishInitialization();
363   if (variables_.find("array_property_type") == variables_.end()) {
364     variables_["array_property_type"] = variable("array_storage_type");
365   }
366 }
367 
GenerateFieldStorageDeclaration(io::Printer * printer) const368 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
369     io::Printer* printer) const {
370   printer->Print(variables_, "$array_storage_type$ *$name$;\n");
371 }
372 
GeneratePropertyImplementation(io::Printer * printer) const373 void RepeatedFieldGenerator::GeneratePropertyImplementation(
374     io::Printer* printer) const {
375   printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
376 }
377 
GeneratePropertyDeclaration(io::Printer * printer) const378 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
379     io::Printer* printer) const {
380 
381   // Repeated fields don't need the has* properties, but they do expose a
382   // *Count (to check without autocreation).  So for the field property we need
383   // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
384   // dealing with needing Objective C's rules around storage name conventions
385   // (init*, new*, etc.)
386 
387   printer->Print(
388       variables_,
389       "$comments$"
390       "$array_comment$"
391       "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
392       "/** The number of items in @c $name$ without causing the array to be created. */\n"
393       "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
394   if (IsInitName(variables_.find("name")->second)) {
395     // If property name starts with init we need to annotate it to get past ARC.
396     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
397     printer->Print(variables_,
398                    "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
399   }
400   printer->Print("\n");
401 }
402 
RuntimeUsesHasBit(void) const403 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
404   return false;  // The array (or map/dict) having anything is what is used.
405 }
406 
FieldGeneratorMap(const Descriptor * descriptor)407 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
408     : descriptor_(descriptor),
409       field_generators_(descriptor->field_count()),
410       extension_generators_(descriptor->extension_count()) {
411   // Construct all the FieldGenerators.
412   for (int i = 0; i < descriptor->field_count(); i++) {
413     field_generators_[i].reset(
414         FieldGenerator::Make(descriptor->field(i)));
415   }
416   for (int i = 0; i < descriptor->extension_count(); i++) {
417     extension_generators_[i].reset(
418         FieldGenerator::Make(descriptor->extension(i)));
419   }
420 }
421 
~FieldGeneratorMap()422 FieldGeneratorMap::~FieldGeneratorMap() {}
423 
get(const FieldDescriptor * field) const424 const FieldGenerator& FieldGeneratorMap::get(
425     const FieldDescriptor* field) const {
426   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
427   return *field_generators_[field->index()];
428 }
429 
get_extension(int index) const430 const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
431   return *extension_generators_[index];
432 }
433 
CalculateHasBits(void)434 int FieldGeneratorMap::CalculateHasBits(void) {
435   int total_bits = 0;
436   for (int i = 0; i < descriptor_->field_count(); i++) {
437     if (field_generators_[i]->RuntimeUsesHasBit()) {
438       field_generators_[i]->SetRuntimeHasBit(total_bits);
439       ++total_bits;
440     } else {
441       field_generators_[i]->SetNoHasBit();
442     }
443     int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
444     if (extra_bits) {
445       field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
446       total_bits += extra_bits;
447     }
448   }
449   return total_bits;
450 }
451 
SetOneofIndexBase(int index_base)452 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
453   for (int i = 0; i < descriptor_->field_count(); i++) {
454     field_generators_[i]->SetOneofIndexBase(index_base);
455   }
456 }
457 
DoesAnyFieldHaveNonZeroDefault(void) const458 bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
459   for (int i = 0; i < descriptor_->field_count(); i++) {
460     if (HasNonZeroDefaultValue(descriptor_->field(i))) {
461       return true;
462     }
463   }
464 
465   return false;
466 }
467 
468 }  // namespace objectivec
469 }  // namespace compiler
470 }  // namespace protobuf
471 }  // namespace google
472