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 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 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 156 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor, 157 const Options& options) 158 : descriptor_(descriptor) { 159 SetCommonFieldVariables(descriptor, &variables_); 160 } 161 162 FieldGenerator::~FieldGenerator() {} 163 164 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const { 165 printer->Print( 166 variables_, 167 "$field_number_name$ = $field_number$,\n"); 168 } 169 170 void FieldGenerator::GenerateCFunctionDeclarations( 171 io::Printer* printer) const { 172 // Nothing 173 } 174 175 void FieldGenerator::GenerateCFunctionImplementations( 176 io::Printer* printer) const { 177 // Nothing 178 } 179 180 void FieldGenerator::DetermineForwardDeclarations( 181 set<string>* fwd_decls) const { 182 // Nothing 183 } 184 185 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 216 void FieldGenerator::SetRuntimeHasBit(int has_index) { 217 variables_["has_index"] = SimpleItoa(has_index); 218 } 219 220 void FieldGenerator::SetNoHasBit(void) { 221 variables_["has_index"] = "GPBNoHasBit"; 222 } 223 224 int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { 225 return 0; 226 } 227 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 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 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 252 SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor, 253 const Options& options) 254 : FieldGenerator(descriptor, options) { 255 // Nothing 256 } 257 258 SingleFieldGenerator::~SingleFieldGenerator() {} 259 260 void SingleFieldGenerator::GenerateFieldStorageDeclaration( 261 io::Printer* printer) const { 262 printer->Print(variables_, "$storage_type$ $name$;\n"); 263 } 264 265 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 279 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 288 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 300 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 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 317 ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {} 318 319 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( 320 io::Printer* printer) const { 321 printer->Print(variables_, "$storage_type$ *$name$;\n"); 322 } 323 324 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 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 357 RepeatedFieldGenerator::~RepeatedFieldGenerator() {} 358 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 366 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( 367 io::Printer* printer) const { 368 printer->Print(variables_, "$array_storage_type$ *$name$;\n"); 369 } 370 371 void RepeatedFieldGenerator::GeneratePropertyImplementation( 372 io::Printer* printer) const { 373 printer->Print(variables_, "@dynamic $name$, $name$_Count;\n"); 374 } 375 376 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 401 bool RepeatedFieldGenerator::WantsHasProperty(void) const { 402 // Consumer check the array size/existance rather than a has bit. 403 return false; 404 } 405 406 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { 407 return false; // The array having anything is what is used. 408 } 409 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 428 FieldGeneratorMap::~FieldGeneratorMap() {} 429 430 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 436 const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { 437 return *extension_generators_[index]; 438 } 439 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 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 464 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