| 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 <algorithm> | 
|---|
| 32 | #include <iostream> | 
|---|
| 33 | #include <sstream> | 
|---|
| 34 |  | 
|---|
| 35 | #include <google/protobuf/compiler/objectivec/objectivec_message.h> | 
|---|
| 36 | #include <google/protobuf/compiler/objectivec/objectivec_enum.h> | 
|---|
| 37 | #include <google/protobuf/compiler/objectivec/objectivec_extension.h> | 
|---|
| 38 | #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> | 
|---|
| 39 | #include <google/protobuf/stubs/stl_util.h> | 
|---|
| 40 | #include <google/protobuf/stubs/strutil.h> | 
|---|
| 41 | #include <google/protobuf/io/printer.h> | 
|---|
| 42 | #include <google/protobuf/io/coded_stream.h> | 
|---|
| 43 | #include <google/protobuf/io/zero_copy_stream_impl.h> | 
|---|
| 44 | #include <google/protobuf/descriptor.pb.h> | 
|---|
| 45 |  | 
|---|
| 46 | namespace google { | 
|---|
| 47 | namespace protobuf { | 
|---|
| 48 | namespace compiler { | 
|---|
| 49 | namespace objectivec { | 
|---|
| 50 |  | 
|---|
| 51 | namespace { | 
|---|
| 52 | struct FieldOrderingByNumber { | 
|---|
| 53 | inline bool operator()(const FieldDescriptor* a, | 
|---|
| 54 | const FieldDescriptor* b) const { | 
|---|
| 55 | return a->number() < b->number(); | 
|---|
| 56 | } | 
|---|
| 57 | }; | 
|---|
| 58 |  | 
|---|
| 59 | int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { | 
|---|
| 60 | // The first item in the object structure is our uint32[] for has bits. | 
|---|
| 61 | // We then want to order things to make the instances as small as | 
|---|
| 62 | // possible. So we follow the has bits with: | 
|---|
| 63 | //   1. Anything always 4 bytes - float, *32, enums | 
|---|
| 64 | //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit | 
|---|
| 65 | //      builds and 4 bytes on 32bit builds. | 
|---|
| 66 | //   3. Anything always 8 bytes - double, *64 | 
|---|
| 67 | // | 
|---|
| 68 | // NOTE: Bools aren't listed, they were stored in the has bits. | 
|---|
| 69 | // | 
|---|
| 70 | // Why? Using 64bit builds as an example, this means worse case, we have | 
|---|
| 71 | // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes | 
|---|
| 72 | // are wasted before the 4 byte values. Then if we have an odd number of | 
|---|
| 73 | // those 4 byte values, the 8 byte values will be pushed down by 32bits to | 
|---|
| 74 | // keep them aligned. But the structure will end 8 byte aligned, so no | 
|---|
| 75 | // waste on the end. If you did the reverse order, you could waste 4 bytes | 
|---|
| 76 | // before the first 8 byte value (after the has array), then a single | 
|---|
| 77 | // bool on the end would need 7 bytes of padding to make the overall | 
|---|
| 78 | // structure 8 byte aligned; so 11 bytes, wasted total. | 
|---|
| 79 |  | 
|---|
| 80 | // Anything repeated is a GPB*Array/NSArray, so pointer. | 
|---|
| 81 | if (descriptor->is_repeated()) { | 
|---|
| 82 | return 3; | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | switch (descriptor->type()) { | 
|---|
| 86 | // All always 8 bytes. | 
|---|
| 87 | case FieldDescriptor::TYPE_DOUBLE: | 
|---|
| 88 | case FieldDescriptor::TYPE_INT64: | 
|---|
| 89 | case FieldDescriptor::TYPE_SINT64: | 
|---|
| 90 | case FieldDescriptor::TYPE_UINT64: | 
|---|
| 91 | case FieldDescriptor::TYPE_SFIXED64: | 
|---|
| 92 | case FieldDescriptor::TYPE_FIXED64: | 
|---|
| 93 | return 4; | 
|---|
| 94 |  | 
|---|
| 95 | // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes | 
|---|
| 96 | // depending on the build architecture. | 
|---|
| 97 | case FieldDescriptor::TYPE_GROUP: | 
|---|
| 98 | case FieldDescriptor::TYPE_MESSAGE: | 
|---|
| 99 | case FieldDescriptor::TYPE_STRING: | 
|---|
| 100 | case FieldDescriptor::TYPE_BYTES: | 
|---|
| 101 | return 3; | 
|---|
| 102 |  | 
|---|
| 103 | // All always 4 bytes (enums are int32s). | 
|---|
| 104 | case FieldDescriptor::TYPE_FLOAT: | 
|---|
| 105 | case FieldDescriptor::TYPE_INT32: | 
|---|
| 106 | case FieldDescriptor::TYPE_SINT32: | 
|---|
| 107 | case FieldDescriptor::TYPE_UINT32: | 
|---|
| 108 | case FieldDescriptor::TYPE_SFIXED32: | 
|---|
| 109 | case FieldDescriptor::TYPE_FIXED32: | 
|---|
| 110 | case FieldDescriptor::TYPE_ENUM: | 
|---|
| 111 | return 2; | 
|---|
| 112 |  | 
|---|
| 113 | // 0 bytes. Stored in the has bits. | 
|---|
| 114 | case FieldDescriptor::TYPE_BOOL: | 
|---|
| 115 | return 99;  // End of the list (doesn't really matter). | 
|---|
| 116 | } | 
|---|
| 117 |  | 
|---|
| 118 | // Some compilers report reaching end of function even though all cases of | 
|---|
| 119 | // the enum are handed in the switch. | 
|---|
| 120 | GOOGLE_LOG(FATAL) << "Can't get here."; | 
|---|
| 121 | return 0; | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | struct FieldOrderingByStorageSize { | 
|---|
| 125 | inline bool operator()(const FieldDescriptor* a, | 
|---|
| 126 | const FieldDescriptor* b) const { | 
|---|
| 127 | // Order by grouping. | 
|---|
| 128 | const int order_group_a = OrderGroupForFieldDescriptor(descriptor: a); | 
|---|
| 129 | const int order_group_b = OrderGroupForFieldDescriptor(descriptor: b); | 
|---|
| 130 | if (order_group_a != order_group_b) { | 
|---|
| 131 | return order_group_a < order_group_b; | 
|---|
| 132 | } | 
|---|
| 133 | // Within the group, order by field number (provides stable ordering). | 
|---|
| 134 | return a->number() < b->number(); | 
|---|
| 135 | } | 
|---|
| 136 | }; | 
|---|
| 137 |  | 
|---|
| 138 | struct ExtensionRangeOrdering { | 
|---|
| 139 | bool operator()(const Descriptor::ExtensionRange* a, | 
|---|
| 140 | const Descriptor::ExtensionRange* b) const { | 
|---|
| 141 | return a->start < b->start; | 
|---|
| 142 | } | 
|---|
| 143 | }; | 
|---|
| 144 |  | 
|---|
| 145 | // Sort the fields of the given Descriptor by number into a new[]'d array | 
|---|
| 146 | // and return it. | 
|---|
| 147 | const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { | 
|---|
| 148 | const FieldDescriptor** fields = | 
|---|
| 149 | new const FieldDescriptor* [descriptor->field_count()]; | 
|---|
| 150 | for (int i = 0; i < descriptor->field_count(); i++) { | 
|---|
| 151 | fields[i] = descriptor->field(index: i); | 
|---|
| 152 | } | 
|---|
| 153 | std::sort(first: fields, last: fields + descriptor->field_count(), comp: FieldOrderingByNumber()); | 
|---|
| 154 | return fields; | 
|---|
| 155 | } | 
|---|
| 156 |  | 
|---|
| 157 | // Sort the fields of the given Descriptor by storage size into a new[]'d | 
|---|
| 158 | // array and return it. | 
|---|
| 159 | const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { | 
|---|
| 160 | const FieldDescriptor** fields = | 
|---|
| 161 | new const FieldDescriptor* [descriptor->field_count()]; | 
|---|
| 162 | for (int i = 0; i < descriptor->field_count(); i++) { | 
|---|
| 163 | fields[i] = descriptor->field(index: i); | 
|---|
| 164 | } | 
|---|
| 165 | std::sort(first: fields, last: fields + descriptor->field_count(), | 
|---|
| 166 | comp: FieldOrderingByStorageSize()); | 
|---|
| 167 | return fields; | 
|---|
| 168 | } | 
|---|
| 169 | }  // namespace | 
|---|
| 170 |  | 
|---|
| 171 | MessageGenerator::MessageGenerator(const std::string& root_classname, | 
|---|
| 172 | const Descriptor* descriptor) | 
|---|
| 173 | : root_classname_(root_classname), | 
|---|
| 174 | descriptor_(descriptor), | 
|---|
| 175 | field_generators_(descriptor), | 
|---|
| 176 | class_name_(ClassName(descriptor: descriptor_)), | 
|---|
| 177 | deprecated_attribute_(GetOptionalDeprecatedAttribute( | 
|---|
| 178 | descriptor, file: descriptor->file(), preSpace: false, postNewline: true)) { | 
|---|
| 179 | for (int i = 0; i < descriptor_->extension_count(); i++) { | 
|---|
| 180 | extension_generators_.emplace_back( | 
|---|
| 181 | args: new ExtensionGenerator(class_name_, descriptor_->extension(index: i))); | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { | 
|---|
| 185 | OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(index: i)); | 
|---|
| 186 | oneof_generators_.emplace_back(args&: generator); | 
|---|
| 187 | } | 
|---|
| 188 |  | 
|---|
| 189 | for (int i = 0; i < descriptor_->enum_type_count(); i++) { | 
|---|
| 190 | EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(index: i)); | 
|---|
| 191 | enum_generators_.emplace_back(args&: generator); | 
|---|
| 192 | } | 
|---|
| 193 |  | 
|---|
| 194 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { | 
|---|
| 195 | MessageGenerator* generator = | 
|---|
| 196 | new MessageGenerator(root_classname_, | 
|---|
| 197 | descriptor_->nested_type(index: i)); | 
|---|
| 198 | nested_message_generators_.emplace_back(args&: generator); | 
|---|
| 199 | } | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | MessageGenerator::~MessageGenerator() {} | 
|---|
| 203 |  | 
|---|
| 204 | void MessageGenerator::GenerateStaticVariablesInitialization( | 
|---|
| 205 | io::Printer* printer) { | 
|---|
| 206 | for (const auto& generator : extension_generators_) { | 
|---|
| 207 | generator->GenerateStaticVariablesInitialization(printer); | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 211 | generator->GenerateStaticVariablesInitialization(printer); | 
|---|
| 212 | } | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | void MessageGenerator::DetermineForwardDeclarations( | 
|---|
| 216 | std::set<std::string>* fwd_decls, | 
|---|
| 217 | bool include_external_types) { | 
|---|
| 218 | if (!IsMapEntryMessage(descriptor: descriptor_)) { | 
|---|
| 219 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 220 | const FieldDescriptor* fieldDescriptor = descriptor_->field(index: i); | 
|---|
| 221 | field_generators_.get(field: fieldDescriptor) | 
|---|
| 222 | .DetermineForwardDeclarations(fwd_decls, include_external_types); | 
|---|
| 223 | } | 
|---|
| 224 | } | 
|---|
| 225 |  | 
|---|
| 226 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 227 | generator->DetermineForwardDeclarations(fwd_decls, include_external_types); | 
|---|
| 228 | } | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | void MessageGenerator::DetermineObjectiveCClassDefinitions( | 
|---|
| 232 | std::set<std::string>* fwd_decls) { | 
|---|
| 233 | if (!IsMapEntryMessage(descriptor: descriptor_)) { | 
|---|
| 234 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 235 | const FieldDescriptor* fieldDescriptor = descriptor_->field(index: i); | 
|---|
| 236 | field_generators_.get(field: fieldDescriptor) | 
|---|
| 237 | .DetermineObjectiveCClassDefinitions(fwd_decls); | 
|---|
| 238 | } | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | for (const auto& generator : extension_generators_) { | 
|---|
| 242 | generator->DetermineObjectiveCClassDefinitions(fwd_decls); | 
|---|
| 243 | } | 
|---|
| 244 |  | 
|---|
| 245 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 246 | generator->DetermineObjectiveCClassDefinitions(fwd_decls); | 
|---|
| 247 | } | 
|---|
| 248 |  | 
|---|
| 249 | const Descriptor* containing_descriptor = descriptor_->containing_type(); | 
|---|
| 250 | if (containing_descriptor != NULL) { | 
|---|
| 251 | std::string containing_class = ClassName(descriptor: containing_descriptor); | 
|---|
| 252 | fwd_decls->insert(x: ObjCClassDeclaration(class_name: containing_class)); | 
|---|
| 253 | } | 
|---|
| 254 | } | 
|---|
| 255 |  | 
|---|
| 256 | bool MessageGenerator::IncludesOneOfDefinition() const { | 
|---|
| 257 | if (!oneof_generators_.empty()) { | 
|---|
| 258 | return true; | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 262 | if (generator->IncludesOneOfDefinition()) { | 
|---|
| 263 | return true; | 
|---|
| 264 | } | 
|---|
| 265 | } | 
|---|
| 266 |  | 
|---|
| 267 | return false; | 
|---|
| 268 | } | 
|---|
| 269 |  | 
|---|
| 270 | void MessageGenerator::(io::Printer* printer) { | 
|---|
| 271 | for (const auto& generator : enum_generators_) { | 
|---|
| 272 | generator->GenerateHeader(printer); | 
|---|
| 273 | } | 
|---|
| 274 |  | 
|---|
| 275 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 276 | generator->GenerateEnumHeader(printer); | 
|---|
| 277 | } | 
|---|
| 278 | } | 
|---|
| 279 |  | 
|---|
| 280 | void MessageGenerator::GenerateExtensionRegistrationSource( | 
|---|
| 281 | io::Printer* printer) { | 
|---|
| 282 | for (const auto& generator : extension_generators_) { | 
|---|
| 283 | generator->GenerateRegistrationSource(printer); | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 287 | generator->GenerateExtensionRegistrationSource(printer); | 
|---|
| 288 | } | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|
| 291 | void MessageGenerator::(io::Printer* printer) { | 
|---|
| 292 | // This a a map entry message, just recurse and do nothing directly. | 
|---|
| 293 | if (IsMapEntryMessage(descriptor: descriptor_)) { | 
|---|
| 294 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 295 | generator->GenerateMessageHeader(printer); | 
|---|
| 296 | } | 
|---|
| 297 | return; | 
|---|
| 298 | } | 
|---|
| 299 |  | 
|---|
| 300 | printer->Print( | 
|---|
| 301 | text: "#pragma mark - $classname$\n" | 
|---|
| 302 | "\n", | 
|---|
| 303 | args: "classname", args: class_name_); | 
|---|
| 304 |  | 
|---|
| 305 | if (descriptor_->field_count()) { | 
|---|
| 306 | std::unique_ptr<const FieldDescriptor*[]> sorted_fields( | 
|---|
| 307 | SortFieldsByNumber(descriptor: descriptor_)); | 
|---|
| 308 |  | 
|---|
| 309 | printer->Print(text: "typedef GPB_ENUM($classname$_FieldNumber) {\n", | 
|---|
| 310 | args: "classname", args: class_name_); | 
|---|
| 311 | printer->Indent(); | 
|---|
| 312 |  | 
|---|
| 313 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 314 | field_generators_.get(field: sorted_fields[i]) | 
|---|
| 315 | .GenerateFieldNumberConstant(printer); | 
|---|
| 316 | } | 
|---|
| 317 |  | 
|---|
| 318 | printer->Outdent(); | 
|---|
| 319 | printer->Print(text: "};\n\n"); | 
|---|
| 320 | } | 
|---|
| 321 |  | 
|---|
| 322 | for (const auto& generator : oneof_generators_) { | 
|---|
| 323 | generator->GenerateCaseEnum(printer); | 
|---|
| 324 | } | 
|---|
| 325 |  | 
|---|
| 326 | std::string ; | 
|---|
| 327 | SourceLocation location; | 
|---|
| 328 | if (descriptor_->GetSourceLocation(out_location: &location)) { | 
|---|
| 329 | message_comments = BuildCommentsString(location, prefer_single_line: false); | 
|---|
| 330 | } else { | 
|---|
| 331 | message_comments = ""; | 
|---|
| 332 | } | 
|---|
| 333 |  | 
|---|
| 334 | printer->Print( | 
|---|
| 335 | text: "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n", | 
|---|
| 336 | args: "classname", args: class_name_, | 
|---|
| 337 | args: "deprecated_attribute", args: deprecated_attribute_, | 
|---|
| 338 | args: "comments", args: message_comments); | 
|---|
| 339 |  | 
|---|
| 340 | std::vector<char> seen_oneofs(oneof_generators_.size(), 0); | 
|---|
| 341 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 342 | const FieldDescriptor* field = descriptor_->field(index: i); | 
|---|
| 343 | const OneofDescriptor* oneof = field->real_containing_oneof(); | 
|---|
| 344 | if (oneof) { | 
|---|
| 345 | const int oneof_index = oneof->index(); | 
|---|
| 346 | if (!seen_oneofs[oneof_index]) { | 
|---|
| 347 | seen_oneofs[oneof_index] = 1; | 
|---|
| 348 | oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( | 
|---|
| 349 | printer); | 
|---|
| 350 | } | 
|---|
| 351 | } | 
|---|
| 352 | field_generators_.get(field).GeneratePropertyDeclaration(printer); | 
|---|
| 353 | } | 
|---|
| 354 |  | 
|---|
| 355 | printer->Print(text: "@end\n\n"); | 
|---|
| 356 |  | 
|---|
| 357 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 358 | field_generators_.get(field: descriptor_->field(index: i)) | 
|---|
| 359 | .GenerateCFunctionDeclarations(printer); | 
|---|
| 360 | } | 
|---|
| 361 |  | 
|---|
| 362 | if (!oneof_generators_.empty()) { | 
|---|
| 363 | for (const auto& generator : oneof_generators_) { | 
|---|
| 364 | generator->GenerateClearFunctionDeclaration(printer); | 
|---|
| 365 | } | 
|---|
| 366 | printer->Print(text: "\n"); | 
|---|
| 367 | } | 
|---|
| 368 |  | 
|---|
| 369 | if (descriptor_->extension_count() > 0) { | 
|---|
| 370 | printer->Print(text: "@interface $classname$ (DynamicMethods)\n\n", | 
|---|
| 371 | args: "classname", args: class_name_); | 
|---|
| 372 | for (const auto& generator : extension_generators_) { | 
|---|
| 373 | generator->GenerateMembersHeader(printer); | 
|---|
| 374 | } | 
|---|
| 375 | printer->Print(text: "@end\n\n"); | 
|---|
| 376 | } | 
|---|
| 377 |  | 
|---|
| 378 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 379 | generator->GenerateMessageHeader(printer); | 
|---|
| 380 | } | 
|---|
| 381 | } | 
|---|
| 382 |  | 
|---|
| 383 | void MessageGenerator::GenerateSource(io::Printer* printer) { | 
|---|
| 384 | if (!IsMapEntryMessage(descriptor: descriptor_)) { | 
|---|
| 385 | printer->Print( | 
|---|
| 386 | text: "#pragma mark - $classname$\n" | 
|---|
| 387 | "\n", | 
|---|
| 388 | args: "classname", args: class_name_); | 
|---|
| 389 |  | 
|---|
| 390 | if (!deprecated_attribute_.empty()) { | 
|---|
| 391 | // No warnings when compiling the impl of this deprecated class. | 
|---|
| 392 | printer->Print( | 
|---|
| 393 | text: "#pragma clang diagnostic push\n" | 
|---|
| 394 | "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" | 
|---|
| 395 | "\n"); | 
|---|
| 396 | } | 
|---|
| 397 |  | 
|---|
| 398 | printer->Print(text: "@implementation $classname$\n\n", | 
|---|
| 399 | args: "classname", args: class_name_); | 
|---|
| 400 |  | 
|---|
| 401 | for (const auto& generator : oneof_generators_) { | 
|---|
| 402 | generator->GeneratePropertyImplementation(printer); | 
|---|
| 403 | } | 
|---|
| 404 |  | 
|---|
| 405 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 406 | field_generators_.get(field: descriptor_->field(index: i)) | 
|---|
| 407 | .GeneratePropertyImplementation(printer); | 
|---|
| 408 | } | 
|---|
| 409 |  | 
|---|
| 410 | std::unique_ptr<const FieldDescriptor*[]> sorted_fields( | 
|---|
| 411 | SortFieldsByNumber(descriptor: descriptor_)); | 
|---|
| 412 | std::unique_ptr<const FieldDescriptor*[]> size_order_fields( | 
|---|
| 413 | SortFieldsByStorageSize(descriptor: descriptor_)); | 
|---|
| 414 |  | 
|---|
| 415 | std::vector<const Descriptor::ExtensionRange*> sorted_extensions; | 
|---|
| 416 | sorted_extensions.reserve(n: descriptor_->extension_range_count()); | 
|---|
| 417 | for (int i = 0; i < descriptor_->extension_range_count(); ++i) { | 
|---|
| 418 | sorted_extensions.push_back(x: descriptor_->extension_range(index: i)); | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 | std::sort(first: sorted_extensions.begin(), last: sorted_extensions.end(), | 
|---|
| 422 | comp: ExtensionRangeOrdering()); | 
|---|
| 423 |  | 
|---|
| 424 | // Assign has bits: | 
|---|
| 425 | // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing | 
|---|
| 426 | //    who needs has bits and assigning them. | 
|---|
| 427 | // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative | 
|---|
| 428 | //    index that groups all the elements in the oneof. | 
|---|
| 429 | size_t num_has_bits = field_generators_.CalculateHasBits(); | 
|---|
| 430 | size_t sizeof_has_storage = (num_has_bits + 31) / 32; | 
|---|
| 431 | if (sizeof_has_storage == 0) { | 
|---|
| 432 | // In the case where no field needs has bits, don't let the _has_storage_ | 
|---|
| 433 | // end up as zero length (zero length arrays are sort of a grey area | 
|---|
| 434 | // since it has to be at the start of the struct). This also ensures a | 
|---|
| 435 | // field with only oneofs keeps the required negative indices they need. | 
|---|
| 436 | sizeof_has_storage = 1; | 
|---|
| 437 | } | 
|---|
| 438 | // Tell all the fields the oneof base. | 
|---|
| 439 | for (const auto& generator : oneof_generators_) { | 
|---|
| 440 | generator->SetOneofIndexBase(sizeof_has_storage); | 
|---|
| 441 | } | 
|---|
| 442 | field_generators_.SetOneofIndexBase(sizeof_has_storage); | 
|---|
| 443 | // sizeof_has_storage needs enough bits for the single fields that aren't in | 
|---|
| 444 | // any oneof, and then one int32 for each oneof (to store the field number). | 
|---|
| 445 | sizeof_has_storage += oneof_generators_.size(); | 
|---|
| 446 |  | 
|---|
| 447 | printer->Print( | 
|---|
| 448 | text: "\n" | 
|---|
| 449 | "typedef struct $classname$__storage_ {\n" | 
|---|
| 450 | "  uint32_t _has_storage_[$sizeof_has_storage$];\n", | 
|---|
| 451 | args: "classname", args: class_name_, | 
|---|
| 452 | args: "sizeof_has_storage", args: StrCat(a: sizeof_has_storage)); | 
|---|
| 453 | printer->Indent(); | 
|---|
| 454 |  | 
|---|
| 455 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 456 | field_generators_.get(field: size_order_fields[i]) | 
|---|
| 457 | .GenerateFieldStorageDeclaration(printer); | 
|---|
| 458 | } | 
|---|
| 459 | printer->Outdent(); | 
|---|
| 460 |  | 
|---|
| 461 | printer->Print(text: "} $classname$__storage_;\n\n", args: "classname", args: class_name_); | 
|---|
| 462 |  | 
|---|
| 463 |  | 
|---|
| 464 | printer->Print( | 
|---|
| 465 | text: "// This method is threadsafe because it is initially called\n" | 
|---|
| 466 | "// in +initialize for each subclass.\n" | 
|---|
| 467 | "+ (GPBDescriptor *)descriptor {\n" | 
|---|
| 468 | "  static GPBDescriptor *descriptor = nil;\n" | 
|---|
| 469 | "  if (!descriptor) {\n"); | 
|---|
| 470 |  | 
|---|
| 471 | TextFormatDecodeData text_format_decode_data; | 
|---|
| 472 | bool has_fields = descriptor_->field_count() > 0; | 
|---|
| 473 | bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); | 
|---|
| 474 | std::string field_description_type; | 
|---|
| 475 | if (need_defaults) { | 
|---|
| 476 | field_description_type = "GPBMessageFieldDescriptionWithDefault"; | 
|---|
| 477 | } else { | 
|---|
| 478 | field_description_type = "GPBMessageFieldDescription"; | 
|---|
| 479 | } | 
|---|
| 480 | if (has_fields) { | 
|---|
| 481 | printer->Indent(); | 
|---|
| 482 | printer->Indent(); | 
|---|
| 483 | printer->Print( | 
|---|
| 484 | text: "static $field_description_type$ fields[] = {\n", | 
|---|
| 485 | args: "field_description_type", args: field_description_type); | 
|---|
| 486 | printer->Indent(); | 
|---|
| 487 | for (int i = 0; i < descriptor_->field_count(); ++i) { | 
|---|
| 488 | const FieldGenerator& field_generator = | 
|---|
| 489 | field_generators_.get(field: sorted_fields[i]); | 
|---|
| 490 | field_generator.GenerateFieldDescription(printer, include_default: need_defaults); | 
|---|
| 491 | if (field_generator.needs_textformat_name_support()) { | 
|---|
| 492 | text_format_decode_data.AddString(key: sorted_fields[i]->number(), | 
|---|
| 493 | input_for_decode: field_generator.generated_objc_name(), | 
|---|
| 494 | desired_output: field_generator.raw_field_name()); | 
|---|
| 495 | } | 
|---|
| 496 | } | 
|---|
| 497 | printer->Outdent(); | 
|---|
| 498 | printer->Print( | 
|---|
| 499 | text: "};\n"); | 
|---|
| 500 | printer->Outdent(); | 
|---|
| 501 | printer->Outdent(); | 
|---|
| 502 | } | 
|---|
| 503 |  | 
|---|
| 504 | std::map<std::string, std::string> vars; | 
|---|
| 505 | vars[ "classname"] = class_name_; | 
|---|
| 506 | vars[ "rootclassname"] = root_classname_; | 
|---|
| 507 | vars[ "fields"] = has_fields ? "fields": "NULL"; | 
|---|
| 508 | if (has_fields) { | 
|---|
| 509 | vars[ "fields_count"] = | 
|---|
| 510 | "(uint32_t)(sizeof(fields) / sizeof("+ field_description_type + "))"; | 
|---|
| 511 | } else { | 
|---|
| 512 | vars[ "fields_count"] = "0"; | 
|---|
| 513 | } | 
|---|
| 514 |  | 
|---|
| 515 | std::vector<std::string> init_flags; | 
|---|
| 516 | init_flags.push_back(x: "GPBDescriptorInitializationFlag_UsesClassRefs"); | 
|---|
| 517 | init_flags.push_back(x: "GPBDescriptorInitializationFlag_Proto3OptionalKnown"); | 
|---|
| 518 | if (need_defaults) { | 
|---|
| 519 | init_flags.push_back(x: "GPBDescriptorInitializationFlag_FieldsWithDefault"); | 
|---|
| 520 | } | 
|---|
| 521 | if (descriptor_->options().message_set_wire_format()) { | 
|---|
| 522 | init_flags.push_back(x: "GPBDescriptorInitializationFlag_WireFormat"); | 
|---|
| 523 | } | 
|---|
| 524 | vars[ "init_flags"] = BuildFlagsString(type: FLAGTYPE_DESCRIPTOR_INITIALIZATION, | 
|---|
| 525 | strings: init_flags); | 
|---|
| 526 |  | 
|---|
| 527 | printer->Print( | 
|---|
| 528 | variables: vars, | 
|---|
| 529 | text: "    GPBDescriptor *localDescriptor =\n" | 
|---|
| 530 | "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" | 
|---|
| 531 | "                                     rootClass:[$rootclassname$ class]\n" | 
|---|
| 532 | "                                          file:$rootclassname$_FileDescriptor()\n" | 
|---|
| 533 | "                                        fields:$fields$\n" | 
|---|
| 534 | "                                    fieldCount:$fields_count$\n" | 
|---|
| 535 | "                                   storageSize:sizeof($classname$__storage_)\n" | 
|---|
| 536 | "                                         flags:$init_flags$];\n"); | 
|---|
| 537 | if (!oneof_generators_.empty()) { | 
|---|
| 538 | printer->Print( | 
|---|
| 539 | text: "    static const char *oneofs[] = {\n"); | 
|---|
| 540 | for (const auto& generator : oneof_generators_) { | 
|---|
| 541 | printer->Print(text: "      \"$name$\",\n", args: "name", | 
|---|
| 542 | args: generator->DescriptorName()); | 
|---|
| 543 | } | 
|---|
| 544 | printer->Print( | 
|---|
| 545 | text: "    };\n" | 
|---|
| 546 | "    [localDescriptor setupOneofs:oneofs\n" | 
|---|
| 547 | "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n" | 
|---|
| 548 | "                   firstHasIndex:$first_has_index$];\n", | 
|---|
| 549 | args: "first_has_index", args: oneof_generators_[0]->HasIndexAsString()); | 
|---|
| 550 | } | 
|---|
| 551 | if (text_format_decode_data.num_entries() != 0) { | 
|---|
| 552 | const std::string text_format_data_str(text_format_decode_data.Data()); | 
|---|
| 553 | printer->Print( | 
|---|
| 554 | text: "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" | 
|---|
| 555 | "    static const char *extraTextFormatInfo ="); | 
|---|
| 556 | static const int kBytesPerLine = 40;  // allow for escaping | 
|---|
| 557 | for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { | 
|---|
| 558 | printer->Print( | 
|---|
| 559 | text: "\n        \"$data$\"", | 
|---|
| 560 | args: "data", args: EscapeTrigraphs( | 
|---|
| 561 | to_escape: CEscape(src: text_format_data_str.substr(pos: i, n: kBytesPerLine)))); | 
|---|
| 562 | } | 
|---|
| 563 | printer->Print( | 
|---|
| 564 | text: ";\n" | 
|---|
| 565 | "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" | 
|---|
| 566 | "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); | 
|---|
| 567 | } | 
|---|
| 568 | if (!sorted_extensions.empty()) { | 
|---|
| 569 | printer->Print( | 
|---|
| 570 | text: "    static const GPBExtensionRange ranges[] = {\n"); | 
|---|
| 571 | for (int i = 0; i < sorted_extensions.size(); i++) { | 
|---|
| 572 | printer->Print(text: "      { .start = $start$, .end = $end$ },\n", | 
|---|
| 573 | args: "start", args: StrCat(a: sorted_extensions[i]->start), | 
|---|
| 574 | args: "end", args: StrCat(a: sorted_extensions[i]->end)); | 
|---|
| 575 | } | 
|---|
| 576 | printer->Print( | 
|---|
| 577 | text: "    };\n" | 
|---|
| 578 | "    [localDescriptor setupExtensionRanges:ranges\n" | 
|---|
| 579 | "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); | 
|---|
| 580 | } | 
|---|
| 581 | if (descriptor_->containing_type() != NULL) { | 
|---|
| 582 | std::string containing_class = ClassName(descriptor: descriptor_->containing_type()); | 
|---|
| 583 | std::string parent_class_ref = ObjCClass(class_name: containing_class); | 
|---|
| 584 | printer->Print( | 
|---|
| 585 | text: "    [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", | 
|---|
| 586 | args: "parent_class_ref", args: parent_class_ref); | 
|---|
| 587 | } | 
|---|
| 588 | std::string suffix_added; | 
|---|
| 589 | ClassName(descriptor: descriptor_, out_suffix_added: &suffix_added); | 
|---|
| 590 | if (!suffix_added.empty()) { | 
|---|
| 591 | printer->Print( | 
|---|
| 592 | text: "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", | 
|---|
| 593 | args: "suffix", args: suffix_added); | 
|---|
| 594 | } | 
|---|
| 595 | printer->Print( | 
|---|
| 596 | text: "    #if defined(DEBUG) && DEBUG\n" | 
|---|
| 597 | "      NSAssert(descriptor == nil, @\"Startup recursed!\");\n" | 
|---|
| 598 | "    #endif  // DEBUG\n" | 
|---|
| 599 | "    descriptor = localDescriptor;\n" | 
|---|
| 600 | "  }\n" | 
|---|
| 601 | "  return descriptor;\n" | 
|---|
| 602 | "}\n\n" | 
|---|
| 603 | "@end\n\n"); | 
|---|
| 604 |  | 
|---|
| 605 | if (!deprecated_attribute_.empty()) { | 
|---|
| 606 | printer->Print( | 
|---|
| 607 | text: "#pragma clang diagnostic pop\n" | 
|---|
| 608 | "\n"); | 
|---|
| 609 | } | 
|---|
| 610 |  | 
|---|
| 611 | for (int i = 0; i < descriptor_->field_count(); i++) { | 
|---|
| 612 | field_generators_.get(field: descriptor_->field(index: i)) | 
|---|
| 613 | .GenerateCFunctionImplementations(printer); | 
|---|
| 614 | } | 
|---|
| 615 |  | 
|---|
| 616 | for (const auto& generator : oneof_generators_) { | 
|---|
| 617 | generator->GenerateClearFunctionImplementation(printer); | 
|---|
| 618 | } | 
|---|
| 619 | } | 
|---|
| 620 |  | 
|---|
| 621 | for (const auto& generator : enum_generators_) { | 
|---|
| 622 | generator->GenerateSource(printer); | 
|---|
| 623 | } | 
|---|
| 624 |  | 
|---|
| 625 | for (const auto& generator : nested_message_generators_) { | 
|---|
| 626 | generator->GenerateSource(printer); | 
|---|
| 627 | } | 
|---|
| 628 | } | 
|---|
| 629 |  | 
|---|
| 630 | }  // namespace objectivec | 
|---|
| 631 | }  // namespace compiler | 
|---|
| 632 | }  // namespace protobuf | 
|---|
| 633 | }  // namespace google | 
|---|
| 634 |  | 
|---|