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
95 (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
96
97 (*variables)["default"] = DefaultValue(descriptor);
98 (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
99
100 (*variables)["dataTypeSpecific_name"] = "className";
101 (*variables)["dataTypeSpecific_value"] = "NULL";
102
103 (*variables)["storage_offset_value"] =
104 "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
105 (*variables)["storage_offset_comment"] = "";
106
107 // Clear some common things so they can be set just when needed.
108 (*variables)["storage_attribute"] = "";
109 }
110
111 } // namespace
112
Make(const FieldDescriptor * field,const Options & options)113 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
114 const Options& options) {
115 FieldGenerator* result = NULL;
116 if (field->is_repeated()) {
117 switch (GetObjectiveCType(field)) {
118 case OBJECTIVECTYPE_MESSAGE: {
119 if (field->is_map()) {
120 result = new MapFieldGenerator(field, options);
121 } else {
122 result = new RepeatedMessageFieldGenerator(field, options);
123 }
124 break;
125 }
126 case OBJECTIVECTYPE_ENUM:
127 result = new RepeatedEnumFieldGenerator(field, options);
128 break;
129 default:
130 result = new RepeatedPrimitiveFieldGenerator(field, options);
131 break;
132 }
133 } else {
134 switch (GetObjectiveCType(field)) {
135 case OBJECTIVECTYPE_MESSAGE: {
136 result = new MessageFieldGenerator(field, options);
137 break;
138 }
139 case OBJECTIVECTYPE_ENUM:
140 result = new EnumFieldGenerator(field, options);
141 break;
142 default:
143 if (IsReferenceType(field)) {
144 result = new PrimitiveObjFieldGenerator(field, options);
145 } else {
146 result = new PrimitiveFieldGenerator(field, options);
147 }
148 break;
149 }
150 }
151 result->FinishInitialization();
152 return result;
153 }
154
FieldGenerator(const FieldDescriptor * descriptor,const Options & options)155 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
156 const Options& options)
157 : descriptor_(descriptor) {
158 SetCommonFieldVariables(descriptor, &variables_);
159 }
160
~FieldGenerator()161 FieldGenerator::~FieldGenerator() {}
162
GenerateFieldNumberConstant(io::Printer * printer) const163 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
164 printer->Print(
165 variables_,
166 "$field_number_name$ = $field_number$,\n");
167 }
168
GenerateCFunctionDeclarations(io::Printer * printer) const169 void FieldGenerator::GenerateCFunctionDeclarations(
170 io::Printer* printer) const {
171 // Nothing
172 }
173
GenerateCFunctionImplementations(io::Printer * printer) const174 void FieldGenerator::GenerateCFunctionImplementations(
175 io::Printer* printer) const {
176 // Nothing
177 }
178
DetermineForwardDeclarations(std::set<string> * fwd_decls) const179 void FieldGenerator::DetermineForwardDeclarations(
180 std::set<string>* fwd_decls) const {
181 // Nothing
182 }
183
GenerateFieldDescription(io::Printer * printer,bool include_default) const184 void FieldGenerator::GenerateFieldDescription(
185 io::Printer* printer, bool include_default) const {
186 // Printed in the same order as the structure decl.
187 if (include_default) {
188 printer->Print(
189 variables_,
190 "{\n"
191 " .defaultValue.$default_name$ = $default$,\n"
192 " .core.name = \"$name$\",\n"
193 " .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
194 " .core.number = $field_number_name$,\n"
195 " .core.hasIndex = $has_index$,\n"
196 " .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
197 " .core.flags = $fieldflags$,\n"
198 " .core.dataType = GPBDataType$field_type$,\n"
199 "},\n");
200 } else {
201 printer->Print(
202 variables_,
203 "{\n"
204 " .name = \"$name$\",\n"
205 " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
206 " .number = $field_number_name$,\n"
207 " .hasIndex = $has_index$,\n"
208 " .offset = $storage_offset_value$,$storage_offset_comment$\n"
209 " .flags = $fieldflags$,\n"
210 " .dataType = GPBDataType$field_type$,\n"
211 "},\n");
212 }
213 }
214
SetRuntimeHasBit(int has_index)215 void FieldGenerator::SetRuntimeHasBit(int has_index) {
216 variables_["has_index"] = StrCat(has_index);
217 }
218
SetNoHasBit(void)219 void FieldGenerator::SetNoHasBit(void) {
220 variables_["has_index"] = "GPBNoHasBit";
221 }
222
ExtraRuntimeHasBitsNeeded(void) const223 int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
224 return 0;
225 }
226
SetExtraRuntimeHasBitsBase(int index_base)227 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
228 // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
229 // error cases, so it seems to be ok to use as a back door for errors.
230 std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
231 std::cerr.flush();
232 abort();
233 }
234
SetOneofIndexBase(int index_base)235 void FieldGenerator::SetOneofIndexBase(int index_base) {
236 if (descriptor_->containing_oneof() != NULL) {
237 int index = descriptor_->containing_oneof()->index() + index_base;
238 // Flip the sign to mark it as a oneof.
239 variables_["has_index"] = StrCat(-index);
240 }
241 }
242
FinishInitialization(void)243 void FieldGenerator::FinishInitialization(void) {
244 // If "property_type" wasn't set, make it "storage_type".
245 if ((variables_.find("property_type") == variables_.end()) &&
246 (variables_.find("storage_type") != variables_.end())) {
247 variables_["property_type"] = variable("storage_type");
248 }
249 }
250
SingleFieldGenerator(const FieldDescriptor * descriptor,const Options & options)251 SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
252 const Options& options)
253 : FieldGenerator(descriptor, options) {
254 // Nothing
255 }
256
~SingleFieldGenerator()257 SingleFieldGenerator::~SingleFieldGenerator() {}
258
GenerateFieldStorageDeclaration(io::Printer * printer) const259 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
260 io::Printer* printer) const {
261 printer->Print(variables_, "$storage_type$ $name$;\n");
262 }
263
GeneratePropertyDeclaration(io::Printer * printer) const264 void SingleFieldGenerator::GeneratePropertyDeclaration(
265 io::Printer* printer) const {
266 printer->Print(variables_, "$comments$");
267 printer->Print(
268 variables_,
269 "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
270 "\n");
271 if (WantsHasProperty()) {
272 printer->Print(
273 variables_,
274 "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
275 }
276 }
277
GeneratePropertyImplementation(io::Printer * printer) const278 void SingleFieldGenerator::GeneratePropertyImplementation(
279 io::Printer* printer) const {
280 if (WantsHasProperty()) {
281 printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
282 } else {
283 printer->Print(variables_, "@dynamic $name$;\n");
284 }
285 }
286
WantsHasProperty(void) const287 bool SingleFieldGenerator::WantsHasProperty(void) const {
288 if (descriptor_->containing_oneof() != NULL) {
289 // If in a oneof, it uses the oneofcase instead of a has bit.
290 return false;
291 }
292 if (HasFieldPresence(descriptor_->file())) {
293 // In proto1/proto2, every field has a has_$name$() method.
294 return true;
295 }
296 return false;
297 }
298
RuntimeUsesHasBit(void) const299 bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
300 if (descriptor_->containing_oneof() != NULL) {
301 // The oneof tracks what is set instead.
302 return false;
303 }
304 return true;
305 }
306
ObjCObjFieldGenerator(const FieldDescriptor * descriptor,const Options & options)307 ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
308 const Options& options)
309 : SingleFieldGenerator(descriptor, options) {
310 variables_["property_storage_attribute"] = "strong";
311 if (IsRetainedName(variables_["name"])) {
312 variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
313 }
314 }
315
~ObjCObjFieldGenerator()316 ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
317
GenerateFieldStorageDeclaration(io::Printer * printer) const318 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
319 io::Printer* printer) const {
320 printer->Print(variables_, "$storage_type$ *$name$;\n");
321 }
322
GeneratePropertyDeclaration(io::Printer * printer) const323 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
324 io::Printer* printer) const {
325
326 // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
327 // it uses pointers and deals with Objective C's rules around storage name
328 // conventions (init*, new*, etc.)
329
330 printer->Print(variables_, "$comments$");
331 printer->Print(
332 variables_,
333 "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
334 if (WantsHasProperty()) {
335 printer->Print(
336 variables_,
337 "/** Test to see if @c $name$ has been set. */\n"
338 "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
339 }
340 if (IsInitName(variables_.find("name")->second)) {
341 // If property name starts with init we need to annotate it to get past ARC.
342 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
343 printer->Print(variables_,
344 "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
345 }
346 printer->Print("\n");
347 }
348
RepeatedFieldGenerator(const FieldDescriptor * descriptor,const Options & options)349 RepeatedFieldGenerator::RepeatedFieldGenerator(
350 const FieldDescriptor* descriptor, const Options& options)
351 : ObjCObjFieldGenerator(descriptor, options) {
352 // Default to no comment and let the cases needing it fill it in.
353 variables_["array_comment"] = "";
354 }
355
~RepeatedFieldGenerator()356 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
357
FinishInitialization(void)358 void RepeatedFieldGenerator::FinishInitialization(void) {
359 FieldGenerator::FinishInitialization();
360 if (variables_.find("array_property_type") == variables_.end()) {
361 variables_["array_property_type"] = variable("array_storage_type");
362 }
363 }
364
GenerateFieldStorageDeclaration(io::Printer * printer) const365 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
366 io::Printer* printer) const {
367 printer->Print(variables_, "$array_storage_type$ *$name$;\n");
368 }
369
GeneratePropertyImplementation(io::Printer * printer) const370 void RepeatedFieldGenerator::GeneratePropertyImplementation(
371 io::Printer* printer) const {
372 printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
373 }
374
GeneratePropertyDeclaration(io::Printer * printer) const375 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
376 io::Printer* printer) const {
377
378 // Repeated fields don't need the has* properties, but they do expose a
379 // *Count (to check without autocreation). So for the field property we need
380 // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
381 // dealing with needing Objective C's rules around storage name conventions
382 // (init*, new*, etc.)
383
384 printer->Print(
385 variables_,
386 "$comments$"
387 "$array_comment$"
388 "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
389 "/** The number of items in @c $name$ without causing the array to be created. */\n"
390 "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
391 if (IsInitName(variables_.find("name")->second)) {
392 // If property name starts with init we need to annotate it to get past ARC.
393 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
394 printer->Print(variables_,
395 "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
396 }
397 printer->Print("\n");
398 }
399
WantsHasProperty(void) const400 bool RepeatedFieldGenerator::WantsHasProperty(void) const {
401 // Consumer check the array size/existance rather than a has bit.
402 return false;
403 }
404
RuntimeUsesHasBit(void) const405 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
406 return false; // The array having anything is what is used.
407 }
408
FieldGeneratorMap(const Descriptor * descriptor,const Options & options)409 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
410 const Options& options)
411 : descriptor_(descriptor),
412 field_generators_(descriptor->field_count()),
413 extension_generators_(descriptor->extension_count()) {
414 // Construct all the FieldGenerators.
415 for (int i = 0; i < descriptor->field_count(); i++) {
416 field_generators_[i].reset(
417 FieldGenerator::Make(descriptor->field(i), options));
418 }
419 for (int i = 0; i < descriptor->extension_count(); i++) {
420 extension_generators_[i].reset(
421 FieldGenerator::Make(descriptor->extension(i), options));
422 }
423 }
424
~FieldGeneratorMap()425 FieldGeneratorMap::~FieldGeneratorMap() {}
426
get(const FieldDescriptor * field) const427 const FieldGenerator& FieldGeneratorMap::get(
428 const FieldDescriptor* field) const {
429 GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
430 return *field_generators_[field->index()];
431 }
432
get_extension(int index) const433 const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
434 return *extension_generators_[index];
435 }
436
CalculateHasBits(void)437 int FieldGeneratorMap::CalculateHasBits(void) {
438 int total_bits = 0;
439 for (int i = 0; i < descriptor_->field_count(); i++) {
440 if (field_generators_[i]->RuntimeUsesHasBit()) {
441 field_generators_[i]->SetRuntimeHasBit(total_bits);
442 ++total_bits;
443 } else {
444 field_generators_[i]->SetNoHasBit();
445 }
446 int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
447 if (extra_bits) {
448 field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
449 total_bits += extra_bits;
450 }
451 }
452 return total_bits;
453 }
454
SetOneofIndexBase(int index_base)455 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
456 for (int i = 0; i < descriptor_->field_count(); i++) {
457 field_generators_[i]->SetOneofIndexBase(index_base);
458 }
459 }
460
DoesAnyFieldHaveNonZeroDefault(void) const461 bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
462 for (int i = 0; i < descriptor_->field_count(); i++) {
463 if (HasNonZeroDefaultValue(descriptor_->field(i))) {
464 return true;
465 }
466 }
467
468 return false;
469 }
470
471 } // namespace objectivec
472 } // namespace compiler
473 } // namespace protobuf
474 } // namespace google
475