Line data Source code
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 <google/protobuf/compiler/objectivec/objectivec_field.h>
32 : #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
33 : #include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
34 : #include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
35 : #include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
36 : #include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
37 : #include <google/protobuf/io/printer.h>
38 : #include <google/protobuf/wire_format.h>
39 : #include <google/protobuf/stubs/common.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 0 : void SetCommonFieldVariables(const FieldDescriptor* descriptor,
49 : map<string, string>* variables) {
50 0 : string camel_case_name = FieldName(descriptor);
51 : string raw_field_name;
52 0 : if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
53 0 : raw_field_name = descriptor->message_type()->name();
54 : } else {
55 0 : raw_field_name = descriptor->name();
56 : }
57 : // The logic here has to match -[GGPBFieldDescriptor textFormatName].
58 : const string un_camel_case_name(
59 0 : UnCamelCaseFieldName(camel_case_name, descriptor));
60 0 : const bool needs_custom_name = (raw_field_name != un_camel_case_name);
61 :
62 0 : SourceLocation location;
63 0 : if (descriptor->GetSourceLocation(&location)) {
64 0 : (*variables)["comments"] = BuildCommentsString(location);
65 : } else {
66 0 : (*variables)["comments"] = "\n";
67 : }
68 0 : const string& classname = ClassName(descriptor->containing_type());
69 0 : (*variables)["classname"] = classname;
70 0 : (*variables)["name"] = camel_case_name;
71 0 : const string& capitalized_name = FieldNameCapitalized(descriptor);
72 0 : (*variables)["capitalized_name"] = capitalized_name;
73 0 : (*variables)["raw_field_name"] = raw_field_name;
74 0 : (*variables)["field_number_name"] =
75 0 : classname + "_FieldNumber_" + capitalized_name;
76 0 : (*variables)["field_number"] = SimpleItoa(descriptor->number());
77 0 : (*variables)["has_index"] = SimpleItoa(descriptor->index());
78 0 : (*variables)["field_type"] = GetCapitalizedType(descriptor);
79 0 : std::vector<string> field_flags;
80 0 : if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
81 0 : if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
82 0 : if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
83 0 : if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
84 :
85 : // ObjC custom flags.
86 0 : if (descriptor->has_default_value())
87 0 : field_flags.push_back("GPBFieldHasDefaultValue");
88 0 : if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
89 0 : if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
90 0 : field_flags.push_back("GPBFieldHasEnumDescriptor");
91 : }
92 :
93 0 : (*variables)["fieldflags"] = BuildFlagsString(field_flags);
94 :
95 0 : (*variables)["default"] = DefaultValue(descriptor);
96 0 : (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
97 :
98 0 : (*variables)["dataTypeSpecific_name"] = "className";
99 0 : (*variables)["dataTypeSpecific_value"] = "NULL";
100 :
101 0 : string field_options = descriptor->options().SerializeAsString();
102 : // Must convert to a standard byte order for packing length into
103 : // a cstring.
104 0 : uint32 length = ghtonl(field_options.length());
105 0 : if (length > 0) {
106 0 : string bytes((const char*)&length, sizeof(length));
107 0 : bytes.append(field_options);
108 0 : string options_str = "\"" + CEscape(bytes) + "\"";
109 0 : (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
110 : } else {
111 0 : (*variables)["fieldoptions"] = "";
112 : }
113 :
114 : // Clear some common things so they can be set just when needed.
115 0 : (*variables)["storage_attribute"] = "";
116 0 : }
117 :
118 : } // namespace
119 :
120 0 : FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
121 0 : FieldGenerator* result = NULL;
122 0 : if (field->is_repeated()) {
123 0 : switch (GetObjectiveCType(field)) {
124 : case OBJECTIVECTYPE_MESSAGE: {
125 0 : if (field->is_map()) {
126 0 : result = new MapFieldGenerator(field);
127 : } else {
128 0 : result = new RepeatedMessageFieldGenerator(field);
129 : }
130 : break;
131 : }
132 : case OBJECTIVECTYPE_ENUM:
133 0 : result = new RepeatedEnumFieldGenerator(field);
134 : break;
135 : default:
136 0 : result = new RepeatedPrimitiveFieldGenerator(field);
137 : break;
138 : }
139 : } else {
140 0 : switch (GetObjectiveCType(field)) {
141 : case OBJECTIVECTYPE_MESSAGE: {
142 0 : result = new MessageFieldGenerator(field);
143 : break;
144 : }
145 : case OBJECTIVECTYPE_ENUM:
146 0 : result = new EnumFieldGenerator(field);
147 : break;
148 : default:
149 0 : if (IsReferenceType(field)) {
150 0 : result = new PrimitiveObjFieldGenerator(field);
151 : } else {
152 0 : result = new PrimitiveFieldGenerator(field);
153 : }
154 : break;
155 : }
156 : }
157 0 : result->FinishInitialization();
158 0 : return result;
159 : }
160 :
161 :
162 0 : FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
163 0 : : descriptor_(descriptor) {
164 0 : SetCommonFieldVariables(descriptor, &variables_);
165 0 : }
166 :
167 0 : FieldGenerator::~FieldGenerator() {}
168 :
169 0 : void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
170 : printer->Print(
171 : variables_,
172 0 : "$field_number_name$ = $field_number$,\n");
173 0 : }
174 :
175 0 : void FieldGenerator::GenerateCFunctionDeclarations(
176 : io::Printer* printer) const {
177 : // Nothing
178 0 : }
179 :
180 0 : void FieldGenerator::GenerateCFunctionImplementations(
181 : io::Printer* printer) const {
182 : // Nothing
183 0 : }
184 :
185 0 : void FieldGenerator::DetermineForwardDeclarations(
186 : set<string>* fwd_decls) const {
187 : // Nothing
188 0 : }
189 :
190 0 : void FieldGenerator::GenerateFieldDescription(
191 : io::Printer* printer) const {
192 : printer->Print(
193 : variables_,
194 : "{\n"
195 : " .name = \"$name$\",\n"
196 : " .number = $field_number_name$,\n"
197 : " .hasIndex = $has_index$,\n"
198 : " .flags = $fieldflags$,\n"
199 : " .dataType = GPBDataType$field_type$,\n"
200 : " .offset = offsetof($classname$__storage_, $name$),\n"
201 0 : " .defaultValue.$default_name$ = $default$,\n");
202 :
203 : // TODO(thomasvl): It might be useful to add a CPP wrapper to support
204 : // compiling away the EnumDescriptors. To do that, we'd need a #if here
205 : // to control setting the descriptor vs. the validator, and above in
206 : // SetCommonFieldVariables() we'd want to wrap how we add
207 : // GPBFieldHasDefaultValue to the flags.
208 :
209 : // " .dataTypeSpecific.value* = [something],"
210 0 : GenerateFieldDescriptionTypeSpecific(printer);
211 :
212 0 : const string& field_options(variables_.find("fieldoptions")->second);
213 0 : if (field_options.empty()) {
214 0 : printer->Print(" .fieldOptions = NULL,\n");
215 : } else {
216 : // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
217 : // outdented because the need for indent captured on the previous
218 : // printing of a \n and there is no way to get the current indent level
219 : // to call the right number of Outdent()/Indents() to maintain state.
220 : printer->Print(
221 : variables_,
222 : "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
223 : " .fieldOptions = $fieldoptions$,\n"
224 : "#else\n"
225 : " .fieldOptions = NULL,\n"
226 0 : "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
227 : }
228 :
229 0 : printer->Print("},\n");
230 0 : }
231 :
232 0 : void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
233 : io::Printer* printer) const {
234 : printer->Print(
235 : variables_,
236 0 : " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
237 0 : }
238 :
239 0 : void FieldGenerator::SetOneofIndexBase(int index_base) {
240 0 : if (descriptor_->containing_oneof() != NULL) {
241 0 : int index = descriptor_->containing_oneof()->index() + index_base;
242 : // Flip the sign to mark it as a oneof.
243 0 : variables_["has_index"] = SimpleItoa(-index);
244 : }
245 0 : }
246 :
247 0 : void FieldGenerator::FinishInitialization(void) {
248 : // If "property_type" wasn't set, make it "storage_type".
249 0 : if ((variables_.find("property_type") == variables_.end()) &&
250 0 : (variables_.find("storage_type") != variables_.end())) {
251 0 : variables_["property_type"] = variable("storage_type");
252 : }
253 0 : }
254 :
255 0 : SingleFieldGenerator::SingleFieldGenerator(
256 : const FieldDescriptor* descriptor)
257 0 : : FieldGenerator(descriptor) {
258 : // Nothing
259 0 : }
260 :
261 0 : SingleFieldGenerator::~SingleFieldGenerator() {}
262 :
263 0 : void SingleFieldGenerator::GenerateFieldStorageDeclaration(
264 : io::Printer* printer) const {
265 0 : printer->Print(variables_, "$storage_type$ $name$;\n");
266 0 : }
267 :
268 0 : void SingleFieldGenerator::GeneratePropertyDeclaration(
269 : io::Printer* printer) const {
270 0 : printer->Print(variables_, "$comments$");
271 0 : if (WantsHasProperty()) {
272 : printer->Print(
273 : variables_,
274 0 : "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
275 : }
276 : printer->Print(
277 : variables_,
278 : "@property(nonatomic, readwrite) $property_type$ $name$;\n"
279 0 : "\n");
280 0 : }
281 :
282 0 : void SingleFieldGenerator::GeneratePropertyImplementation(
283 : io::Printer* printer) const {
284 0 : if (WantsHasProperty()) {
285 0 : printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
286 : } else {
287 0 : printer->Print(variables_, "@dynamic $name$;\n");
288 : }
289 0 : }
290 :
291 0 : bool SingleFieldGenerator::WantsHasProperty(void) const {
292 0 : if (descriptor_->containing_oneof() != NULL) {
293 : // If in a oneof, it uses the oneofcase instead of a has bit.
294 : return false;
295 : }
296 0 : if (HasFieldPresence(descriptor_->file())) {
297 : // In proto1/proto2, every field has a has_$name$() method.
298 : return true;
299 : }
300 0 : return false;
301 : }
302 :
303 0 : ObjCObjFieldGenerator::ObjCObjFieldGenerator(
304 : const FieldDescriptor* descriptor)
305 0 : : SingleFieldGenerator(descriptor) {
306 0 : variables_["property_storage_attribute"] = "strong";
307 0 : if (IsRetainedName(variables_["name"])) {
308 0 : variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
309 : }
310 0 : }
311 :
312 0 : ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
313 :
314 0 : void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
315 : io::Printer* printer) const {
316 0 : printer->Print(variables_, "$storage_type$ *$name$;\n");
317 0 : }
318 :
319 0 : void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
320 : io::Printer* printer) const {
321 :
322 : // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
323 : // it uses pointers and deals with Objective C's rules around storage name
324 : // conventions (init*, new*, etc.)
325 :
326 0 : printer->Print(variables_, "$comments$");
327 0 : if (WantsHasProperty()) {
328 : printer->Print(
329 : variables_,
330 0 : "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
331 : }
332 : printer->Print(
333 : variables_,
334 0 : "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
335 0 : if (IsInitName(variables_.find("name")->second)) {
336 : // If property name starts with init we need to annotate it to get past ARC.
337 : // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
338 : printer->Print(variables_,
339 0 : "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
340 : }
341 0 : printer->Print("\n");
342 0 : }
343 :
344 0 : RepeatedFieldGenerator::RepeatedFieldGenerator(
345 : const FieldDescriptor* descriptor)
346 0 : : ObjCObjFieldGenerator(descriptor) {
347 : // Repeated fields don't use the has index.
348 0 : variables_["has_index"] = "GPBNoHasBit";
349 0 : }
350 :
351 0 : RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
352 :
353 0 : void RepeatedFieldGenerator::FinishInitialization(void) {
354 0 : FieldGenerator::FinishInitialization();
355 0 : variables_["array_comment"] =
356 0 : "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
357 0 : }
358 :
359 0 : void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
360 : io::Printer* printer) const {
361 0 : printer->Print(variables_, "$array_storage_type$ *$name$;\n");
362 0 : }
363 :
364 0 : void RepeatedFieldGenerator::GeneratePropertyImplementation(
365 : io::Printer* printer) const {
366 0 : printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
367 0 : }
368 :
369 0 : void RepeatedFieldGenerator::GeneratePropertyDeclaration(
370 : io::Printer* printer) const {
371 :
372 : // Repeated fields don't need the has* properties, but they do expose a
373 : // *Count (to check without autocreation). So for the field property we need
374 : // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
375 : // dealing with needing Objective C's rules around storage name conventions
376 : // (init*, new*, etc.)
377 :
378 : printer->Print(
379 : variables_,
380 : "$comments$"
381 : "$array_comment$"
382 : "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n"
383 0 : "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
384 0 : if (IsInitName(variables_.find("name")->second)) {
385 : // If property name starts with init we need to annotate it to get past ARC.
386 : // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
387 : printer->Print(variables_,
388 0 : "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
389 : }
390 0 : printer->Print("\n");
391 0 : }
392 :
393 0 : bool RepeatedFieldGenerator::WantsHasProperty(void) const {
394 : // Consumer check the array size/existance rather than a has bit.
395 0 : return false;
396 : }
397 :
398 0 : FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
399 : : descriptor_(descriptor),
400 : field_generators_(
401 0 : new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
402 : extension_generators_(
403 0 : new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
404 : // Construct all the FieldGenerators.
405 0 : for (int i = 0; i < descriptor->field_count(); i++) {
406 0 : field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
407 : }
408 0 : for (int i = 0; i < descriptor->extension_count(); i++) {
409 0 : extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
410 : }
411 0 : }
412 :
413 0 : FieldGeneratorMap::~FieldGeneratorMap() {}
414 :
415 0 : const FieldGenerator& FieldGeneratorMap::get(
416 0 : const FieldDescriptor* field) const {
417 0 : GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
418 0 : return *field_generators_[field->index()];
419 : }
420 :
421 0 : const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
422 0 : return *extension_generators_[index];
423 : }
424 :
425 0 : void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
426 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
427 0 : field_generators_[i]->SetOneofIndexBase(index_base);
428 : }
429 0 : }
430 :
431 : } // namespace objectivec
432 : } // namespace compiler
433 : } // namespace protobuf
434 : } // namespace google
|