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