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