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