OLD | NEW |
(Empty) | |
| 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 #import "GPBMessage_PackagePrivate.h" |
| 32 |
| 33 #import <objc/runtime.h> |
| 34 #import <objc/message.h> |
| 35 |
| 36 #import "GPBArray_PackagePrivate.h" |
| 37 #import "GPBCodedInputStream_PackagePrivate.h" |
| 38 #import "GPBCodedOutputStream.h" |
| 39 #import "GPBDescriptor_PackagePrivate.h" |
| 40 #import "GPBDictionary_PackagePrivate.h" |
| 41 #import "GPBExtensionInternals.h" |
| 42 #import "GPBExtensionRegistry.h" |
| 43 #import "GPBRootObject_PackagePrivate.h" |
| 44 #import "GPBUnknownFieldSet_PackagePrivate.h" |
| 45 #import "GPBUtilities_PackagePrivate.h" |
| 46 |
| 47 NSString *const GPBMessageErrorDomain = |
| 48 GPBNSStringifySymbol(GPBMessageErrorDomain); |
| 49 |
| 50 #ifdef DEBUG |
| 51 NSString *const GPBExceptionMessageKey = |
| 52 GPBNSStringifySymbol(GPBExceptionMessage); |
| 53 #endif // DEBUG |
| 54 |
| 55 static NSString *const kGPBDataCoderKey = @"GPBData"; |
| 56 |
| 57 #ifndef _GPBCompileAssert |
| 58 #if __has_feature(c_static_assert) || __has_extension(c_static_assert) |
| 59 #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg) |
| 60 #else |
| 61 // Pre-Xcode 7 support. |
| 62 #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ##
__ ## msg |
| 63 #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line
, msg) |
| 64 #define _GPBCompileAssert(test, msg) \ |
| 65 typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1)
] |
| 66 #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) |
| 67 #endif // _GPBCompileAssert |
| 68 |
| 69 // |
| 70 // PLEASE REMEMBER: |
| 71 // |
| 72 // This is the base class for *all* messages generated, so any selector defined, |
| 73 // *public* or *private* could end up colliding with a proto message field. So |
| 74 // avoid using selectors that could match a property, use C functions to hide |
| 75 // them, etc. |
| 76 // |
| 77 |
| 78 @interface GPBMessage () { |
| 79 @package |
| 80 GPBUnknownFieldSet *unknownFields_; |
| 81 NSMutableDictionary *extensionMap_; |
| 82 NSMutableDictionary *autocreatedExtensionMap_; |
| 83 |
| 84 // If the object was autocreated, we remember the creator so that if we get |
| 85 // mutated, we can inform the creator to make our field visible. |
| 86 GPBMessage *autocreator_; |
| 87 GPBFieldDescriptor *autocreatorField_; |
| 88 GPBExtensionDescriptor *autocreatorExtension_; |
| 89 } |
| 90 @end |
| 91 |
| 92 static id CreateArrayForField(GPBFieldDescriptor *field, |
| 93 GPBMessage *autocreator) |
| 94 __attribute__((ns_returns_retained)); |
| 95 static id GetOrCreateArrayIvarWithField(GPBMessage *self, |
| 96 GPBFieldDescriptor *field, |
| 97 GPBFileSyntax syntax); |
| 98 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); |
| 99 static id CreateMapForField(GPBFieldDescriptor *field, |
| 100 GPBMessage *autocreator) |
| 101 __attribute__((ns_returns_retained)); |
| 102 static id GetOrCreateMapIvarWithField(GPBMessage *self, |
| 103 GPBFieldDescriptor *field, |
| 104 GPBFileSyntax syntax); |
| 105 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); |
| 106 static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, |
| 107 NSZone *zone) |
| 108 __attribute__((ns_returns_retained)); |
| 109 |
| 110 static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { |
| 111 return [NSError errorWithDomain:GPBMessageErrorDomain |
| 112 code:code |
| 113 userInfo:userInfo]; |
| 114 } |
| 115 |
| 116 static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) { |
| 117 NSDictionary *userInfo = nil; |
| 118 if ([reason length]) { |
| 119 userInfo = @{ @"Reason" : reason }; |
| 120 } |
| 121 return MessageError(code, userInfo); |
| 122 } |
| 123 |
| 124 |
| 125 static void CheckExtension(GPBMessage *self, |
| 126 GPBExtensionDescriptor *extension) { |
| 127 if ([self class] != extension.containingMessageClass) { |
| 128 [NSException |
| 129 raise:NSInvalidArgumentException |
| 130 format:@"Extension %@ used on wrong class (%@ instead of %@)", |
| 131 extension.singletonName, |
| 132 [self class], extension.containingMessageClass]; |
| 133 } |
| 134 } |
| 135 |
| 136 static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, |
| 137 NSZone *zone) { |
| 138 if (extensionMap.count == 0) { |
| 139 return nil; |
| 140 } |
| 141 NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone] |
| 142 initWithCapacity:extensionMap.count]; |
| 143 |
| 144 for (GPBExtensionDescriptor *extension in extensionMap) { |
| 145 id value = [extensionMap objectForKey:extension]; |
| 146 BOOL isMessageExtension = GPBExtensionIsMessage(extension); |
| 147 |
| 148 if (extension.repeated) { |
| 149 if (isMessageExtension) { |
| 150 NSMutableArray *list = |
| 151 [[NSMutableArray alloc] initWithCapacity:[value count]]; |
| 152 for (GPBMessage *listValue in value) { |
| 153 GPBMessage *copiedValue = [listValue copyWithZone:zone]; |
| 154 [list addObject:copiedValue]; |
| 155 [copiedValue release]; |
| 156 } |
| 157 [result setObject:list forKey:extension]; |
| 158 [list release]; |
| 159 } else { |
| 160 NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; |
| 161 [result setObject:copiedValue forKey:extension]; |
| 162 [copiedValue release]; |
| 163 } |
| 164 } else { |
| 165 if (isMessageExtension) { |
| 166 GPBMessage *copiedValue = [value copyWithZone:zone]; |
| 167 [result setObject:copiedValue forKey:extension]; |
| 168 [copiedValue release]; |
| 169 } else { |
| 170 [result setObject:value forKey:extension]; |
| 171 } |
| 172 } |
| 173 } |
| 174 |
| 175 return result; |
| 176 } |
| 177 |
| 178 static id CreateArrayForField(GPBFieldDescriptor *field, |
| 179 GPBMessage *autocreator) { |
| 180 id result; |
| 181 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 182 switch (fieldDataType) { |
| 183 case GPBDataTypeBool: |
| 184 result = [[GPBBoolArray alloc] init]; |
| 185 break; |
| 186 case GPBDataTypeFixed32: |
| 187 case GPBDataTypeUInt32: |
| 188 result = [[GPBUInt32Array alloc] init]; |
| 189 break; |
| 190 case GPBDataTypeInt32: |
| 191 case GPBDataTypeSFixed32: |
| 192 case GPBDataTypeSInt32: |
| 193 result = [[GPBInt32Array alloc] init]; |
| 194 break; |
| 195 case GPBDataTypeFixed64: |
| 196 case GPBDataTypeUInt64: |
| 197 result = [[GPBUInt64Array alloc] init]; |
| 198 break; |
| 199 case GPBDataTypeInt64: |
| 200 case GPBDataTypeSFixed64: |
| 201 case GPBDataTypeSInt64: |
| 202 result = [[GPBInt64Array alloc] init]; |
| 203 break; |
| 204 case GPBDataTypeFloat: |
| 205 result = [[GPBFloatArray alloc] init]; |
| 206 break; |
| 207 case GPBDataTypeDouble: |
| 208 result = [[GPBDoubleArray alloc] init]; |
| 209 break; |
| 210 |
| 211 case GPBDataTypeEnum: |
| 212 result = [[GPBEnumArray alloc] |
| 213 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 214 break; |
| 215 |
| 216 case GPBDataTypeBytes: |
| 217 case GPBDataTypeGroup: |
| 218 case GPBDataTypeMessage: |
| 219 case GPBDataTypeString: |
| 220 if (autocreator) { |
| 221 result = [[GPBAutocreatedArray alloc] init]; |
| 222 } else { |
| 223 result = [[NSMutableArray alloc] init]; |
| 224 } |
| 225 break; |
| 226 } |
| 227 |
| 228 if (autocreator) { |
| 229 if (GPBDataTypeIsObject(fieldDataType)) { |
| 230 GPBAutocreatedArray *autoArray = result; |
| 231 autoArray->_autocreator = autocreator; |
| 232 } else { |
| 233 GPBInt32Array *gpbArray = result; |
| 234 gpbArray->_autocreator = autocreator; |
| 235 } |
| 236 } |
| 237 |
| 238 return result; |
| 239 } |
| 240 |
| 241 static id CreateMapForField(GPBFieldDescriptor *field, |
| 242 GPBMessage *autocreator) { |
| 243 id result; |
| 244 GPBDataType keyDataType = field.mapKeyDataType; |
| 245 GPBDataType valueDataType = GPBGetFieldDataType(field); |
| 246 switch (keyDataType) { |
| 247 case GPBDataTypeBool: |
| 248 switch (valueDataType) { |
| 249 case GPBDataTypeBool: |
| 250 result = [[GPBBoolBoolDictionary alloc] init]; |
| 251 break; |
| 252 case GPBDataTypeFixed32: |
| 253 case GPBDataTypeUInt32: |
| 254 result = [[GPBBoolUInt32Dictionary alloc] init]; |
| 255 break; |
| 256 case GPBDataTypeInt32: |
| 257 case GPBDataTypeSFixed32: |
| 258 case GPBDataTypeSInt32: |
| 259 result = [[GPBBoolInt32Dictionary alloc] init]; |
| 260 break; |
| 261 case GPBDataTypeFixed64: |
| 262 case GPBDataTypeUInt64: |
| 263 result = [[GPBBoolUInt64Dictionary alloc] init]; |
| 264 break; |
| 265 case GPBDataTypeInt64: |
| 266 case GPBDataTypeSFixed64: |
| 267 case GPBDataTypeSInt64: |
| 268 result = [[GPBBoolInt64Dictionary alloc] init]; |
| 269 break; |
| 270 case GPBDataTypeFloat: |
| 271 result = [[GPBBoolFloatDictionary alloc] init]; |
| 272 break; |
| 273 case GPBDataTypeDouble: |
| 274 result = [[GPBBoolDoubleDictionary alloc] init]; |
| 275 break; |
| 276 case GPBDataTypeEnum: |
| 277 result = [[GPBBoolEnumDictionary alloc] |
| 278 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 279 break; |
| 280 case GPBDataTypeBytes: |
| 281 case GPBDataTypeMessage: |
| 282 case GPBDataTypeString: |
| 283 result = [[GPBBoolObjectDictionary alloc] init]; |
| 284 break; |
| 285 case GPBDataTypeGroup: |
| 286 NSCAssert(NO, @"shouldn't happen"); |
| 287 return nil; |
| 288 } |
| 289 break; |
| 290 case GPBDataTypeFixed32: |
| 291 case GPBDataTypeUInt32: |
| 292 switch (valueDataType) { |
| 293 case GPBDataTypeBool: |
| 294 result = [[GPBUInt32BoolDictionary alloc] init]; |
| 295 break; |
| 296 case GPBDataTypeFixed32: |
| 297 case GPBDataTypeUInt32: |
| 298 result = [[GPBUInt32UInt32Dictionary alloc] init]; |
| 299 break; |
| 300 case GPBDataTypeInt32: |
| 301 case GPBDataTypeSFixed32: |
| 302 case GPBDataTypeSInt32: |
| 303 result = [[GPBUInt32Int32Dictionary alloc] init]; |
| 304 break; |
| 305 case GPBDataTypeFixed64: |
| 306 case GPBDataTypeUInt64: |
| 307 result = [[GPBUInt32UInt64Dictionary alloc] init]; |
| 308 break; |
| 309 case GPBDataTypeInt64: |
| 310 case GPBDataTypeSFixed64: |
| 311 case GPBDataTypeSInt64: |
| 312 result = [[GPBUInt32Int64Dictionary alloc] init]; |
| 313 break; |
| 314 case GPBDataTypeFloat: |
| 315 result = [[GPBUInt32FloatDictionary alloc] init]; |
| 316 break; |
| 317 case GPBDataTypeDouble: |
| 318 result = [[GPBUInt32DoubleDictionary alloc] init]; |
| 319 break; |
| 320 case GPBDataTypeEnum: |
| 321 result = [[GPBUInt32EnumDictionary alloc] |
| 322 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 323 break; |
| 324 case GPBDataTypeBytes: |
| 325 case GPBDataTypeMessage: |
| 326 case GPBDataTypeString: |
| 327 result = [[GPBUInt32ObjectDictionary alloc] init]; |
| 328 break; |
| 329 case GPBDataTypeGroup: |
| 330 NSCAssert(NO, @"shouldn't happen"); |
| 331 return nil; |
| 332 } |
| 333 break; |
| 334 case GPBDataTypeInt32: |
| 335 case GPBDataTypeSFixed32: |
| 336 case GPBDataTypeSInt32: |
| 337 switch (valueDataType) { |
| 338 case GPBDataTypeBool: |
| 339 result = [[GPBInt32BoolDictionary alloc] init]; |
| 340 break; |
| 341 case GPBDataTypeFixed32: |
| 342 case GPBDataTypeUInt32: |
| 343 result = [[GPBInt32UInt32Dictionary alloc] init]; |
| 344 break; |
| 345 case GPBDataTypeInt32: |
| 346 case GPBDataTypeSFixed32: |
| 347 case GPBDataTypeSInt32: |
| 348 result = [[GPBInt32Int32Dictionary alloc] init]; |
| 349 break; |
| 350 case GPBDataTypeFixed64: |
| 351 case GPBDataTypeUInt64: |
| 352 result = [[GPBInt32UInt64Dictionary alloc] init]; |
| 353 break; |
| 354 case GPBDataTypeInt64: |
| 355 case GPBDataTypeSFixed64: |
| 356 case GPBDataTypeSInt64: |
| 357 result = [[GPBInt32Int64Dictionary alloc] init]; |
| 358 break; |
| 359 case GPBDataTypeFloat: |
| 360 result = [[GPBInt32FloatDictionary alloc] init]; |
| 361 break; |
| 362 case GPBDataTypeDouble: |
| 363 result = [[GPBInt32DoubleDictionary alloc] init]; |
| 364 break; |
| 365 case GPBDataTypeEnum: |
| 366 result = [[GPBInt32EnumDictionary alloc] |
| 367 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 368 break; |
| 369 case GPBDataTypeBytes: |
| 370 case GPBDataTypeMessage: |
| 371 case GPBDataTypeString: |
| 372 result = [[GPBInt32ObjectDictionary alloc] init]; |
| 373 break; |
| 374 case GPBDataTypeGroup: |
| 375 NSCAssert(NO, @"shouldn't happen"); |
| 376 return nil; |
| 377 } |
| 378 break; |
| 379 case GPBDataTypeFixed64: |
| 380 case GPBDataTypeUInt64: |
| 381 switch (valueDataType) { |
| 382 case GPBDataTypeBool: |
| 383 result = [[GPBUInt64BoolDictionary alloc] init]; |
| 384 break; |
| 385 case GPBDataTypeFixed32: |
| 386 case GPBDataTypeUInt32: |
| 387 result = [[GPBUInt64UInt32Dictionary alloc] init]; |
| 388 break; |
| 389 case GPBDataTypeInt32: |
| 390 case GPBDataTypeSFixed32: |
| 391 case GPBDataTypeSInt32: |
| 392 result = [[GPBUInt64Int32Dictionary alloc] init]; |
| 393 break; |
| 394 case GPBDataTypeFixed64: |
| 395 case GPBDataTypeUInt64: |
| 396 result = [[GPBUInt64UInt64Dictionary alloc] init]; |
| 397 break; |
| 398 case GPBDataTypeInt64: |
| 399 case GPBDataTypeSFixed64: |
| 400 case GPBDataTypeSInt64: |
| 401 result = [[GPBUInt64Int64Dictionary alloc] init]; |
| 402 break; |
| 403 case GPBDataTypeFloat: |
| 404 result = [[GPBUInt64FloatDictionary alloc] init]; |
| 405 break; |
| 406 case GPBDataTypeDouble: |
| 407 result = [[GPBUInt64DoubleDictionary alloc] init]; |
| 408 break; |
| 409 case GPBDataTypeEnum: |
| 410 result = [[GPBUInt64EnumDictionary alloc] |
| 411 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 412 break; |
| 413 case GPBDataTypeBytes: |
| 414 case GPBDataTypeMessage: |
| 415 case GPBDataTypeString: |
| 416 result = [[GPBUInt64ObjectDictionary alloc] init]; |
| 417 break; |
| 418 case GPBDataTypeGroup: |
| 419 NSCAssert(NO, @"shouldn't happen"); |
| 420 return nil; |
| 421 } |
| 422 break; |
| 423 case GPBDataTypeInt64: |
| 424 case GPBDataTypeSFixed64: |
| 425 case GPBDataTypeSInt64: |
| 426 switch (valueDataType) { |
| 427 case GPBDataTypeBool: |
| 428 result = [[GPBInt64BoolDictionary alloc] init]; |
| 429 break; |
| 430 case GPBDataTypeFixed32: |
| 431 case GPBDataTypeUInt32: |
| 432 result = [[GPBInt64UInt32Dictionary alloc] init]; |
| 433 break; |
| 434 case GPBDataTypeInt32: |
| 435 case GPBDataTypeSFixed32: |
| 436 case GPBDataTypeSInt32: |
| 437 result = [[GPBInt64Int32Dictionary alloc] init]; |
| 438 break; |
| 439 case GPBDataTypeFixed64: |
| 440 case GPBDataTypeUInt64: |
| 441 result = [[GPBInt64UInt64Dictionary alloc] init]; |
| 442 break; |
| 443 case GPBDataTypeInt64: |
| 444 case GPBDataTypeSFixed64: |
| 445 case GPBDataTypeSInt64: |
| 446 result = [[GPBInt64Int64Dictionary alloc] init]; |
| 447 break; |
| 448 case GPBDataTypeFloat: |
| 449 result = [[GPBInt64FloatDictionary alloc] init]; |
| 450 break; |
| 451 case GPBDataTypeDouble: |
| 452 result = [[GPBInt64DoubleDictionary alloc] init]; |
| 453 break; |
| 454 case GPBDataTypeEnum: |
| 455 result = [[GPBInt64EnumDictionary alloc] |
| 456 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 457 break; |
| 458 case GPBDataTypeBytes: |
| 459 case GPBDataTypeMessage: |
| 460 case GPBDataTypeString: |
| 461 result = [[GPBInt64ObjectDictionary alloc] init]; |
| 462 break; |
| 463 case GPBDataTypeGroup: |
| 464 NSCAssert(NO, @"shouldn't happen"); |
| 465 return nil; |
| 466 } |
| 467 break; |
| 468 case GPBDataTypeString: |
| 469 switch (valueDataType) { |
| 470 case GPBDataTypeBool: |
| 471 result = [[GPBStringBoolDictionary alloc] init]; |
| 472 break; |
| 473 case GPBDataTypeFixed32: |
| 474 case GPBDataTypeUInt32: |
| 475 result = [[GPBStringUInt32Dictionary alloc] init]; |
| 476 break; |
| 477 case GPBDataTypeInt32: |
| 478 case GPBDataTypeSFixed32: |
| 479 case GPBDataTypeSInt32: |
| 480 result = [[GPBStringInt32Dictionary alloc] init]; |
| 481 break; |
| 482 case GPBDataTypeFixed64: |
| 483 case GPBDataTypeUInt64: |
| 484 result = [[GPBStringUInt64Dictionary alloc] init]; |
| 485 break; |
| 486 case GPBDataTypeInt64: |
| 487 case GPBDataTypeSFixed64: |
| 488 case GPBDataTypeSInt64: |
| 489 result = [[GPBStringInt64Dictionary alloc] init]; |
| 490 break; |
| 491 case GPBDataTypeFloat: |
| 492 result = [[GPBStringFloatDictionary alloc] init]; |
| 493 break; |
| 494 case GPBDataTypeDouble: |
| 495 result = [[GPBStringDoubleDictionary alloc] init]; |
| 496 break; |
| 497 case GPBDataTypeEnum: |
| 498 result = [[GPBStringEnumDictionary alloc] |
| 499 initWithValidationFunction:field.enumDescriptor.enumVerifier]; |
| 500 break; |
| 501 case GPBDataTypeBytes: |
| 502 case GPBDataTypeMessage: |
| 503 case GPBDataTypeString: |
| 504 if (autocreator) { |
| 505 result = [[GPBAutocreatedDictionary alloc] init]; |
| 506 } else { |
| 507 result = [[NSMutableDictionary alloc] init]; |
| 508 } |
| 509 break; |
| 510 case GPBDataTypeGroup: |
| 511 NSCAssert(NO, @"shouldn't happen"); |
| 512 return nil; |
| 513 } |
| 514 break; |
| 515 |
| 516 case GPBDataTypeFloat: |
| 517 case GPBDataTypeDouble: |
| 518 case GPBDataTypeEnum: |
| 519 case GPBDataTypeBytes: |
| 520 case GPBDataTypeGroup: |
| 521 case GPBDataTypeMessage: |
| 522 NSCAssert(NO, @"shouldn't happen"); |
| 523 return nil; |
| 524 } |
| 525 |
| 526 if (autocreator) { |
| 527 if ((keyDataType == GPBDataTypeString) && |
| 528 GPBDataTypeIsObject(valueDataType)) { |
| 529 GPBAutocreatedDictionary *autoDict = result; |
| 530 autoDict->_autocreator = autocreator; |
| 531 } else { |
| 532 GPBInt32Int32Dictionary *gpbDict = result; |
| 533 gpbDict->_autocreator = autocreator; |
| 534 } |
| 535 } |
| 536 |
| 537 return result; |
| 538 } |
| 539 |
| 540 #if !defined(__clang_analyzer__) |
| 541 // These functions are blocked from the analyzer because the analyzer sees the |
| 542 // GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map, |
| 543 // so use of the array/map after the call returns is flagged as a use after |
| 544 // free. |
| 545 // But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain |
| 546 // count be holding onto the object (it is transfering it), the object is |
| 547 // still valid after returning from the call. The other way to avoid this |
| 548 // would be to add a -retain/-autorelease, but that would force every |
| 549 // repeated/map field parsed into the autorelease pool which is both a memory |
| 550 // and performance hit. |
| 551 |
| 552 static id GetOrCreateArrayIvarWithField(GPBMessage *self, |
| 553 GPBFieldDescriptor *field, |
| 554 GPBFileSyntax syntax) { |
| 555 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 556 if (!array) { |
| 557 // No lock needed, this is called from places expecting to mutate |
| 558 // so no threading protection is needed. |
| 559 array = CreateArrayForField(field, nil); |
| 560 GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax); |
| 561 } |
| 562 return array; |
| 563 } |
| 564 |
| 565 // This is like GPBGetObjectIvarWithField(), but for arrays, it should |
| 566 // only be used to wire the method into the class. |
| 567 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { |
| 568 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 569 if (!array) { |
| 570 // Check again after getting the lock. |
| 571 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
| 572 array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 573 if (!array) { |
| 574 array = CreateArrayForField(field, self); |
| 575 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); |
| 576 } |
| 577 dispatch_semaphore_signal(self->readOnlySemaphore_); |
| 578 } |
| 579 return array; |
| 580 } |
| 581 |
| 582 static id GetOrCreateMapIvarWithField(GPBMessage *self, |
| 583 GPBFieldDescriptor *field, |
| 584 GPBFileSyntax syntax) { |
| 585 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 586 if (!dict) { |
| 587 // No lock needed, this is called from places expecting to mutate |
| 588 // so no threading protection is needed. |
| 589 dict = CreateMapForField(field, nil); |
| 590 GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); |
| 591 } |
| 592 return dict; |
| 593 } |
| 594 |
| 595 // This is like GPBGetObjectIvarWithField(), but for maps, it should |
| 596 // only be used to wire the method into the class. |
| 597 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { |
| 598 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 599 if (!dict) { |
| 600 // Check again after getting the lock. |
| 601 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
| 602 dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 603 if (!dict) { |
| 604 dict = CreateMapForField(field, self); |
| 605 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); |
| 606 } |
| 607 dispatch_semaphore_signal(self->readOnlySemaphore_); |
| 608 } |
| 609 return dict; |
| 610 } |
| 611 |
| 612 #endif // !defined(__clang_analyzer__) |
| 613 |
| 614 GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, |
| 615 GPBMessage *autocreator, |
| 616 GPBFieldDescriptor *field) { |
| 617 GPBMessage *message = [[msgClass alloc] init]; |
| 618 message->autocreator_ = autocreator; |
| 619 message->autocreatorField_ = [field retain]; |
| 620 return message; |
| 621 } |
| 622 |
| 623 static GPBMessage *CreateMessageWithAutocreatorForExtension( |
| 624 Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) |
| 625 __attribute__((ns_returns_retained)); |
| 626 |
| 627 static GPBMessage *CreateMessageWithAutocreatorForExtension( |
| 628 Class msgClass, GPBMessage *autocreator, |
| 629 GPBExtensionDescriptor *extension) { |
| 630 GPBMessage *message = [[msgClass alloc] init]; |
| 631 message->autocreator_ = autocreator; |
| 632 message->autocreatorExtension_ = [extension retain]; |
| 633 return message; |
| 634 } |
| 635 |
| 636 BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) { |
| 637 return (message->autocreator_ == parent); |
| 638 } |
| 639 |
| 640 void GPBBecomeVisibleToAutocreator(GPBMessage *self) { |
| 641 // Message objects that are implicitly created by accessing a message field |
| 642 // are initially not visible via the hasX selector. This method makes them |
| 643 // visible. |
| 644 if (self->autocreator_) { |
| 645 // This will recursively make all parent messages visible until it reaches a |
| 646 // super-creator that's visible. |
| 647 if (self->autocreatorField_) { |
| 648 GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax; |
| 649 GPBSetObjectIvarWithFieldInternal(self->autocreator_, |
| 650 self->autocreatorField_, self, syntax); |
| 651 } else { |
| 652 [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; |
| 653 } |
| 654 } |
| 655 } |
| 656 |
| 657 void GPBAutocreatedArrayModified(GPBMessage *self, id array) { |
| 658 // When one of our autocreated arrays adds elements, make it visible. |
| 659 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 660 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 661 if (field.fieldType == GPBFieldTypeRepeated) { |
| 662 id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 663 if (curArray == array) { |
| 664 if (GPBFieldDataTypeIsObject(field)) { |
| 665 GPBAutocreatedArray *autoArray = array; |
| 666 autoArray->_autocreator = nil; |
| 667 } else { |
| 668 GPBInt32Array *gpbArray = array; |
| 669 gpbArray->_autocreator = nil; |
| 670 } |
| 671 GPBBecomeVisibleToAutocreator(self); |
| 672 return; |
| 673 } |
| 674 } |
| 675 } |
| 676 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); |
| 677 } |
| 678 |
| 679 void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { |
| 680 // When one of our autocreated dicts adds elements, make it visible. |
| 681 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 682 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 683 if (field.fieldType == GPBFieldTypeMap) { |
| 684 id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 685 if (curDict == dictionary) { |
| 686 if ((field.mapKeyDataType == GPBDataTypeString) && |
| 687 GPBFieldDataTypeIsObject(field)) { |
| 688 GPBAutocreatedDictionary *autoDict = dictionary; |
| 689 autoDict->_autocreator = nil; |
| 690 } else { |
| 691 GPBInt32Int32Dictionary *gpbDict = dictionary; |
| 692 gpbDict->_autocreator = nil; |
| 693 } |
| 694 GPBBecomeVisibleToAutocreator(self); |
| 695 return; |
| 696 } |
| 697 } |
| 698 } |
| 699 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); |
| 700 } |
| 701 |
| 702 void GPBClearMessageAutocreator(GPBMessage *self) { |
| 703 if ((self == nil) || !self->autocreator_) { |
| 704 return; |
| 705 } |
| 706 |
| 707 #if DEBUG && !defined(NS_BLOCK_ASSERTIONS) |
| 708 // Either the autocreator must have its "has" flag set to YES, or it must be |
| 709 // NO and not equal to ourselves. |
| 710 BOOL autocreatorHas = |
| 711 (self->autocreatorField_ |
| 712 ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_) |
| 713 : [self->autocreator_ hasExtension:self->autocreatorExtension_]); |
| 714 GPBMessage *autocreatorFieldValue = |
| 715 (self->autocreatorField_ |
| 716 ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, |
| 717 self->autocreatorField_) |
| 718 : [self->autocreator_->autocreatedExtensionMap_ |
| 719 objectForKey:self->autocreatorExtension_]); |
| 720 NSCAssert(autocreatorHas || autocreatorFieldValue != self, |
| 721 @"Cannot clear autocreator because it still refers to self, self: %@
.", |
| 722 self); |
| 723 |
| 724 #endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) |
| 725 |
| 726 self->autocreator_ = nil; |
| 727 [self->autocreatorField_ release]; |
| 728 self->autocreatorField_ = nil; |
| 729 [self->autocreatorExtension_ release]; |
| 730 self->autocreatorExtension_ = nil; |
| 731 } |
| 732 |
| 733 static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { |
| 734 if (!self->unknownFields_) { |
| 735 self->unknownFields_ = [[GPBUnknownFieldSet alloc] init]; |
| 736 GPBBecomeVisibleToAutocreator(self); |
| 737 } |
| 738 return self->unknownFields_; |
| 739 } |
| 740 |
| 741 @implementation GPBMessage |
| 742 |
| 743 + (void)initialize { |
| 744 Class pbMessageClass = [GPBMessage class]; |
| 745 if ([self class] == pbMessageClass) { |
| 746 // This is here to start up the "base" class descriptor. |
| 747 [self descriptor]; |
| 748 // Message shares extension method resolving with GPBRootObject so insure |
| 749 // it is started up at the same time. |
| 750 (void)[GPBRootObject class]; |
| 751 } else if ([self superclass] == pbMessageClass) { |
| 752 // This is here to start up all the "message" subclasses. Just needs to be |
| 753 // done for the messages, not any of the subclasses. |
| 754 // This must be done in initialize to enforce thread safety of start up of |
| 755 // the protocol buffer library. |
| 756 // Note: The generated code for -descriptor calls |
| 757 // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject |
| 758 // subclass for the file. That call chain is what ensures that *Root class |
| 759 // is started up to support extension resolution off the message class |
| 760 // (+resolveClassMethod: below) in a thread safe manner. |
| 761 [self descriptor]; |
| 762 } |
| 763 } |
| 764 |
| 765 + (instancetype)allocWithZone:(NSZone *)zone { |
| 766 // Override alloc to allocate our classes with the additional storage |
| 767 // required for the instance variables. |
| 768 GPBDescriptor *descriptor = [self descriptor]; |
| 769 return NSAllocateObject(self, descriptor->storageSize_, zone); |
| 770 } |
| 771 |
| 772 + (instancetype)alloc { |
| 773 return [self allocWithZone:nil]; |
| 774 } |
| 775 |
| 776 + (GPBDescriptor *)descriptor { |
| 777 // This is thread safe because it is called from +initialize. |
| 778 static GPBDescriptor *descriptor = NULL; |
| 779 static GPBFileDescriptor *fileDescriptor = NULL; |
| 780 if (!descriptor) { |
| 781 // Use a dummy file that marks it as proto2 syntax so when used generically |
| 782 // it supports unknowns/etc. |
| 783 fileDescriptor = |
| 784 [[GPBFileDescriptor alloc] initWithPackage:@"internal" |
| 785 syntax:GPBFileSyntaxProto2]; |
| 786 |
| 787 descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] |
| 788 rootClass:Nil |
| 789 file:fileDescriptor |
| 790 fields:NULL |
| 791 fieldCount:0 |
| 792 oneofs:NULL |
| 793 oneofCount:0 |
| 794 enums:NULL |
| 795 enumCount:0 |
| 796 ranges:NULL |
| 797 rangeCount:0 |
| 798 storageSize:0 |
| 799 wireFormat:NO]; |
| 800 } |
| 801 return descriptor; |
| 802 } |
| 803 |
| 804 + (instancetype)message { |
| 805 return [[[self alloc] init] autorelease]; |
| 806 } |
| 807 |
| 808 - (instancetype)init { |
| 809 if ((self = [super init])) { |
| 810 messageStorage_ = (GPBMessage_StoragePtr)( |
| 811 ((uint8_t *)self) + class_getInstanceSize([self class])); |
| 812 |
| 813 readOnlySemaphore_ = dispatch_semaphore_create(1); |
| 814 } |
| 815 |
| 816 return self; |
| 817 } |
| 818 |
| 819 - (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { |
| 820 return [self initWithData:data extensionRegistry:nil error:errorPtr]; |
| 821 } |
| 822 |
| 823 - (instancetype)initWithData:(NSData *)data |
| 824 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry |
| 825 error:(NSError **)errorPtr { |
| 826 if ((self = [self init])) { |
| 827 @try { |
| 828 [self mergeFromData:data extensionRegistry:extensionRegistry]; |
| 829 if (errorPtr) { |
| 830 *errorPtr = nil; |
| 831 } |
| 832 } |
| 833 @catch (NSException *exception) { |
| 834 [self release]; |
| 835 self = nil; |
| 836 if (errorPtr) { |
| 837 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, |
| 838 exception.reason); |
| 839 } |
| 840 } |
| 841 #ifdef DEBUG |
| 842 if (self && !self.initialized) { |
| 843 [self release]; |
| 844 self = nil; |
| 845 if (errorPtr) { |
| 846 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); |
| 847 } |
| 848 } |
| 849 #endif |
| 850 } |
| 851 return self; |
| 852 } |
| 853 |
| 854 - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input |
| 855 extensionRegistry: |
| 856 (GPBExtensionRegistry *)extensionRegistry |
| 857 error:(NSError **)errorPtr { |
| 858 if ((self = [self init])) { |
| 859 @try { |
| 860 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]
; |
| 861 if (errorPtr) { |
| 862 *errorPtr = nil; |
| 863 } |
| 864 } |
| 865 @catch (NSException *exception) { |
| 866 [self release]; |
| 867 self = nil; |
| 868 if (errorPtr) { |
| 869 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, |
| 870 exception.reason); |
| 871 } |
| 872 } |
| 873 #ifdef DEBUG |
| 874 if (self && !self.initialized) { |
| 875 [self release]; |
| 876 self = nil; |
| 877 if (errorPtr) { |
| 878 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); |
| 879 } |
| 880 } |
| 881 #endif |
| 882 } |
| 883 return self; |
| 884 } |
| 885 |
| 886 - (void)dealloc { |
| 887 [self internalClear:NO]; |
| 888 NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); |
| 889 [super dealloc]; |
| 890 } |
| 891 |
| 892 - (void)copyFieldsInto:(GPBMessage *)message |
| 893 zone:(NSZone *)zone |
| 894 descriptor:(GPBDescriptor *)descriptor { |
| 895 // Copy all the storage... |
| 896 memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); |
| 897 |
| 898 GPBFileSyntax syntax = descriptor.file.syntax; |
| 899 |
| 900 // Loop over the fields doing fixup... |
| 901 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 902 if (GPBFieldIsMapOrArray(field)) { |
| 903 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 904 if (value) { |
| 905 // We need to copy the array/map, but the catch is for message fields, |
| 906 // we also need to ensure all the messages as those need copying also. |
| 907 id newValue; |
| 908 if (GPBFieldDataTypeIsMessage(field)) { |
| 909 if (field.fieldType == GPBFieldTypeRepeated) { |
| 910 NSArray *existingArray = (NSArray *)value; |
| 911 NSMutableArray *newArray = |
| 912 [[NSMutableArray alloc] initWithCapacity:existingArray.count]; |
| 913 newValue = newArray; |
| 914 for (GPBMessage *msg in existingArray) { |
| 915 GPBMessage *copiedMsg = [msg copyWithZone:zone]; |
| 916 [newArray addObject:copiedMsg]; |
| 917 [copiedMsg release]; |
| 918 } |
| 919 } else { |
| 920 if (field.mapKeyDataType == GPBDataTypeString) { |
| 921 // Map is an NSDictionary. |
| 922 NSDictionary *existingDict = value; |
| 923 NSMutableDictionary *newDict = [[NSMutableDictionary alloc] |
| 924 initWithCapacity:existingDict.count]; |
| 925 newValue = newDict; |
| 926 [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, |
| 927 GPBMessage *msg, |
| 928 BOOL *stop) { |
| 929 #pragma unused(stop) |
| 930 GPBMessage *copiedMsg = [msg copyWithZone:zone]; |
| 931 [newDict setObject:copiedMsg forKey:key]; |
| 932 [copiedMsg release]; |
| 933 }]; |
| 934 } else { |
| 935 // Is one of the GPB*ObjectDictionary classes. Type doesn't |
| 936 // matter, just need one to invoke the selector. |
| 937 GPBInt32ObjectDictionary *existingDict = value; |
| 938 newValue = [existingDict deepCopyWithZone:zone]; |
| 939 } |
| 940 } |
| 941 } else { |
| 942 // Not messages (but is a map/array)... |
| 943 if (field.fieldType == GPBFieldTypeRepeated) { |
| 944 if (GPBFieldDataTypeIsObject(field)) { |
| 945 // NSArray |
| 946 newValue = [value mutableCopyWithZone:zone]; |
| 947 } else { |
| 948 // GPB*Array |
| 949 newValue = [value copyWithZone:zone]; |
| 950 } |
| 951 } else { |
| 952 if (field.mapKeyDataType == GPBDataTypeString) { |
| 953 // NSDictionary |
| 954 newValue = [value mutableCopyWithZone:zone]; |
| 955 } else { |
| 956 // Is one of the GPB*Dictionary classes. Type doesn't matter, |
| 957 // just need one to invoke the selector. |
| 958 GPBInt32Int32Dictionary *existingDict = value; |
| 959 newValue = [existingDict copyWithZone:zone]; |
| 960 } |
| 961 } |
| 962 } |
| 963 // We retain here because the memcpy picked up the pointer value and |
| 964 // the next call to SetRetainedObject... will release the current value. |
| 965 [value retain]; |
| 966 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, |
| 967 syntax); |
| 968 } |
| 969 } else if (GPBFieldDataTypeIsMessage(field)) { |
| 970 // For object types, if we have a value, copy it. If we don't, |
| 971 // zero it to remove the pointer to something that was autocreated |
| 972 // (and the ptr just got memcpyed). |
| 973 if (GPBGetHasIvarField(self, field)) { |
| 974 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 975 GPBMessage *newValue = [value copyWithZone:zone]; |
| 976 // We retain here because the memcpy picked up the pointer value and |
| 977 // the next call to SetRetainedObject... will release the current value. |
| 978 [value retain]; |
| 979 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, |
| 980 syntax); |
| 981 } else { |
| 982 uint8_t *storage = (uint8_t *)message->messageStorage_; |
| 983 id *typePtr = (id *)&storage[field->description_->offset]; |
| 984 *typePtr = NULL; |
| 985 } |
| 986 } else if (GPBFieldDataTypeIsObject(field) && |
| 987 GPBGetHasIvarField(self, field)) { |
| 988 // A set string/data value (message picked off above), copy it. |
| 989 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 990 id newValue = [value copyWithZone:zone]; |
| 991 // We retain here because the memcpy picked up the pointer value and |
| 992 // the next call to SetRetainedObject... will release the current value. |
| 993 [value retain]; |
| 994 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, |
| 995 syntax); |
| 996 } else { |
| 997 // memcpy took care of the rest of the primitive fields if they were set. |
| 998 } |
| 999 } // for (field in descriptor->fields_) |
| 1000 } |
| 1001 |
| 1002 - (id)copyWithZone:(NSZone *)zone { |
| 1003 GPBDescriptor *descriptor = [self descriptor]; |
| 1004 GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; |
| 1005 |
| 1006 [self copyFieldsInto:result zone:zone descriptor:descriptor]; |
| 1007 // Make immutable copies of the extra bits. |
| 1008 result->unknownFields_ = [unknownFields_ copyWithZone:zone]; |
| 1009 result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); |
| 1010 return result; |
| 1011 } |
| 1012 |
| 1013 - (void)clear { |
| 1014 [self internalClear:YES]; |
| 1015 } |
| 1016 |
| 1017 - (void)internalClear:(BOOL)zeroStorage { |
| 1018 GPBDescriptor *descriptor = [self descriptor]; |
| 1019 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 1020 if (GPBFieldIsMapOrArray(field)) { |
| 1021 id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1022 if (arrayOrMap) { |
| 1023 if (field.fieldType == GPBFieldTypeRepeated) { |
| 1024 if (GPBFieldDataTypeIsObject(field)) { |
| 1025 GPBAutocreatedArray *autoArray = arrayOrMap; |
| 1026 if (autoArray->_autocreator == self) { |
| 1027 autoArray->_autocreator = nil; |
| 1028 } |
| 1029 } else { |
| 1030 // Type doesn't matter, it is a GPB*Array. |
| 1031 GPBInt32Array *gpbArray = arrayOrMap; |
| 1032 if (gpbArray->_autocreator == self) { |
| 1033 gpbArray->_autocreator = nil; |
| 1034 } |
| 1035 } |
| 1036 } else { |
| 1037 if ((field.mapKeyDataType == GPBDataTypeString) && |
| 1038 GPBFieldDataTypeIsObject(field)) { |
| 1039 GPBAutocreatedDictionary *autoDict = arrayOrMap; |
| 1040 if (autoDict->_autocreator == self) { |
| 1041 autoDict->_autocreator = nil; |
| 1042 } |
| 1043 } else { |
| 1044 // Type doesn't matter, it is a GPB*Dictionary. |
| 1045 GPBInt32Int32Dictionary *gpbDict = arrayOrMap; |
| 1046 if (gpbDict->_autocreator == self) { |
| 1047 gpbDict->_autocreator = nil; |
| 1048 } |
| 1049 } |
| 1050 } |
| 1051 [arrayOrMap release]; |
| 1052 } |
| 1053 } else if (GPBFieldDataTypeIsMessage(field)) { |
| 1054 GPBClearAutocreatedMessageIvarWithField(self, field); |
| 1055 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1056 [value release]; |
| 1057 } else if (GPBFieldDataTypeIsObject(field) && |
| 1058 GPBGetHasIvarField(self, field)) { |
| 1059 id value = GPBGetObjectIvarWithField(self, field); |
| 1060 [value release]; |
| 1061 } |
| 1062 } |
| 1063 |
| 1064 // GPBClearMessageAutocreator() expects that its caller has already been |
| 1065 // removed from autocreatedExtensionMap_ so we set to nil first. |
| 1066 NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues]; |
| 1067 [autocreatedExtensionMap_ release]; |
| 1068 autocreatedExtensionMap_ = nil; |
| 1069 |
| 1070 // Since we're clearing all of our extensions, make sure that we clear the |
| 1071 // autocreator on any that we've created so they no longer refer to us. |
| 1072 for (GPBMessage *value in autocreatedValues) { |
| 1073 NSCAssert(GPBWasMessageAutocreatedBy(value, self), |
| 1074 @"Autocreated extension does not refer back to self."); |
| 1075 GPBClearMessageAutocreator(value); |
| 1076 } |
| 1077 |
| 1078 [extensionMap_ release]; |
| 1079 extensionMap_ = nil; |
| 1080 [unknownFields_ release]; |
| 1081 unknownFields_ = nil; |
| 1082 |
| 1083 // Note that clearing does not affect autocreator_. If we are being cleared |
| 1084 // because of a dealloc, then autocreator_ should be nil anyway. If we are |
| 1085 // being cleared because someone explicitly clears us, we don't want to |
| 1086 // sever our relationship with our autocreator. |
| 1087 |
| 1088 if (zeroStorage) { |
| 1089 memset(messageStorage_, 0, descriptor->storageSize_); |
| 1090 } |
| 1091 } |
| 1092 |
| 1093 - (BOOL)isInitialized { |
| 1094 GPBDescriptor *descriptor = [self descriptor]; |
| 1095 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 1096 if (field.isRequired) { |
| 1097 if (!GPBGetHasIvarField(self, field)) { |
| 1098 return NO; |
| 1099 } |
| 1100 } |
| 1101 if (GPBFieldDataTypeIsMessage(field)) { |
| 1102 GPBFieldType fieldType = field.fieldType; |
| 1103 if (fieldType == GPBFieldTypeSingle) { |
| 1104 if (field.isRequired) { |
| 1105 GPBMessage *message = GPBGetMessageMessageField(self, field); |
| 1106 if (!message.initialized) { |
| 1107 return NO; |
| 1108 } |
| 1109 } else { |
| 1110 NSAssert(field.isOptional, |
| 1111 @"%@: Single message field %@ not required or optional?", |
| 1112 [self class], field.name); |
| 1113 if (GPBGetHasIvarField(self, field)) { |
| 1114 GPBMessage *message = GPBGetMessageMessageField(self, field); |
| 1115 if (!message.initialized) { |
| 1116 return NO; |
| 1117 } |
| 1118 } |
| 1119 } |
| 1120 } else if (fieldType == GPBFieldTypeRepeated) { |
| 1121 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1122 for (GPBMessage *message in array) { |
| 1123 if (!message.initialized) { |
| 1124 return NO; |
| 1125 } |
| 1126 } |
| 1127 } else { // fieldType == GPBFieldTypeMap |
| 1128 if (field.mapKeyDataType == GPBDataTypeString) { |
| 1129 NSDictionary *map = |
| 1130 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1131 if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { |
| 1132 return NO; |
| 1133 } |
| 1134 } else { |
| 1135 // Real type is GPB*ObjectDictionary, exact type doesn't matter. |
| 1136 GPBInt32ObjectDictionary *map = |
| 1137 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1138 if (map && ![map isInitialized]) { |
| 1139 return NO; |
| 1140 } |
| 1141 } |
| 1142 } |
| 1143 } |
| 1144 } |
| 1145 |
| 1146 __block BOOL result = YES; |
| 1147 [extensionMap_ |
| 1148 enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, |
| 1149 id obj, |
| 1150 BOOL *stop) { |
| 1151 if (GPBExtensionIsMessage(extension)) { |
| 1152 if (extension.isRepeated) { |
| 1153 for (GPBMessage *msg in obj) { |
| 1154 if (!msg.initialized) { |
| 1155 result = NO; |
| 1156 *stop = YES; |
| 1157 break; |
| 1158 } |
| 1159 } |
| 1160 } else { |
| 1161 GPBMessage *asMsg = obj; |
| 1162 if (!asMsg.initialized) { |
| 1163 result = NO; |
| 1164 *stop = YES; |
| 1165 } |
| 1166 } |
| 1167 } |
| 1168 }]; |
| 1169 return result; |
| 1170 } |
| 1171 |
| 1172 - (GPBDescriptor *)descriptor { |
| 1173 return [[self class] descriptor]; |
| 1174 } |
| 1175 |
| 1176 - (NSData *)data { |
| 1177 #ifdef DEBUG |
| 1178 if (!self.initialized) { |
| 1179 return nil; |
| 1180 } |
| 1181 #endif |
| 1182 NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]]; |
| 1183 GPBCodedOutputStream *stream = |
| 1184 [[GPBCodedOutputStream alloc] initWithData:data]; |
| 1185 @try { |
| 1186 [self writeToCodedOutputStream:stream]; |
| 1187 } |
| 1188 @catch (NSException *exception) { |
| 1189 // This really shouldn't happen. The only way writeToCodedOutputStream: |
| 1190 // could throw is if something in the library has a bug and the |
| 1191 // serializedSize was wrong. |
| 1192 #ifdef DEBUG |
| 1193 NSLog(@"%@: Internal exception while building message data: %@", |
| 1194 [self class], exception); |
| 1195 #endif |
| 1196 data = nil; |
| 1197 } |
| 1198 [stream release]; |
| 1199 return data; |
| 1200 } |
| 1201 |
| 1202 - (NSData *)delimitedData { |
| 1203 size_t serializedSize = [self serializedSize]; |
| 1204 size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize); |
| 1205 NSMutableData *data = |
| 1206 [NSMutableData dataWithLength:(serializedSize + varintSize)]; |
| 1207 GPBCodedOutputStream *stream = |
| 1208 [[GPBCodedOutputStream alloc] initWithData:data]; |
| 1209 @try { |
| 1210 [self writeDelimitedToCodedOutputStream:stream]; |
| 1211 } |
| 1212 @catch (NSException *exception) { |
| 1213 // This really shouldn't happen. The only way writeToCodedOutputStream: |
| 1214 // could throw is if something in the library has a bug and the |
| 1215 // serializedSize was wrong. |
| 1216 #ifdef DEBUG |
| 1217 NSLog(@"%@: Internal exception while building message delimitedData: %@", |
| 1218 [self class], exception); |
| 1219 #endif |
| 1220 // If it happens, truncate. |
| 1221 data.length = 0; |
| 1222 } |
| 1223 [stream release]; |
| 1224 return data; |
| 1225 } |
| 1226 |
| 1227 - (void)writeToOutputStream:(NSOutputStream *)output { |
| 1228 GPBCodedOutputStream *stream = |
| 1229 [[GPBCodedOutputStream alloc] initWithOutputStream:output]; |
| 1230 [self writeToCodedOutputStream:stream]; |
| 1231 [stream release]; |
| 1232 } |
| 1233 |
| 1234 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { |
| 1235 GPBDescriptor *descriptor = [self descriptor]; |
| 1236 NSArray *fieldsArray = descriptor->fields_; |
| 1237 NSUInteger fieldCount = fieldsArray.count; |
| 1238 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; |
| 1239 NSUInteger extensionRangesCount = descriptor.extensionRangesCount; |
| 1240 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { |
| 1241 if (i == fieldCount) { |
| 1242 [self writeExtensionsToCodedOutputStream:output |
| 1243 range:extensionRanges[j++]]; |
| 1244 } else if (j == extensionRangesCount || |
| 1245 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { |
| 1246 [self writeField:fieldsArray[i++] toCodedOutputStream:output]; |
| 1247 } else { |
| 1248 [self writeExtensionsToCodedOutputStream:output |
| 1249 range:extensionRanges[j++]]; |
| 1250 } |
| 1251 } |
| 1252 if (descriptor.isWireFormat) { |
| 1253 [unknownFields_ writeAsMessageSetTo:output]; |
| 1254 } else { |
| 1255 [unknownFields_ writeToCodedOutputStream:output]; |
| 1256 } |
| 1257 } |
| 1258 |
| 1259 - (void)writeDelimitedToOutputStream:(NSOutputStream *)output { |
| 1260 GPBCodedOutputStream *codedOutput = |
| 1261 [[GPBCodedOutputStream alloc] initWithOutputStream:output]; |
| 1262 [self writeDelimitedToCodedOutputStream:codedOutput]; |
| 1263 [codedOutput release]; |
| 1264 } |
| 1265 |
| 1266 - (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output { |
| 1267 [output writeRawVarintSizeTAs32:[self serializedSize]]; |
| 1268 [self writeToCodedOutputStream:output]; |
| 1269 } |
| 1270 |
| 1271 - (void)writeField:(GPBFieldDescriptor *)field |
| 1272 toCodedOutputStream:(GPBCodedOutputStream *)output { |
| 1273 GPBFieldType fieldType = field.fieldType; |
| 1274 if (fieldType == GPBFieldTypeSingle) { |
| 1275 BOOL has = GPBGetHasIvarField(self, field); |
| 1276 if (!has) { |
| 1277 return; |
| 1278 } |
| 1279 } |
| 1280 uint32_t fieldNumber = GPBFieldNumber(field); |
| 1281 |
| 1282 //%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) |
| 1283 //%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) |
| 1284 //%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) |
| 1285 //% case GPBDataType##TYPE: |
| 1286 //% if (fieldType == GPBFieldTypeRepeated) { |
| 1287 //% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1288 //% GPB##ARRAY_TYPE##Array *array = |
| 1289 //% GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1290 //% [output write##TYPE##Array:fieldNumber values:array tag:tag]; |
| 1291 //% } else if (fieldType == GPBFieldTypeSingle) { |
| 1292 //% [output write##TYPE:fieldNumber |
| 1293 //% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; |
| 1294 //% } else { // fieldType == GPBFieldTypeMap |
| 1295 //% // Exact type here doesn't matter. |
| 1296 //% GPBInt32##ARRAY_TYPE##Dictionary *dict = |
| 1297 //% GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1298 //% [dict writeToCodedOutputStream:output asField:field]; |
| 1299 //% } |
| 1300 //% break; |
| 1301 //% |
| 1302 //%PDDM-DEFINE FIELD_CASE2(TYPE) |
| 1303 //% case GPBDataType##TYPE: |
| 1304 //% if (fieldType == GPBFieldTypeRepeated) { |
| 1305 //% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1306 //% [output write##TYPE##Array:fieldNumber values:array]; |
| 1307 //% } else if (fieldType == GPBFieldTypeSingle) { |
| 1308 //% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check |
| 1309 //% // again. |
| 1310 //% [output write##TYPE:fieldNumber |
| 1311 //% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field
)]; |
| 1312 //% } else { // fieldType == GPBFieldTypeMap |
| 1313 //% // Exact type here doesn't matter. |
| 1314 //% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1315 //% GPBDataType mapKeyDataType = field.mapKeyDataType; |
| 1316 //% if (mapKeyDataType == GPBDataTypeString) { |
| 1317 //% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); |
| 1318 //% } else { |
| 1319 //% [dict writeToCodedOutputStream:output asField:field]; |
| 1320 //% } |
| 1321 //% } |
| 1322 //% break; |
| 1323 //% |
| 1324 |
| 1325 switch (GPBGetFieldDataType(field)) { |
| 1326 |
| 1327 //%PDDM-EXPAND FIELD_CASE(Bool, Bool) |
| 1328 // This block of code is generated, do not edit it directly. |
| 1329 |
| 1330 case GPBDataTypeBool: |
| 1331 if (fieldType == GPBFieldTypeRepeated) { |
| 1332 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1333 GPBBoolArray *array = |
| 1334 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1335 [output writeBoolArray:fieldNumber values:array tag:tag]; |
| 1336 } else if (fieldType == GPBFieldTypeSingle) { |
| 1337 [output writeBool:fieldNumber |
| 1338 value:GPBGetMessageBoolField(self, field)]; |
| 1339 } else { // fieldType == GPBFieldTypeMap |
| 1340 // Exact type here doesn't matter. |
| 1341 GPBInt32BoolDictionary *dict = |
| 1342 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1343 [dict writeToCodedOutputStream:output asField:field]; |
| 1344 } |
| 1345 break; |
| 1346 |
| 1347 //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) |
| 1348 // This block of code is generated, do not edit it directly. |
| 1349 |
| 1350 case GPBDataTypeFixed32: |
| 1351 if (fieldType == GPBFieldTypeRepeated) { |
| 1352 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1353 GPBUInt32Array *array = |
| 1354 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1355 [output writeFixed32Array:fieldNumber values:array tag:tag]; |
| 1356 } else if (fieldType == GPBFieldTypeSingle) { |
| 1357 [output writeFixed32:fieldNumber |
| 1358 value:GPBGetMessageUInt32Field(self, field)]; |
| 1359 } else { // fieldType == GPBFieldTypeMap |
| 1360 // Exact type here doesn't matter. |
| 1361 GPBInt32UInt32Dictionary *dict = |
| 1362 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1363 [dict writeToCodedOutputStream:output asField:field]; |
| 1364 } |
| 1365 break; |
| 1366 |
| 1367 //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) |
| 1368 // This block of code is generated, do not edit it directly. |
| 1369 |
| 1370 case GPBDataTypeSFixed32: |
| 1371 if (fieldType == GPBFieldTypeRepeated) { |
| 1372 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1373 GPBInt32Array *array = |
| 1374 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1375 [output writeSFixed32Array:fieldNumber values:array tag:tag]; |
| 1376 } else if (fieldType == GPBFieldTypeSingle) { |
| 1377 [output writeSFixed32:fieldNumber |
| 1378 value:GPBGetMessageInt32Field(self, field)]; |
| 1379 } else { // fieldType == GPBFieldTypeMap |
| 1380 // Exact type here doesn't matter. |
| 1381 GPBInt32Int32Dictionary *dict = |
| 1382 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1383 [dict writeToCodedOutputStream:output asField:field]; |
| 1384 } |
| 1385 break; |
| 1386 |
| 1387 //%PDDM-EXPAND FIELD_CASE(Float, Float) |
| 1388 // This block of code is generated, do not edit it directly. |
| 1389 |
| 1390 case GPBDataTypeFloat: |
| 1391 if (fieldType == GPBFieldTypeRepeated) { |
| 1392 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1393 GPBFloatArray *array = |
| 1394 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1395 [output writeFloatArray:fieldNumber values:array tag:tag]; |
| 1396 } else if (fieldType == GPBFieldTypeSingle) { |
| 1397 [output writeFloat:fieldNumber |
| 1398 value:GPBGetMessageFloatField(self, field)]; |
| 1399 } else { // fieldType == GPBFieldTypeMap |
| 1400 // Exact type here doesn't matter. |
| 1401 GPBInt32FloatDictionary *dict = |
| 1402 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1403 [dict writeToCodedOutputStream:output asField:field]; |
| 1404 } |
| 1405 break; |
| 1406 |
| 1407 //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) |
| 1408 // This block of code is generated, do not edit it directly. |
| 1409 |
| 1410 case GPBDataTypeFixed64: |
| 1411 if (fieldType == GPBFieldTypeRepeated) { |
| 1412 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1413 GPBUInt64Array *array = |
| 1414 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1415 [output writeFixed64Array:fieldNumber values:array tag:tag]; |
| 1416 } else if (fieldType == GPBFieldTypeSingle) { |
| 1417 [output writeFixed64:fieldNumber |
| 1418 value:GPBGetMessageUInt64Field(self, field)]; |
| 1419 } else { // fieldType == GPBFieldTypeMap |
| 1420 // Exact type here doesn't matter. |
| 1421 GPBInt32UInt64Dictionary *dict = |
| 1422 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1423 [dict writeToCodedOutputStream:output asField:field]; |
| 1424 } |
| 1425 break; |
| 1426 |
| 1427 //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) |
| 1428 // This block of code is generated, do not edit it directly. |
| 1429 |
| 1430 case GPBDataTypeSFixed64: |
| 1431 if (fieldType == GPBFieldTypeRepeated) { |
| 1432 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1433 GPBInt64Array *array = |
| 1434 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1435 [output writeSFixed64Array:fieldNumber values:array tag:tag]; |
| 1436 } else if (fieldType == GPBFieldTypeSingle) { |
| 1437 [output writeSFixed64:fieldNumber |
| 1438 value:GPBGetMessageInt64Field(self, field)]; |
| 1439 } else { // fieldType == GPBFieldTypeMap |
| 1440 // Exact type here doesn't matter. |
| 1441 GPBInt32Int64Dictionary *dict = |
| 1442 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1443 [dict writeToCodedOutputStream:output asField:field]; |
| 1444 } |
| 1445 break; |
| 1446 |
| 1447 //%PDDM-EXPAND FIELD_CASE(Double, Double) |
| 1448 // This block of code is generated, do not edit it directly. |
| 1449 |
| 1450 case GPBDataTypeDouble: |
| 1451 if (fieldType == GPBFieldTypeRepeated) { |
| 1452 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1453 GPBDoubleArray *array = |
| 1454 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1455 [output writeDoubleArray:fieldNumber values:array tag:tag]; |
| 1456 } else if (fieldType == GPBFieldTypeSingle) { |
| 1457 [output writeDouble:fieldNumber |
| 1458 value:GPBGetMessageDoubleField(self, field)]; |
| 1459 } else { // fieldType == GPBFieldTypeMap |
| 1460 // Exact type here doesn't matter. |
| 1461 GPBInt32DoubleDictionary *dict = |
| 1462 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1463 [dict writeToCodedOutputStream:output asField:field]; |
| 1464 } |
| 1465 break; |
| 1466 |
| 1467 //%PDDM-EXPAND FIELD_CASE(Int32, Int32) |
| 1468 // This block of code is generated, do not edit it directly. |
| 1469 |
| 1470 case GPBDataTypeInt32: |
| 1471 if (fieldType == GPBFieldTypeRepeated) { |
| 1472 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1473 GPBInt32Array *array = |
| 1474 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1475 [output writeInt32Array:fieldNumber values:array tag:tag]; |
| 1476 } else if (fieldType == GPBFieldTypeSingle) { |
| 1477 [output writeInt32:fieldNumber |
| 1478 value:GPBGetMessageInt32Field(self, field)]; |
| 1479 } else { // fieldType == GPBFieldTypeMap |
| 1480 // Exact type here doesn't matter. |
| 1481 GPBInt32Int32Dictionary *dict = |
| 1482 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1483 [dict writeToCodedOutputStream:output asField:field]; |
| 1484 } |
| 1485 break; |
| 1486 |
| 1487 //%PDDM-EXPAND FIELD_CASE(Int64, Int64) |
| 1488 // This block of code is generated, do not edit it directly. |
| 1489 |
| 1490 case GPBDataTypeInt64: |
| 1491 if (fieldType == GPBFieldTypeRepeated) { |
| 1492 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1493 GPBInt64Array *array = |
| 1494 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1495 [output writeInt64Array:fieldNumber values:array tag:tag]; |
| 1496 } else if (fieldType == GPBFieldTypeSingle) { |
| 1497 [output writeInt64:fieldNumber |
| 1498 value:GPBGetMessageInt64Field(self, field)]; |
| 1499 } else { // fieldType == GPBFieldTypeMap |
| 1500 // Exact type here doesn't matter. |
| 1501 GPBInt32Int64Dictionary *dict = |
| 1502 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1503 [dict writeToCodedOutputStream:output asField:field]; |
| 1504 } |
| 1505 break; |
| 1506 |
| 1507 //%PDDM-EXPAND FIELD_CASE(SInt32, Int32) |
| 1508 // This block of code is generated, do not edit it directly. |
| 1509 |
| 1510 case GPBDataTypeSInt32: |
| 1511 if (fieldType == GPBFieldTypeRepeated) { |
| 1512 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1513 GPBInt32Array *array = |
| 1514 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1515 [output writeSInt32Array:fieldNumber values:array tag:tag]; |
| 1516 } else if (fieldType == GPBFieldTypeSingle) { |
| 1517 [output writeSInt32:fieldNumber |
| 1518 value:GPBGetMessageInt32Field(self, field)]; |
| 1519 } else { // fieldType == GPBFieldTypeMap |
| 1520 // Exact type here doesn't matter. |
| 1521 GPBInt32Int32Dictionary *dict = |
| 1522 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1523 [dict writeToCodedOutputStream:output asField:field]; |
| 1524 } |
| 1525 break; |
| 1526 |
| 1527 //%PDDM-EXPAND FIELD_CASE(SInt64, Int64) |
| 1528 // This block of code is generated, do not edit it directly. |
| 1529 |
| 1530 case GPBDataTypeSInt64: |
| 1531 if (fieldType == GPBFieldTypeRepeated) { |
| 1532 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1533 GPBInt64Array *array = |
| 1534 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1535 [output writeSInt64Array:fieldNumber values:array tag:tag]; |
| 1536 } else if (fieldType == GPBFieldTypeSingle) { |
| 1537 [output writeSInt64:fieldNumber |
| 1538 value:GPBGetMessageInt64Field(self, field)]; |
| 1539 } else { // fieldType == GPBFieldTypeMap |
| 1540 // Exact type here doesn't matter. |
| 1541 GPBInt32Int64Dictionary *dict = |
| 1542 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1543 [dict writeToCodedOutputStream:output asField:field]; |
| 1544 } |
| 1545 break; |
| 1546 |
| 1547 //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) |
| 1548 // This block of code is generated, do not edit it directly. |
| 1549 |
| 1550 case GPBDataTypeUInt32: |
| 1551 if (fieldType == GPBFieldTypeRepeated) { |
| 1552 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1553 GPBUInt32Array *array = |
| 1554 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1555 [output writeUInt32Array:fieldNumber values:array tag:tag]; |
| 1556 } else if (fieldType == GPBFieldTypeSingle) { |
| 1557 [output writeUInt32:fieldNumber |
| 1558 value:GPBGetMessageUInt32Field(self, field)]; |
| 1559 } else { // fieldType == GPBFieldTypeMap |
| 1560 // Exact type here doesn't matter. |
| 1561 GPBInt32UInt32Dictionary *dict = |
| 1562 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1563 [dict writeToCodedOutputStream:output asField:field]; |
| 1564 } |
| 1565 break; |
| 1566 |
| 1567 //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) |
| 1568 // This block of code is generated, do not edit it directly. |
| 1569 |
| 1570 case GPBDataTypeUInt64: |
| 1571 if (fieldType == GPBFieldTypeRepeated) { |
| 1572 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1573 GPBUInt64Array *array = |
| 1574 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1575 [output writeUInt64Array:fieldNumber values:array tag:tag]; |
| 1576 } else if (fieldType == GPBFieldTypeSingle) { |
| 1577 [output writeUInt64:fieldNumber |
| 1578 value:GPBGetMessageUInt64Field(self, field)]; |
| 1579 } else { // fieldType == GPBFieldTypeMap |
| 1580 // Exact type here doesn't matter. |
| 1581 GPBInt32UInt64Dictionary *dict = |
| 1582 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1583 [dict writeToCodedOutputStream:output asField:field]; |
| 1584 } |
| 1585 break; |
| 1586 |
| 1587 //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) |
| 1588 // This block of code is generated, do not edit it directly. |
| 1589 |
| 1590 case GPBDataTypeEnum: |
| 1591 if (fieldType == GPBFieldTypeRepeated) { |
| 1592 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; |
| 1593 GPBEnumArray *array = |
| 1594 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1595 [output writeEnumArray:fieldNumber values:array tag:tag]; |
| 1596 } else if (fieldType == GPBFieldTypeSingle) { |
| 1597 [output writeEnum:fieldNumber |
| 1598 value:GPBGetMessageInt32Field(self, field)]; |
| 1599 } else { // fieldType == GPBFieldTypeMap |
| 1600 // Exact type here doesn't matter. |
| 1601 GPBInt32EnumDictionary *dict = |
| 1602 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1603 [dict writeToCodedOutputStream:output asField:field]; |
| 1604 } |
| 1605 break; |
| 1606 |
| 1607 //%PDDM-EXPAND FIELD_CASE2(Bytes) |
| 1608 // This block of code is generated, do not edit it directly. |
| 1609 |
| 1610 case GPBDataTypeBytes: |
| 1611 if (fieldType == GPBFieldTypeRepeated) { |
| 1612 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1613 [output writeBytesArray:fieldNumber values:array]; |
| 1614 } else if (fieldType == GPBFieldTypeSingle) { |
| 1615 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check |
| 1616 // again. |
| 1617 [output writeBytes:fieldNumber |
| 1618 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; |
| 1619 } else { // fieldType == GPBFieldTypeMap |
| 1620 // Exact type here doesn't matter. |
| 1621 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1622 GPBDataType mapKeyDataType = field.mapKeyDataType; |
| 1623 if (mapKeyDataType == GPBDataTypeString) { |
| 1624 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); |
| 1625 } else { |
| 1626 [dict writeToCodedOutputStream:output asField:field]; |
| 1627 } |
| 1628 } |
| 1629 break; |
| 1630 |
| 1631 //%PDDM-EXPAND FIELD_CASE2(String) |
| 1632 // This block of code is generated, do not edit it directly. |
| 1633 |
| 1634 case GPBDataTypeString: |
| 1635 if (fieldType == GPBFieldTypeRepeated) { |
| 1636 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1637 [output writeStringArray:fieldNumber values:array]; |
| 1638 } else if (fieldType == GPBFieldTypeSingle) { |
| 1639 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check |
| 1640 // again. |
| 1641 [output writeString:fieldNumber |
| 1642 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; |
| 1643 } else { // fieldType == GPBFieldTypeMap |
| 1644 // Exact type here doesn't matter. |
| 1645 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1646 GPBDataType mapKeyDataType = field.mapKeyDataType; |
| 1647 if (mapKeyDataType == GPBDataTypeString) { |
| 1648 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); |
| 1649 } else { |
| 1650 [dict writeToCodedOutputStream:output asField:field]; |
| 1651 } |
| 1652 } |
| 1653 break; |
| 1654 |
| 1655 //%PDDM-EXPAND FIELD_CASE2(Message) |
| 1656 // This block of code is generated, do not edit it directly. |
| 1657 |
| 1658 case GPBDataTypeMessage: |
| 1659 if (fieldType == GPBFieldTypeRepeated) { |
| 1660 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1661 [output writeMessageArray:fieldNumber values:array]; |
| 1662 } else if (fieldType == GPBFieldTypeSingle) { |
| 1663 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check |
| 1664 // again. |
| 1665 [output writeMessage:fieldNumber |
| 1666 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]
; |
| 1667 } else { // fieldType == GPBFieldTypeMap |
| 1668 // Exact type here doesn't matter. |
| 1669 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1670 GPBDataType mapKeyDataType = field.mapKeyDataType; |
| 1671 if (mapKeyDataType == GPBDataTypeString) { |
| 1672 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); |
| 1673 } else { |
| 1674 [dict writeToCodedOutputStream:output asField:field]; |
| 1675 } |
| 1676 } |
| 1677 break; |
| 1678 |
| 1679 //%PDDM-EXPAND FIELD_CASE2(Group) |
| 1680 // This block of code is generated, do not edit it directly. |
| 1681 |
| 1682 case GPBDataTypeGroup: |
| 1683 if (fieldType == GPBFieldTypeRepeated) { |
| 1684 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1685 [output writeGroupArray:fieldNumber values:array]; |
| 1686 } else if (fieldType == GPBFieldTypeSingle) { |
| 1687 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check |
| 1688 // again. |
| 1689 [output writeGroup:fieldNumber |
| 1690 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; |
| 1691 } else { // fieldType == GPBFieldTypeMap |
| 1692 // Exact type here doesn't matter. |
| 1693 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 1694 GPBDataType mapKeyDataType = field.mapKeyDataType; |
| 1695 if (mapKeyDataType == GPBDataTypeString) { |
| 1696 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); |
| 1697 } else { |
| 1698 [dict writeToCodedOutputStream:output asField:field]; |
| 1699 } |
| 1700 } |
| 1701 break; |
| 1702 |
| 1703 //%PDDM-EXPAND-END (18 expansions) |
| 1704 } |
| 1705 } |
| 1706 |
| 1707 #pragma mark - Extensions |
| 1708 |
| 1709 - (id)getExtension:(GPBExtensionDescriptor *)extension { |
| 1710 CheckExtension(self, extension); |
| 1711 id value = [extensionMap_ objectForKey:extension]; |
| 1712 if (value != nil) { |
| 1713 return value; |
| 1714 } |
| 1715 |
| 1716 // No default for repeated. |
| 1717 if (extension.isRepeated) { |
| 1718 return nil; |
| 1719 } |
| 1720 // Non messages get their default. |
| 1721 if (!GPBExtensionIsMessage(extension)) { |
| 1722 return extension.defaultValue; |
| 1723 } |
| 1724 |
| 1725 // Check for an autocreated value. |
| 1726 dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
| 1727 value = [autocreatedExtensionMap_ objectForKey:extension]; |
| 1728 if (!value) { |
| 1729 // Auto create the message extensions to match normal fields. |
| 1730 value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, |
| 1731 extension); |
| 1732 |
| 1733 if (autocreatedExtensionMap_ == nil) { |
| 1734 autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; |
| 1735 } |
| 1736 |
| 1737 // We can't simply call setExtension here because that would clear the new |
| 1738 // value's autocreator. |
| 1739 [autocreatedExtensionMap_ setObject:value forKey:extension]; |
| 1740 [value release]; |
| 1741 } |
| 1742 |
| 1743 dispatch_semaphore_signal(readOnlySemaphore_); |
| 1744 return value; |
| 1745 } |
| 1746 |
| 1747 - (id)getExistingExtension:(GPBExtensionDescriptor *)extension { |
| 1748 // This is an internal method so we don't need to call CheckExtension(). |
| 1749 return [extensionMap_ objectForKey:extension]; |
| 1750 } |
| 1751 |
| 1752 - (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { |
| 1753 #if DEBUG |
| 1754 CheckExtension(self, extension); |
| 1755 #endif // DEBUG |
| 1756 return nil != [extensionMap_ objectForKey:extension]; |
| 1757 } |
| 1758 |
| 1759 - (NSArray *)extensionsCurrentlySet { |
| 1760 return [extensionMap_ allKeys]; |
| 1761 } |
| 1762 |
| 1763 - (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output |
| 1764 range:(GPBExtensionRange)range { |
| 1765 NSArray *sortedExtensions = [[extensionMap_ allKeys] |
| 1766 sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; |
| 1767 uint32_t start = range.start; |
| 1768 uint32_t end = range.end; |
| 1769 for (GPBExtensionDescriptor *extension in sortedExtensions) { |
| 1770 uint32_t fieldNumber = extension.fieldNumber; |
| 1771 if (fieldNumber >= start && fieldNumber < end) { |
| 1772 id value = [extensionMap_ objectForKey:extension]; |
| 1773 GPBWriteExtensionValueToOutputStream(extension, value, output); |
| 1774 } |
| 1775 } |
| 1776 } |
| 1777 |
| 1778 - (NSArray *)sortedExtensionsInUse { |
| 1779 return [[extensionMap_ allKeys] |
| 1780 sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; |
| 1781 } |
| 1782 |
| 1783 - (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { |
| 1784 if (!value) { |
| 1785 [self clearExtension:extension]; |
| 1786 return; |
| 1787 } |
| 1788 |
| 1789 CheckExtension(self, extension); |
| 1790 |
| 1791 if (extension.repeated) { |
| 1792 [NSException raise:NSInvalidArgumentException |
| 1793 format:@"Must call addExtension() for repeated types."]; |
| 1794 } |
| 1795 |
| 1796 if (extensionMap_ == nil) { |
| 1797 extensionMap_ = [[NSMutableDictionary alloc] init]; |
| 1798 } |
| 1799 |
| 1800 // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. |
| 1801 // Without it, the compiler complains we're passing an id nullable when |
| 1802 // setObject:forKey: requires a id nonnull for the value. The check for |
| 1803 // !value at the start of the method ensures it isn't nil, but the check |
| 1804 // isn't smart enough to realize that. |
| 1805 [extensionMap_ setObject:(id)value forKey:extension]; |
| 1806 |
| 1807 GPBExtensionDescriptor *descriptor = extension; |
| 1808 |
| 1809 if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { |
| 1810 GPBMessage *autocreatedValue = |
| 1811 [[autocreatedExtensionMap_ objectForKey:extension] retain]; |
| 1812 // Must remove from the map before calling GPBClearMessageAutocreator() so |
| 1813 // that GPBClearMessageAutocreator() knows its safe to clear. |
| 1814 [autocreatedExtensionMap_ removeObjectForKey:extension]; |
| 1815 GPBClearMessageAutocreator(autocreatedValue); |
| 1816 [autocreatedValue release]; |
| 1817 } |
| 1818 |
| 1819 GPBBecomeVisibleToAutocreator(self); |
| 1820 } |
| 1821 |
| 1822 - (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { |
| 1823 CheckExtension(self, extension); |
| 1824 |
| 1825 if (!extension.repeated) { |
| 1826 [NSException raise:NSInvalidArgumentException |
| 1827 format:@"Must call setExtension() for singular types."]; |
| 1828 } |
| 1829 |
| 1830 if (extensionMap_ == nil) { |
| 1831 extensionMap_ = [[NSMutableDictionary alloc] init]; |
| 1832 } |
| 1833 NSMutableArray *list = [extensionMap_ objectForKey:extension]; |
| 1834 if (list == nil) { |
| 1835 list = [NSMutableArray array]; |
| 1836 [extensionMap_ setObject:list forKey:extension]; |
| 1837 } |
| 1838 |
| 1839 [list addObject:value]; |
| 1840 GPBBecomeVisibleToAutocreator(self); |
| 1841 } |
| 1842 |
| 1843 - (void)setExtension:(GPBExtensionDescriptor *)extension |
| 1844 index:(NSUInteger)idx |
| 1845 value:(id)value { |
| 1846 CheckExtension(self, extension); |
| 1847 |
| 1848 if (!extension.repeated) { |
| 1849 [NSException raise:NSInvalidArgumentException |
| 1850 format:@"Must call setExtension() for singular types."]; |
| 1851 } |
| 1852 |
| 1853 if (extensionMap_ == nil) { |
| 1854 extensionMap_ = [[NSMutableDictionary alloc] init]; |
| 1855 } |
| 1856 |
| 1857 NSMutableArray *list = [extensionMap_ objectForKey:extension]; |
| 1858 |
| 1859 [list replaceObjectAtIndex:idx withObject:value]; |
| 1860 GPBBecomeVisibleToAutocreator(self); |
| 1861 } |
| 1862 |
| 1863 - (void)clearExtension:(GPBExtensionDescriptor *)extension { |
| 1864 CheckExtension(self, extension); |
| 1865 |
| 1866 // Only become visible if there was actually a value to clear. |
| 1867 if ([extensionMap_ objectForKey:extension]) { |
| 1868 [extensionMap_ removeObjectForKey:extension]; |
| 1869 GPBBecomeVisibleToAutocreator(self); |
| 1870 } |
| 1871 } |
| 1872 |
| 1873 #pragma mark - mergeFrom |
| 1874 |
| 1875 - (void)mergeFromData:(NSData *)data |
| 1876 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { |
| 1877 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; |
| 1878 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; |
| 1879 [input checkLastTagWas:0]; |
| 1880 [input release]; |
| 1881 } |
| 1882 |
| 1883 #pragma mark - mergeDelimitedFrom |
| 1884 |
| 1885 - (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input |
| 1886 extensionRegistry:(GPBExtensionRegistry *)extensionRegi
stry { |
| 1887 GPBCodedInputStreamState *state = &input->state_; |
| 1888 if (GPBCodedInputStreamIsAtEnd(state)) { |
| 1889 return; |
| 1890 } |
| 1891 NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); |
| 1892 if (data == nil) { |
| 1893 return; |
| 1894 } |
| 1895 [self mergeFromData:data extensionRegistry:extensionRegistry]; |
| 1896 [data release]; |
| 1897 } |
| 1898 |
| 1899 #pragma mark - Parse From Data Support |
| 1900 |
| 1901 + (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { |
| 1902 return [self parseFromData:data extensionRegistry:nil error:errorPtr]; |
| 1903 } |
| 1904 |
| 1905 + (instancetype)parseFromData:(NSData *)data |
| 1906 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry |
| 1907 error:(NSError **)errorPtr { |
| 1908 return [[[self alloc] initWithData:data |
| 1909 extensionRegistry:extensionRegistry |
| 1910 error:errorPtr] autorelease]; |
| 1911 } |
| 1912 |
| 1913 + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input |
| 1914 extensionRegistry:(GPBExtensionRegistry *)extensionRegis
try |
| 1915 error:(NSError **)errorPtr { |
| 1916 return |
| 1917 [[[self alloc] initWithCodedInputStream:input |
| 1918 extensionRegistry:extensionRegistry |
| 1919 error:errorPtr] autorelease]; |
| 1920 } |
| 1921 |
| 1922 #pragma mark - Parse Delimited From Data Support |
| 1923 |
| 1924 + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input |
| 1925 extensionRegistry: |
| 1926 (GPBExtensionRegistry *)extensionRegistry |
| 1927 error:(NSError **)errorPtr { |
| 1928 GPBMessage *message = [[[self alloc] init] autorelease]; |
| 1929 @try { |
| 1930 [message mergeDelimitedFromCodedInputStream:input |
| 1931 extensionRegistry:extensionRegistry]; |
| 1932 if (errorPtr) { |
| 1933 *errorPtr = nil; |
| 1934 } |
| 1935 } |
| 1936 @catch (NSException *exception) { |
| 1937 [message release]; |
| 1938 message = nil; |
| 1939 if (errorPtr) { |
| 1940 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, |
| 1941 exception.reason); |
| 1942 } |
| 1943 } |
| 1944 #ifdef DEBUG |
| 1945 if (message && !message.initialized) { |
| 1946 [message release]; |
| 1947 message = nil; |
| 1948 if (errorPtr) { |
| 1949 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); |
| 1950 } |
| 1951 } |
| 1952 #endif |
| 1953 return message; |
| 1954 } |
| 1955 |
| 1956 #pragma mark - Unknown Field Support |
| 1957 |
| 1958 - (GPBUnknownFieldSet *)unknownFields { |
| 1959 return unknownFields_; |
| 1960 } |
| 1961 |
| 1962 - (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { |
| 1963 if (unknownFields != unknownFields_) { |
| 1964 [unknownFields_ release]; |
| 1965 unknownFields_ = [unknownFields copy]; |
| 1966 GPBBecomeVisibleToAutocreator(self); |
| 1967 } |
| 1968 } |
| 1969 |
| 1970 - (void)parseMessageSet:(GPBCodedInputStream *)input |
| 1971 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { |
| 1972 uint32_t typeId = 0; |
| 1973 NSData *rawBytes = nil; |
| 1974 GPBExtensionDescriptor *extension = nil; |
| 1975 GPBCodedInputStreamState *state = &input->state_; |
| 1976 while (true) { |
| 1977 uint32_t tag = GPBCodedInputStreamReadTag(state); |
| 1978 if (tag == 0) { |
| 1979 break; |
| 1980 } |
| 1981 |
| 1982 if (tag == GPBWireFormatMessageSetTypeIdTag) { |
| 1983 typeId = GPBCodedInputStreamReadUInt32(state); |
| 1984 if (typeId != 0) { |
| 1985 extension = [extensionRegistry extensionForDescriptor:[self descriptor] |
| 1986 fieldNumber:typeId]; |
| 1987 } |
| 1988 } else if (tag == GPBWireFormatMessageSetMessageTag) { |
| 1989 rawBytes = |
| 1990 [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; |
| 1991 } else { |
| 1992 if (![input skipField:tag]) { |
| 1993 break; |
| 1994 } |
| 1995 } |
| 1996 } |
| 1997 |
| 1998 [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag]; |
| 1999 |
| 2000 if (rawBytes != nil && typeId != 0) { |
| 2001 if (extension != nil) { |
| 2002 GPBCodedInputStream *newInput = |
| 2003 [[GPBCodedInputStream alloc] initWithData:rawBytes]; |
| 2004 GPBExtensionMergeFromInputStream(extension, |
| 2005 extension.packable, |
| 2006 newInput, |
| 2007 extensionRegistry, |
| 2008 self); |
| 2009 [newInput release]; |
| 2010 } else { |
| 2011 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2012 [unknownFields mergeMessageSetMessage:typeId data:rawBytes]; |
| 2013 } |
| 2014 } |
| 2015 } |
| 2016 |
| 2017 - (BOOL)parseUnknownField:(GPBCodedInputStream *)input |
| 2018 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry |
| 2019 tag:(uint32_t)tag { |
| 2020 GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); |
| 2021 int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); |
| 2022 |
| 2023 GPBDescriptor *descriptor = [self descriptor]; |
| 2024 GPBExtensionDescriptor *extension = |
| 2025 [extensionRegistry extensionForDescriptor:descriptor |
| 2026 fieldNumber:fieldNumber]; |
| 2027 if (extension == nil) { |
| 2028 if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { |
| 2029 [self parseMessageSet:input extensionRegistry:extensionRegistry]; |
| 2030 return YES; |
| 2031 } |
| 2032 } else { |
| 2033 if (extension.wireType == wireType) { |
| 2034 GPBExtensionMergeFromInputStream(extension, |
| 2035 extension.packable, |
| 2036 input, |
| 2037 extensionRegistry, |
| 2038 self); |
| 2039 return YES; |
| 2040 } |
| 2041 // Primitive, repeated types can be packed on unpacked on the wire, and are |
| 2042 // parsed either way. |
| 2043 if ([extension isRepeated] && |
| 2044 !GPBDataTypeIsObject(extension->description_->dataType) && |
| 2045 (extension.alternateWireType == wireType)) { |
| 2046 GPBExtensionMergeFromInputStream(extension, |
| 2047 !extension.packable, |
| 2048 input, |
| 2049 extensionRegistry, |
| 2050 self); |
| 2051 return YES; |
| 2052 } |
| 2053 } |
| 2054 if ([GPBUnknownFieldSet isFieldTag:tag]) { |
| 2055 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2056 return [unknownFields mergeFieldFrom:tag input:input]; |
| 2057 } else { |
| 2058 return NO; |
| 2059 } |
| 2060 } |
| 2061 |
| 2062 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { |
| 2063 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2064 [unknownFields addUnknownMapEntry:fieldNum value:data]; |
| 2065 } |
| 2066 |
| 2067 #pragma mark - MergeFromCodedInputStream Support |
| 2068 |
| 2069 static void MergeSingleFieldFromCodedInputStream( |
| 2070 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, |
| 2071 GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { |
| 2072 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2073 switch (fieldDataType) { |
| 2074 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ |
| 2075 case GPBDataType##NAME: { \ |
| 2076 TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ |
| 2077 GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ |
| 2078 break; \ |
| 2079 } |
| 2080 #define CASE_SINGLE_OBJECT(NAME) \ |
| 2081 case GPBDataType##NAME: { \ |
| 2082 id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ |
| 2083 GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ |
| 2084 break; \ |
| 2085 } |
| 2086 CASE_SINGLE_POD(Bool, BOOL, Bool) |
| 2087 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) |
| 2088 CASE_SINGLE_POD(SFixed32, int32_t, Int32) |
| 2089 CASE_SINGLE_POD(Float, float, Float) |
| 2090 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) |
| 2091 CASE_SINGLE_POD(SFixed64, int64_t, Int64) |
| 2092 CASE_SINGLE_POD(Double, double, Double) |
| 2093 CASE_SINGLE_POD(Int32, int32_t, Int32) |
| 2094 CASE_SINGLE_POD(Int64, int64_t, Int64) |
| 2095 CASE_SINGLE_POD(SInt32, int32_t, Int32) |
| 2096 CASE_SINGLE_POD(SInt64, int64_t, Int64) |
| 2097 CASE_SINGLE_POD(UInt32, uint32_t, UInt32) |
| 2098 CASE_SINGLE_POD(UInt64, uint64_t, UInt64) |
| 2099 CASE_SINGLE_OBJECT(Bytes) |
| 2100 CASE_SINGLE_OBJECT(String) |
| 2101 #undef CASE_SINGLE_POD |
| 2102 #undef CASE_SINGLE_OBJECT |
| 2103 |
| 2104 case GPBDataTypeMessage: { |
| 2105 if (GPBGetHasIvarField(self, field)) { |
| 2106 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has |
| 2107 // check again. |
| 2108 GPBMessage *message = |
| 2109 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 2110 [input readMessage:message extensionRegistry:extensionRegistry]; |
| 2111 } else { |
| 2112 GPBMessage *message = [[field.msgClass alloc] init]; |
| 2113 [input readMessage:message extensionRegistry:extensionRegistry]; |
| 2114 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); |
| 2115 } |
| 2116 break; |
| 2117 } |
| 2118 |
| 2119 case GPBDataTypeGroup: { |
| 2120 if (GPBGetHasIvarField(self, field)) { |
| 2121 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has |
| 2122 // check again. |
| 2123 GPBMessage *message = |
| 2124 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 2125 [input readGroup:GPBFieldNumber(field) |
| 2126 message:message |
| 2127 extensionRegistry:extensionRegistry]; |
| 2128 } else { |
| 2129 GPBMessage *message = [[field.msgClass alloc] init]; |
| 2130 [input readGroup:GPBFieldNumber(field) |
| 2131 message:message |
| 2132 extensionRegistry:extensionRegistry]; |
| 2133 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); |
| 2134 } |
| 2135 break; |
| 2136 } |
| 2137 |
| 2138 case GPBDataTypeEnum: { |
| 2139 int32_t val = GPBCodedInputStreamReadEnum(&input->state_); |
| 2140 if (GPBHasPreservingUnknownEnumSemantics(syntax) || |
| 2141 [field isValidEnumValue:val]) { |
| 2142 GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); |
| 2143 } else { |
| 2144 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2145 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; |
| 2146 } |
| 2147 } |
| 2148 } // switch |
| 2149 } |
| 2150 |
| 2151 static void MergeRepeatedPackedFieldFromCodedInputStream( |
| 2152 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, |
| 2153 GPBCodedInputStream *input) { |
| 2154 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2155 GPBCodedInputStreamState *state = &input->state_; |
| 2156 id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); |
| 2157 int32_t length = GPBCodedInputStreamReadInt32(state); |
| 2158 size_t limit = GPBCodedInputStreamPushLimit(state, length); |
| 2159 while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { |
| 2160 switch (fieldDataType) { |
| 2161 #define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ |
| 2162 case GPBDataType##NAME: { \ |
| 2163 TYPE val = GPBCodedInputStreamRead##NAME(state); \ |
| 2164 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ |
| 2165 break; \ |
| 2166 } |
| 2167 CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) |
| 2168 CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) |
| 2169 CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) |
| 2170 CASE_REPEATED_PACKED_POD(Float, float, Float) |
| 2171 CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) |
| 2172 CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) |
| 2173 CASE_REPEATED_PACKED_POD(Double, double, Double) |
| 2174 CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) |
| 2175 CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) |
| 2176 CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) |
| 2177 CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) |
| 2178 CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) |
| 2179 CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) |
| 2180 #undef CASE_REPEATED_PACKED_POD |
| 2181 |
| 2182 case GPBDataTypeBytes: |
| 2183 case GPBDataTypeString: |
| 2184 case GPBDataTypeMessage: |
| 2185 case GPBDataTypeGroup: |
| 2186 NSCAssert(NO, @"Non primitive types can't be packed"); |
| 2187 break; |
| 2188 |
| 2189 case GPBDataTypeEnum: { |
| 2190 int32_t val = GPBCodedInputStreamReadEnum(state); |
| 2191 if (GPBHasPreservingUnknownEnumSemantics(syntax) || |
| 2192 [field isValidEnumValue:val]) { |
| 2193 [(GPBEnumArray*)genericArray addRawValue:val]; |
| 2194 } else { |
| 2195 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2196 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; |
| 2197 } |
| 2198 break; |
| 2199 } |
| 2200 } // switch |
| 2201 } // while(BytesUntilLimit() > 0) |
| 2202 GPBCodedInputStreamPopLimit(state, limit); |
| 2203 } |
| 2204 |
| 2205 static void MergeRepeatedNotPackedFieldFromCodedInputStream( |
| 2206 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, |
| 2207 GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { |
| 2208 GPBCodedInputStreamState *state = &input->state_; |
| 2209 id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); |
| 2210 switch (GPBGetFieldDataType(field)) { |
| 2211 #define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ |
| 2212 case GPBDataType##NAME: { \ |
| 2213 TYPE val = GPBCodedInputStreamRead##NAME(state); \ |
| 2214 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ |
| 2215 break; \ |
| 2216 } |
| 2217 #define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ |
| 2218 case GPBDataType##NAME: { \ |
| 2219 id val = GPBCodedInputStreamReadRetained##NAME(state); \ |
| 2220 [(NSMutableArray*)genericArray addObject:val]; \ |
| 2221 [val release]; \ |
| 2222 break; \ |
| 2223 } |
| 2224 CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) |
| 2225 CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) |
| 2226 CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) |
| 2227 CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) |
| 2228 CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) |
| 2229 CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) |
| 2230 CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) |
| 2231 CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) |
| 2232 CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) |
| 2233 CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) |
| 2234 CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) |
| 2235 CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) |
| 2236 CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) |
| 2237 CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) |
| 2238 CASE_REPEATED_NOT_PACKED_OBJECT(String) |
| 2239 #undef CASE_REPEATED_NOT_PACKED_POD |
| 2240 #undef CASE_NOT_PACKED_OBJECT |
| 2241 case GPBDataTypeMessage: { |
| 2242 GPBMessage *message = [[field.msgClass alloc] init]; |
| 2243 [input readMessage:message extensionRegistry:extensionRegistry]; |
| 2244 [(NSMutableArray*)genericArray addObject:message]; |
| 2245 [message release]; |
| 2246 break; |
| 2247 } |
| 2248 case GPBDataTypeGroup: { |
| 2249 GPBMessage *message = [[field.msgClass alloc] init]; |
| 2250 [input readGroup:GPBFieldNumber(field) |
| 2251 message:message |
| 2252 extensionRegistry:extensionRegistry]; |
| 2253 [(NSMutableArray*)genericArray addObject:message]; |
| 2254 [message release]; |
| 2255 break; |
| 2256 } |
| 2257 case GPBDataTypeEnum: { |
| 2258 int32_t val = GPBCodedInputStreamReadEnum(state); |
| 2259 if (GPBHasPreservingUnknownEnumSemantics(syntax) || |
| 2260 [field isValidEnumValue:val]) { |
| 2261 [(GPBEnumArray*)genericArray addRawValue:val]; |
| 2262 } else { |
| 2263 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); |
| 2264 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; |
| 2265 } |
| 2266 break; |
| 2267 } |
| 2268 } // switch |
| 2269 } |
| 2270 |
| 2271 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input |
| 2272 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { |
| 2273 GPBDescriptor *descriptor = [self descriptor]; |
| 2274 GPBFileSyntax syntax = descriptor.file.syntax; |
| 2275 GPBCodedInputStreamState *state = &input->state_; |
| 2276 uint32_t tag = 0; |
| 2277 NSUInteger startingIndex = 0; |
| 2278 NSArray *fields = descriptor->fields_; |
| 2279 NSUInteger numFields = fields.count; |
| 2280 while (YES) { |
| 2281 BOOL merged = NO; |
| 2282 tag = GPBCodedInputStreamReadTag(state); |
| 2283 for (NSUInteger i = 0; i < numFields; ++i) { |
| 2284 if (startingIndex >= numFields) startingIndex = 0; |
| 2285 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; |
| 2286 if (GPBFieldTag(fieldDescriptor) == tag) { |
| 2287 GPBFieldType fieldType = fieldDescriptor.fieldType; |
| 2288 if (fieldType == GPBFieldTypeSingle) { |
| 2289 MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, |
| 2290 input, extensionRegistry); |
| 2291 // Well formed protos will only have a single field once, advance |
| 2292 // the starting index to the next field. |
| 2293 startingIndex += 1; |
| 2294 } else if (fieldType == GPBFieldTypeRepeated) { |
| 2295 if (fieldDescriptor.isPackable) { |
| 2296 MergeRepeatedPackedFieldFromCodedInputStream( |
| 2297 self, fieldDescriptor, syntax, input); |
| 2298 // Well formed protos will only have a repeated field that is |
| 2299 // packed once, advance the starting index to the next field. |
| 2300 startingIndex += 1; |
| 2301 } else { |
| 2302 MergeRepeatedNotPackedFieldFromCodedInputStream( |
| 2303 self, fieldDescriptor, syntax, input, extensionRegistry); |
| 2304 } |
| 2305 } else { // fieldType == GPBFieldTypeMap |
| 2306 // GPB*Dictionary or NSDictionary, exact type doesn't matter at this |
| 2307 // point. |
| 2308 id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); |
| 2309 [input readMapEntry:map |
| 2310 extensionRegistry:extensionRegistry |
| 2311 field:fieldDescriptor |
| 2312 parentMessage:self]; |
| 2313 } |
| 2314 merged = YES; |
| 2315 break; |
| 2316 } else { |
| 2317 startingIndex += 1; |
| 2318 } |
| 2319 } // for(i < numFields) |
| 2320 |
| 2321 if (!merged) { |
| 2322 // Primitive, repeated types can be packed on unpacked on the wire, and |
| 2323 // are parsed either way. The above loop covered tag in the preferred |
| 2324 // for, so this need to check the alternate form. |
| 2325 for (NSUInteger i = 0; i < numFields; ++i) { |
| 2326 if (startingIndex >= numFields) startingIndex = 0; |
| 2327 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; |
| 2328 if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && |
| 2329 !GPBFieldDataTypeIsObject(fieldDescriptor) && |
| 2330 (GPBFieldAlternateTag(fieldDescriptor) == tag)) { |
| 2331 BOOL alternateIsPacked = !fieldDescriptor.isPackable; |
| 2332 if (alternateIsPacked) { |
| 2333 MergeRepeatedPackedFieldFromCodedInputStream( |
| 2334 self, fieldDescriptor, syntax, input); |
| 2335 // Well formed protos will only have a repeated field that is |
| 2336 // packed once, advance the starting index to the next field. |
| 2337 startingIndex += 1; |
| 2338 } else { |
| 2339 MergeRepeatedNotPackedFieldFromCodedInputStream( |
| 2340 self, fieldDescriptor, syntax, input, extensionRegistry); |
| 2341 } |
| 2342 merged = YES; |
| 2343 break; |
| 2344 } else { |
| 2345 startingIndex += 1; |
| 2346 } |
| 2347 } |
| 2348 } |
| 2349 |
| 2350 if (!merged) { |
| 2351 if (tag == 0) { |
| 2352 // zero signals EOF / limit reached |
| 2353 return; |
| 2354 } else { |
| 2355 if (GPBPreserveUnknownFields(syntax)) { |
| 2356 if (![self parseUnknownField:input |
| 2357 extensionRegistry:extensionRegistry |
| 2358 tag:tag]) { |
| 2359 // it's an endgroup tag |
| 2360 return; |
| 2361 } |
| 2362 } else { |
| 2363 if (![input skipField:tag]) { |
| 2364 return; |
| 2365 } |
| 2366 } |
| 2367 } |
| 2368 } // if(!merged) |
| 2369 |
| 2370 } // while(YES) |
| 2371 } |
| 2372 |
| 2373 #pragma mark - MergeFrom Support |
| 2374 |
| 2375 - (void)mergeFrom:(GPBMessage *)other { |
| 2376 Class selfClass = [self class]; |
| 2377 Class otherClass = [other class]; |
| 2378 if (!([selfClass isSubclassOfClass:otherClass] || |
| 2379 [otherClass isSubclassOfClass:selfClass])) { |
| 2380 [NSException raise:NSInvalidArgumentException |
| 2381 format:@"Classes must match %@ != %@", selfClass, otherClass]; |
| 2382 } |
| 2383 |
| 2384 // We assume something will be done and become visible. |
| 2385 GPBBecomeVisibleToAutocreator(self); |
| 2386 |
| 2387 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 2388 GPBFileSyntax syntax = descriptor.file.syntax; |
| 2389 |
| 2390 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 2391 GPBFieldType fieldType = field.fieldType; |
| 2392 if (fieldType == GPBFieldTypeSingle) { |
| 2393 int32_t hasIndex = GPBFieldHasIndex(field); |
| 2394 uint32_t fieldNumber = GPBFieldNumber(field); |
| 2395 if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { |
| 2396 // Other doesn't have the field set, on to the next. |
| 2397 continue; |
| 2398 } |
| 2399 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2400 switch (fieldDataType) { |
| 2401 case GPBDataTypeBool: |
| 2402 GPBSetBoolIvarWithFieldInternal( |
| 2403 self, field, GPBGetMessageBoolField(other, field), syntax); |
| 2404 break; |
| 2405 case GPBDataTypeSFixed32: |
| 2406 case GPBDataTypeEnum: |
| 2407 case GPBDataTypeInt32: |
| 2408 case GPBDataTypeSInt32: |
| 2409 GPBSetInt32IvarWithFieldInternal( |
| 2410 self, field, GPBGetMessageInt32Field(other, field), syntax); |
| 2411 break; |
| 2412 case GPBDataTypeFixed32: |
| 2413 case GPBDataTypeUInt32: |
| 2414 GPBSetUInt32IvarWithFieldInternal( |
| 2415 self, field, GPBGetMessageUInt32Field(other, field), syntax); |
| 2416 break; |
| 2417 case GPBDataTypeSFixed64: |
| 2418 case GPBDataTypeInt64: |
| 2419 case GPBDataTypeSInt64: |
| 2420 GPBSetInt64IvarWithFieldInternal( |
| 2421 self, field, GPBGetMessageInt64Field(other, field), syntax); |
| 2422 break; |
| 2423 case GPBDataTypeFixed64: |
| 2424 case GPBDataTypeUInt64: |
| 2425 GPBSetUInt64IvarWithFieldInternal( |
| 2426 self, field, GPBGetMessageUInt64Field(other, field), syntax); |
| 2427 break; |
| 2428 case GPBDataTypeFloat: |
| 2429 GPBSetFloatIvarWithFieldInternal( |
| 2430 self, field, GPBGetMessageFloatField(other, field), syntax); |
| 2431 break; |
| 2432 case GPBDataTypeDouble: |
| 2433 GPBSetDoubleIvarWithFieldInternal( |
| 2434 self, field, GPBGetMessageDoubleField(other, field), syntax); |
| 2435 break; |
| 2436 case GPBDataTypeBytes: |
| 2437 case GPBDataTypeString: { |
| 2438 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); |
| 2439 GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); |
| 2440 break; |
| 2441 } |
| 2442 case GPBDataTypeMessage: |
| 2443 case GPBDataTypeGroup: { |
| 2444 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); |
| 2445 if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { |
| 2446 GPBMessage *message = |
| 2447 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 2448 [message mergeFrom:otherVal]; |
| 2449 } else { |
| 2450 GPBMessage *message = [otherVal copy]; |
| 2451 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, |
| 2452 syntax); |
| 2453 } |
| 2454 break; |
| 2455 } |
| 2456 } // switch() |
| 2457 } else if (fieldType == GPBFieldTypeRepeated) { |
| 2458 // In the case of a list, they need to be appended, and there is no |
| 2459 // _hasIvar to worry about setting. |
| 2460 id otherArray = |
| 2461 GPBGetObjectIvarWithFieldNoAutocreate(other, field); |
| 2462 if (otherArray) { |
| 2463 GPBDataType fieldDataType = field->description_->dataType; |
| 2464 if (GPBDataTypeIsObject(fieldDataType)) { |
| 2465 NSMutableArray *resultArray = |
| 2466 GetOrCreateArrayIvarWithField(self, field, syntax); |
| 2467 [resultArray addObjectsFromArray:otherArray]; |
| 2468 } else if (fieldDataType == GPBDataTypeEnum) { |
| 2469 GPBEnumArray *resultArray = |
| 2470 GetOrCreateArrayIvarWithField(self, field, syntax); |
| 2471 [resultArray addRawValuesFromArray:otherArray]; |
| 2472 } else { |
| 2473 // The array type doesn't matter, that all implment |
| 2474 // -addValuesFromArray:. |
| 2475 GPBInt32Array *resultArray = |
| 2476 GetOrCreateArrayIvarWithField(self, field, syntax); |
| 2477 [resultArray addValuesFromArray:otherArray]; |
| 2478 } |
| 2479 } |
| 2480 } else { // fieldType = GPBFieldTypeMap |
| 2481 // In the case of a map, they need to be merged, and there is no |
| 2482 // _hasIvar to worry about setting. |
| 2483 id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); |
| 2484 if (otherDict) { |
| 2485 GPBDataType keyDataType = field.mapKeyDataType; |
| 2486 GPBDataType valueDataType = field->description_->dataType; |
| 2487 if (GPBDataTypeIsObject(keyDataType) && |
| 2488 GPBDataTypeIsObject(valueDataType)) { |
| 2489 NSMutableDictionary *resultDict = |
| 2490 GetOrCreateMapIvarWithField(self, field, syntax); |
| 2491 [resultDict addEntriesFromDictionary:otherDict]; |
| 2492 } else if (valueDataType == GPBDataTypeEnum) { |
| 2493 // The exact type doesn't matter, just need to know it is a |
| 2494 // GPB*EnumDictionary. |
| 2495 GPBInt32EnumDictionary *resultDict = |
| 2496 GetOrCreateMapIvarWithField(self, field, syntax); |
| 2497 [resultDict addRawEntriesFromDictionary:otherDict]; |
| 2498 } else { |
| 2499 // The exact type doesn't matter, they all implement |
| 2500 // -addEntriesFromDictionary:. |
| 2501 GPBInt32Int32Dictionary *resultDict = |
| 2502 GetOrCreateMapIvarWithField(self, field, syntax); |
| 2503 [resultDict addEntriesFromDictionary:otherDict]; |
| 2504 } |
| 2505 } |
| 2506 } // if (fieldType)..else if...else |
| 2507 } // for(fields) |
| 2508 |
| 2509 // Unknown fields. |
| 2510 if (!unknownFields_) { |
| 2511 [self setUnknownFields:other.unknownFields]; |
| 2512 } else { |
| 2513 [unknownFields_ mergeUnknownFields:other.unknownFields]; |
| 2514 } |
| 2515 |
| 2516 // Extensions |
| 2517 |
| 2518 if (other->extensionMap_.count == 0) { |
| 2519 return; |
| 2520 } |
| 2521 |
| 2522 if (extensionMap_ == nil) { |
| 2523 extensionMap_ = |
| 2524 CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); |
| 2525 } else { |
| 2526 for (GPBExtensionDescriptor *extension in other->extensionMap_) { |
| 2527 id otherValue = [other->extensionMap_ objectForKey:extension]; |
| 2528 id value = [extensionMap_ objectForKey:extension]; |
| 2529 BOOL isMessageExtension = GPBExtensionIsMessage(extension); |
| 2530 |
| 2531 if (extension.repeated) { |
| 2532 NSMutableArray *list = value; |
| 2533 if (list == nil) { |
| 2534 list = [[NSMutableArray alloc] init]; |
| 2535 [extensionMap_ setObject:list forKey:extension]; |
| 2536 [list release]; |
| 2537 } |
| 2538 if (isMessageExtension) { |
| 2539 for (GPBMessage *otherListValue in otherValue) { |
| 2540 GPBMessage *copiedValue = [otherListValue copy]; |
| 2541 [list addObject:copiedValue]; |
| 2542 [copiedValue release]; |
| 2543 } |
| 2544 } else { |
| 2545 [list addObjectsFromArray:otherValue]; |
| 2546 } |
| 2547 } else { |
| 2548 if (isMessageExtension) { |
| 2549 if (value) { |
| 2550 [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; |
| 2551 } else { |
| 2552 GPBMessage *copiedValue = [otherValue copy]; |
| 2553 [extensionMap_ setObject:copiedValue forKey:extension]; |
| 2554 [copiedValue release]; |
| 2555 } |
| 2556 } else { |
| 2557 [extensionMap_ setObject:otherValue forKey:extension]; |
| 2558 } |
| 2559 } |
| 2560 |
| 2561 if (isMessageExtension && !extension.isRepeated) { |
| 2562 GPBMessage *autocreatedValue = |
| 2563 [[autocreatedExtensionMap_ objectForKey:extension] retain]; |
| 2564 // Must remove from the map before calling GPBClearMessageAutocreator() |
| 2565 // so that GPBClearMessageAutocreator() knows its safe to clear. |
| 2566 [autocreatedExtensionMap_ removeObjectForKey:extension]; |
| 2567 GPBClearMessageAutocreator(autocreatedValue); |
| 2568 [autocreatedValue release]; |
| 2569 } |
| 2570 } |
| 2571 } |
| 2572 } |
| 2573 |
| 2574 #pragma mark - isEqual: & hash Support |
| 2575 |
| 2576 - (BOOL)isEqual:(GPBMessage *)other { |
| 2577 if (other == self) { |
| 2578 return YES; |
| 2579 } |
| 2580 if (![other isKindOfClass:[self class]] && |
| 2581 ![self isKindOfClass:[other class]]) { |
| 2582 return NO; |
| 2583 } |
| 2584 |
| 2585 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 2586 uint8_t *selfStorage = (uint8_t *)messageStorage_; |
| 2587 uint8_t *otherStorage = (uint8_t *)other->messageStorage_; |
| 2588 |
| 2589 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 2590 if (GPBFieldIsMapOrArray(field)) { |
| 2591 // In the case of a list or map, there is no _hasIvar to worry about. |
| 2592 // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but |
| 2593 // the type doesn't really matter as the objects all support -count and |
| 2594 // -isEqual:. |
| 2595 NSArray *resultMapOrArray = |
| 2596 GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 2597 NSArray *otherMapOrArray = |
| 2598 GPBGetObjectIvarWithFieldNoAutocreate(other, field); |
| 2599 // nil and empty are equal |
| 2600 if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { |
| 2601 if (![resultMapOrArray isEqual:otherMapOrArray]) { |
| 2602 return NO; |
| 2603 } |
| 2604 } |
| 2605 } else { // Single field |
| 2606 int32_t hasIndex = GPBFieldHasIndex(field); |
| 2607 uint32_t fieldNum = GPBFieldNumber(field); |
| 2608 BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); |
| 2609 BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); |
| 2610 if (selfHas != otherHas) { |
| 2611 return NO; // Differing has values, not equal. |
| 2612 } |
| 2613 if (!selfHas) { |
| 2614 // Same has values, was no, nothing else to check for this field. |
| 2615 continue; |
| 2616 } |
| 2617 // Now compare the values. |
| 2618 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2619 size_t fieldOffset = field->description_->offset; |
| 2620 switch (fieldDataType) { |
| 2621 case GPBDataTypeBool: { |
| 2622 BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset]; |
| 2623 BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset]; |
| 2624 if (*selfValPtr != *otherValPtr) { |
| 2625 return NO; |
| 2626 } |
| 2627 break; |
| 2628 } |
| 2629 case GPBDataTypeSFixed32: |
| 2630 case GPBDataTypeInt32: |
| 2631 case GPBDataTypeSInt32: |
| 2632 case GPBDataTypeEnum: |
| 2633 case GPBDataTypeFixed32: |
| 2634 case GPBDataTypeUInt32: |
| 2635 case GPBDataTypeFloat: { |
| 2636 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits
); |
| 2637 // These are all 32bit, signed/unsigned doesn't matter for equality. |
| 2638 uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; |
| 2639 uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; |
| 2640 if (*selfValPtr != *otherValPtr) { |
| 2641 return NO; |
| 2642 } |
| 2643 break; |
| 2644 } |
| 2645 case GPBDataTypeSFixed64: |
| 2646 case GPBDataTypeInt64: |
| 2647 case GPBDataTypeSInt64: |
| 2648 case GPBDataTypeFixed64: |
| 2649 case GPBDataTypeUInt64: |
| 2650 case GPBDataTypeDouble: { |
| 2651 _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bi
ts); |
| 2652 // These are all 64bit, signed/unsigned doesn't matter for equality. |
| 2653 uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; |
| 2654 uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; |
| 2655 if (*selfValPtr != *otherValPtr) { |
| 2656 return NO; |
| 2657 } |
| 2658 break; |
| 2659 } |
| 2660 case GPBDataTypeBytes: |
| 2661 case GPBDataTypeString: |
| 2662 case GPBDataTypeMessage: |
| 2663 case GPBDataTypeGroup: { |
| 2664 // Type doesn't matter here, they all implement -isEqual:. |
| 2665 id *selfValPtr = (id *)&selfStorage[fieldOffset]; |
| 2666 id *otherValPtr = (id *)&otherStorage[fieldOffset]; |
| 2667 if (![*selfValPtr isEqual:*otherValPtr]) { |
| 2668 return NO; |
| 2669 } |
| 2670 break; |
| 2671 } |
| 2672 } // switch() |
| 2673 } // if(mapOrArray)...else |
| 2674 } // for(fields) |
| 2675 |
| 2676 // nil and empty are equal |
| 2677 if (extensionMap_.count != 0 || other->extensionMap_.count != 0) { |
| 2678 if (![extensionMap_ isEqual:other->extensionMap_]) { |
| 2679 return NO; |
| 2680 } |
| 2681 } |
| 2682 |
| 2683 // nil and empty are equal |
| 2684 GPBUnknownFieldSet *otherUnknowns = other->unknownFields_; |
| 2685 if ([unknownFields_ countOfFields] != 0 || |
| 2686 [otherUnknowns countOfFields] != 0) { |
| 2687 if (![unknownFields_ isEqual:otherUnknowns]) { |
| 2688 return NO; |
| 2689 } |
| 2690 } |
| 2691 |
| 2692 return YES; |
| 2693 } |
| 2694 |
| 2695 // It is very difficult to implement a generic hash for ProtoBuf messages that |
| 2696 // will perform well. If you need hashing on your ProtoBufs (eg you are using |
| 2697 // them as dictionary keys) you will probably want to implement a ProtoBuf |
| 2698 // message specific hash as a category on your protobuf class. Do not make it a |
| 2699 // category on GPBMessage as you will conflict with this hash, and will possibly |
| 2700 // override hash for all generated protobufs. A good implementation of hash will |
| 2701 // be really fast, so we would recommend only hashing protobufs that have an |
| 2702 // identifier field of some kind that you can easily hash. If you implement |
| 2703 // hash, we would strongly recommend overriding isEqual: in your category as |
| 2704 // well, as the default implementation of isEqual: is extremely slow, and may |
| 2705 // drastically affect performance in large sets. |
| 2706 - (NSUInteger)hash { |
| 2707 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 2708 const NSUInteger prime = 19; |
| 2709 uint8_t *storage = (uint8_t *)messageStorage_; |
| 2710 |
| 2711 // Start with the descriptor and then mix it with some instance info. |
| 2712 // Hopefully that will give a spread based on classes and what fields are set. |
| 2713 NSUInteger result = (NSUInteger)descriptor; |
| 2714 |
| 2715 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 2716 if (GPBFieldIsMapOrArray(field)) { |
| 2717 // Exact type doesn't matter, just check if there are any elements. |
| 2718 NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
| 2719 NSUInteger count = mapOrArray.count; |
| 2720 if (count) { |
| 2721 // NSArray/NSDictionary use count, use the field number and the count. |
| 2722 result = prime * result + GPBFieldNumber(field); |
| 2723 result = prime * result + count; |
| 2724 } |
| 2725 } else if (GPBGetHasIvarField(self, field)) { |
| 2726 // Just using the field number seemed simple/fast, but then a small |
| 2727 // message class where all the same fields are always set (to different |
| 2728 // things would end up all with the same hash, so pull in some data). |
| 2729 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2730 size_t fieldOffset = field->description_->offset; |
| 2731 switch (fieldDataType) { |
| 2732 case GPBDataTypeBool: { |
| 2733 BOOL *valPtr = (BOOL *)&storage[fieldOffset]; |
| 2734 result = prime * result + *valPtr; |
| 2735 break; |
| 2736 } |
| 2737 case GPBDataTypeSFixed32: |
| 2738 case GPBDataTypeInt32: |
| 2739 case GPBDataTypeSInt32: |
| 2740 case GPBDataTypeEnum: |
| 2741 case GPBDataTypeFixed32: |
| 2742 case GPBDataTypeUInt32: |
| 2743 case GPBDataTypeFloat: { |
| 2744 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits
); |
| 2745 // These are all 32bit, just mix it in. |
| 2746 uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; |
| 2747 result = prime * result + *valPtr; |
| 2748 break; |
| 2749 } |
| 2750 case GPBDataTypeSFixed64: |
| 2751 case GPBDataTypeInt64: |
| 2752 case GPBDataTypeSInt64: |
| 2753 case GPBDataTypeFixed64: |
| 2754 case GPBDataTypeUInt64: |
| 2755 case GPBDataTypeDouble: { |
| 2756 _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bi
ts); |
| 2757 // These are all 64bit, just mix what fits into an NSUInteger in. |
| 2758 uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; |
| 2759 result = prime * result + (NSUInteger)(*valPtr); |
| 2760 break; |
| 2761 } |
| 2762 case GPBDataTypeBytes: |
| 2763 case GPBDataTypeString: { |
| 2764 // Type doesn't matter here, they both implement -hash:. |
| 2765 id *valPtr = (id *)&storage[fieldOffset]; |
| 2766 result = prime * result + [*valPtr hash]; |
| 2767 break; |
| 2768 } |
| 2769 |
| 2770 case GPBDataTypeMessage: |
| 2771 case GPBDataTypeGroup: { |
| 2772 GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; |
| 2773 // Could call -hash on the sub message, but that could recurse pretty |
| 2774 // deep; follow the lead of NSArray/NSDictionary and don't really |
| 2775 // recurse for hash, instead use the field number and the descriptor |
| 2776 // of the sub message. Yes, this could suck for a bunch of messages |
| 2777 // where they all only differ in the sub messages, but if you are |
| 2778 // using a message with sub messages for something that needs -hash, |
| 2779 // odds are you are also copying them as keys, and that deep copy |
| 2780 // will also suck. |
| 2781 result = prime * result + GPBFieldNumber(field); |
| 2782 result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; |
| 2783 break; |
| 2784 } |
| 2785 } // switch() |
| 2786 } |
| 2787 } |
| 2788 |
| 2789 // Unknowns and extensions are not included. |
| 2790 |
| 2791 return result; |
| 2792 } |
| 2793 |
| 2794 #pragma mark - Description Support |
| 2795 |
| 2796 - (NSString *)description { |
| 2797 NSString *textFormat = GPBTextFormatForMessage(self, @" "); |
| 2798 NSString *description = [NSString |
| 2799 stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat]; |
| 2800 return description; |
| 2801 } |
| 2802 |
| 2803 #if DEBUG |
| 2804 |
| 2805 // Xcode 5.1 added support for custom quick look info. |
| 2806 // https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomC
lassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_
custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1 |
| 2807 - (id)debugQuickLookObject { |
| 2808 return GPBTextFormatForMessage(self, nil); |
| 2809 } |
| 2810 |
| 2811 #endif // DEBUG |
| 2812 |
| 2813 #pragma mark - SerializedSize |
| 2814 |
| 2815 - (size_t)serializedSize { |
| 2816 GPBDescriptor *descriptor = [[self class] descriptor]; |
| 2817 size_t result = 0; |
| 2818 |
| 2819 // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() |
| 2820 // avoids doing the has check again. |
| 2821 |
| 2822 // Fields. |
| 2823 for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { |
| 2824 GPBFieldType fieldType = fieldDescriptor.fieldType; |
| 2825 GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); |
| 2826 |
| 2827 // Single Fields |
| 2828 if (fieldType == GPBFieldTypeSingle) { |
| 2829 BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); |
| 2830 if (!selfHas) { |
| 2831 continue; // Nothing to do. |
| 2832 } |
| 2833 |
| 2834 uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); |
| 2835 |
| 2836 switch (fieldDataType) { |
| 2837 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ |
| 2838 case GPBDataType##NAME: { \ |
| 2839 TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor)
; \ |
| 2840 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ |
| 2841 break; \ |
| 2842 } |
| 2843 #define CASE_SINGLE_OBJECT(NAME) \ |
| 2844 case GPBDataType##NAME: { \ |
| 2845 id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescrip
tor); \ |
| 2846 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ |
| 2847 break; \ |
| 2848 } |
| 2849 CASE_SINGLE_POD(Bool, BOOL, Bool) |
| 2850 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) |
| 2851 CASE_SINGLE_POD(SFixed32, int32_t, Int32) |
| 2852 CASE_SINGLE_POD(Float, float, Float) |
| 2853 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) |
| 2854 CASE_SINGLE_POD(SFixed64, int64_t, Int64) |
| 2855 CASE_SINGLE_POD(Double, double, Double) |
| 2856 CASE_SINGLE_POD(Int32, int32_t, Int32) |
| 2857 CASE_SINGLE_POD(Int64, int64_t, Int64) |
| 2858 CASE_SINGLE_POD(SInt32, int32_t, Int32) |
| 2859 CASE_SINGLE_POD(SInt64, int64_t, Int64) |
| 2860 CASE_SINGLE_POD(UInt32, uint32_t, UInt32) |
| 2861 CASE_SINGLE_POD(UInt64, uint64_t, UInt64) |
| 2862 CASE_SINGLE_OBJECT(Bytes) |
| 2863 CASE_SINGLE_OBJECT(String) |
| 2864 CASE_SINGLE_OBJECT(Message) |
| 2865 CASE_SINGLE_OBJECT(Group) |
| 2866 CASE_SINGLE_POD(Enum, int32_t, Int32) |
| 2867 #undef CASE_SINGLE_POD |
| 2868 #undef CASE_SINGLE_OBJECT |
| 2869 } |
| 2870 |
| 2871 // Repeated Fields |
| 2872 } else if (fieldType == GPBFieldTypeRepeated) { |
| 2873 id genericArray = |
| 2874 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); |
| 2875 NSUInteger count = [genericArray count]; |
| 2876 if (count == 0) { |
| 2877 continue; // Nothing to add. |
| 2878 } |
| 2879 __block size_t dataSize = 0; |
| 2880 |
| 2881 switch (fieldDataType) { |
| 2882 #define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ |
| 2883 CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) |
| 2884 #define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ |
| 2885 case GPBDataType##NAME: { \ |
| 2886 GPB##ARRAY_TYPE##Array *array = genericArray; \ |
| 2887 [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, N
SUInteger idx, BOOL *stop) { \ |
| 2888 _Pragma("unused(idx, stop)"); \ |
| 2889 dataSize += GPBCompute##NAME##SizeNoTag(value); \ |
| 2890 }]; \ |
| 2891 break; \ |
| 2892 } |
| 2893 #define CASE_REPEATED_OBJECT(NAME) \ |
| 2894 case GPBDataType##NAME: { \ |
| 2895 for (id value in genericArray) { \ |
| 2896 dataSize += GPBCompute##NAME##SizeNoTag(value); \ |
| 2897 } \ |
| 2898 break; \ |
| 2899 } |
| 2900 CASE_REPEATED_POD(Bool, BOOL, Bool) |
| 2901 CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) |
| 2902 CASE_REPEATED_POD(SFixed32, int32_t, Int32) |
| 2903 CASE_REPEATED_POD(Float, float, Float) |
| 2904 CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) |
| 2905 CASE_REPEATED_POD(SFixed64, int64_t, Int64) |
| 2906 CASE_REPEATED_POD(Double, double, Double) |
| 2907 CASE_REPEATED_POD(Int32, int32_t, Int32) |
| 2908 CASE_REPEATED_POD(Int64, int64_t, Int64) |
| 2909 CASE_REPEATED_POD(SInt32, int32_t, Int32) |
| 2910 CASE_REPEATED_POD(SInt64, int64_t, Int64) |
| 2911 CASE_REPEATED_POD(UInt32, uint32_t, UInt32) |
| 2912 CASE_REPEATED_POD(UInt64, uint64_t, UInt64) |
| 2913 CASE_REPEATED_OBJECT(Bytes) |
| 2914 CASE_REPEATED_OBJECT(String) |
| 2915 CASE_REPEATED_OBJECT(Message) |
| 2916 CASE_REPEATED_OBJECT(Group) |
| 2917 CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) |
| 2918 #undef CASE_REPEATED_POD |
| 2919 #undef CASE_REPEATED_POD_EXTRA |
| 2920 #undef CASE_REPEATED_OBJECT |
| 2921 } // switch |
| 2922 result += dataSize; |
| 2923 size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); |
| 2924 if (fieldDataType == GPBDataTypeGroup) { |
| 2925 // Groups have both a start and an end tag. |
| 2926 tagSize *= 2; |
| 2927 } |
| 2928 if (fieldDescriptor.isPackable) { |
| 2929 result += tagSize; |
| 2930 result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); |
| 2931 } else { |
| 2932 result += count * tagSize; |
| 2933 } |
| 2934 |
| 2935 // Map<> Fields |
| 2936 } else { // fieldType == GPBFieldTypeMap |
| 2937 if (GPBDataTypeIsObject(fieldDataType) && |
| 2938 (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { |
| 2939 // If key type was string, then the map is an NSDictionary. |
| 2940 NSDictionary *map = |
| 2941 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); |
| 2942 if (map) { |
| 2943 result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor)
; |
| 2944 } |
| 2945 } else { |
| 2946 // Type will be GPB*GroupDictionary, exact type doesn't matter. |
| 2947 GPBInt32Int32Dictionary *map = |
| 2948 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); |
| 2949 result += [map computeSerializedSizeAsField:fieldDescriptor]; |
| 2950 } |
| 2951 } |
| 2952 } // for(fields) |
| 2953 |
| 2954 // Add any unknown fields. |
| 2955 if (descriptor.wireFormat) { |
| 2956 result += [unknownFields_ serializedSizeAsMessageSet]; |
| 2957 } else { |
| 2958 result += [unknownFields_ serializedSize]; |
| 2959 } |
| 2960 |
| 2961 // Add any extensions. |
| 2962 for (GPBExtensionDescriptor *extension in extensionMap_) { |
| 2963 id value = [extensionMap_ objectForKey:extension]; |
| 2964 result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); |
| 2965 } |
| 2966 |
| 2967 return result; |
| 2968 } |
| 2969 |
| 2970 #pragma mark - Resolve Methods Support |
| 2971 |
| 2972 typedef struct ResolveIvarAccessorMethodResult { |
| 2973 IMP impToAdd; |
| 2974 SEL encodingSelector; |
| 2975 } ResolveIvarAccessorMethodResult; |
| 2976 |
| 2977 static void ResolveIvarGet(GPBFieldDescriptor *field, |
| 2978 ResolveIvarAccessorMethodResult *result) { |
| 2979 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 2980 switch (fieldDataType) { |
| 2981 #define CASE_GET(NAME, TYPE, TRUE_NAME) \ |
| 2982 case GPBDataType##NAME: { \ |
| 2983 result->impToAdd = imp_implementationWithBlock(^(id obj) { \ |
| 2984 return GPBGetMessage##TRUE_NAME##Field(obj, field); \ |
| 2985 }); \ |
| 2986 result->encodingSelector = @selector(get##NAME); \ |
| 2987 break; \ |
| 2988 } |
| 2989 #define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ |
| 2990 case GPBDataType##NAME: { \ |
| 2991 result->impToAdd = imp_implementationWithBlock(^(id obj) { \ |
| 2992 return GPBGetObjectIvarWithField(obj, field); \ |
| 2993 }); \ |
| 2994 result->encodingSelector = @selector(get##NAME); \ |
| 2995 break; \ |
| 2996 } |
| 2997 CASE_GET(Bool, BOOL, Bool) |
| 2998 CASE_GET(Fixed32, uint32_t, UInt32) |
| 2999 CASE_GET(SFixed32, int32_t, Int32) |
| 3000 CASE_GET(Float, float, Float) |
| 3001 CASE_GET(Fixed64, uint64_t, UInt64) |
| 3002 CASE_GET(SFixed64, int64_t, Int64) |
| 3003 CASE_GET(Double, double, Double) |
| 3004 CASE_GET(Int32, int32_t, Int32) |
| 3005 CASE_GET(Int64, int64_t, Int64) |
| 3006 CASE_GET(SInt32, int32_t, Int32) |
| 3007 CASE_GET(SInt64, int64_t, Int64) |
| 3008 CASE_GET(UInt32, uint32_t, UInt32) |
| 3009 CASE_GET(UInt64, uint64_t, UInt64) |
| 3010 CASE_GET_OBJECT(Bytes, id, Object) |
| 3011 CASE_GET_OBJECT(String, id, Object) |
| 3012 CASE_GET_OBJECT(Message, id, Object) |
| 3013 CASE_GET_OBJECT(Group, id, Object) |
| 3014 CASE_GET(Enum, int32_t, Enum) |
| 3015 #undef CASE_GET |
| 3016 } |
| 3017 } |
| 3018 |
| 3019 static void ResolveIvarSet(GPBFieldDescriptor *field, |
| 3020 GPBFileSyntax syntax, |
| 3021 ResolveIvarAccessorMethodResult *result) { |
| 3022 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
| 3023 switch (fieldDataType) { |
| 3024 #define CASE_SET(NAME, TYPE, TRUE_NAME) \ |
| 3025 case GPBDataType##NAME: { \ |
| 3026 result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ |
| 3027 return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, synta
x); \ |
| 3028 }); \ |
| 3029 result->encodingSelector = @selector(set##NAME:); \ |
| 3030 break; \ |
| 3031 } |
| 3032 CASE_SET(Bool, BOOL, Bool) |
| 3033 CASE_SET(Fixed32, uint32_t, UInt32) |
| 3034 CASE_SET(SFixed32, int32_t, Int32) |
| 3035 CASE_SET(Float, float, Float) |
| 3036 CASE_SET(Fixed64, uint64_t, UInt64) |
| 3037 CASE_SET(SFixed64, int64_t, Int64) |
| 3038 CASE_SET(Double, double, Double) |
| 3039 CASE_SET(Int32, int32_t, Int32) |
| 3040 CASE_SET(Int64, int64_t, Int64) |
| 3041 CASE_SET(SInt32, int32_t, Int32) |
| 3042 CASE_SET(SInt64, int64_t, Int64) |
| 3043 CASE_SET(UInt32, uint32_t, UInt32) |
| 3044 CASE_SET(UInt64, uint64_t, UInt64) |
| 3045 CASE_SET(Bytes, id, Object) |
| 3046 CASE_SET(String, id, Object) |
| 3047 CASE_SET(Message, id, Object) |
| 3048 CASE_SET(Group, id, Object) |
| 3049 CASE_SET(Enum, int32_t, Enum) |
| 3050 #undef CASE_SET |
| 3051 } |
| 3052 } |
| 3053 |
| 3054 + (BOOL)resolveInstanceMethod:(SEL)sel { |
| 3055 const GPBDescriptor *descriptor = [self descriptor]; |
| 3056 if (!descriptor) { |
| 3057 return NO; |
| 3058 } |
| 3059 |
| 3060 // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given |
| 3061 // message should not have has support (done in GPBDescriptor.m), so there is |
| 3062 // no need for checks here to see if has*/setHas* are allowed. |
| 3063 |
| 3064 ResolveIvarAccessorMethodResult result = {NULL, NULL}; |
| 3065 for (GPBFieldDescriptor *field in descriptor->fields_) { |
| 3066 BOOL isMapOrArray = GPBFieldIsMapOrArray(field); |
| 3067 if (!isMapOrArray) { |
| 3068 // Single fields. |
| 3069 if (sel == field->getSel_) { |
| 3070 ResolveIvarGet(field, &result); |
| 3071 break; |
| 3072 } else if (sel == field->setSel_) { |
| 3073 ResolveIvarSet(field, descriptor.file.syntax, &result); |
| 3074 break; |
| 3075 } else if (sel == field->hasOrCountSel_) { |
| 3076 int32_t index = GPBFieldHasIndex(field); |
| 3077 uint32_t fieldNum = GPBFieldNumber(field); |
| 3078 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
| 3079 return GPBGetHasIvar(obj, index, fieldNum); |
| 3080 }); |
| 3081 result.encodingSelector = @selector(getBool); |
| 3082 break; |
| 3083 } else if (sel == field->setHasSel_) { |
| 3084 result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { |
| 3085 if (value) { |
| 3086 [NSException raise:NSInvalidArgumentException |
| 3087 format:@"%@: %@ can only be set to NO (to clear field)."
, |
| 3088 [obj class], |
| 3089 NSStringFromSelector(field->setHasSel_)]; |
| 3090 } |
| 3091 GPBClearMessageField(obj, field); |
| 3092 }); |
| 3093 result.encodingSelector = @selector(setBool:); |
| 3094 break; |
| 3095 } else { |
| 3096 GPBOneofDescriptor *oneof = field->containingOneof_; |
| 3097 if (oneof && (sel == oneof->caseSel_)) { |
| 3098 int32_t index = oneof->oneofDescription_->index; |
| 3099 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
| 3100 return GPBGetHasOneof(obj, index); |
| 3101 }); |
| 3102 result.encodingSelector = @selector(getEnum); |
| 3103 break; |
| 3104 } |
| 3105 } |
| 3106 } else { |
| 3107 // map<>/repeated fields. |
| 3108 if (sel == field->getSel_) { |
| 3109 if (field.fieldType == GPBFieldTypeRepeated) { |
| 3110 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
| 3111 return GetArrayIvarWithField(obj, field); |
| 3112 }); |
| 3113 } else { |
| 3114 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
| 3115 return GetMapIvarWithField(obj, field); |
| 3116 }); |
| 3117 } |
| 3118 result.encodingSelector = @selector(getArray); |
| 3119 break; |
| 3120 } else if (sel == field->setSel_) { |
| 3121 // Local for syntax so the block can directly capture it and not the |
| 3122 // full lookup. |
| 3123 const GPBFileSyntax syntax = descriptor.file.syntax; |
| 3124 result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { |
| 3125 return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); |
| 3126 }); |
| 3127 result.encodingSelector = @selector(setArray:); |
| 3128 break; |
| 3129 } else if (sel == field->hasOrCountSel_) { |
| 3130 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
| 3131 // Type doesn't matter, all *Array and *Dictionary types support |
| 3132 // -count. |
| 3133 NSArray *arrayOrMap = |
| 3134 GPBGetObjectIvarWithFieldNoAutocreate(obj, field); |
| 3135 return [arrayOrMap count]; |
| 3136 }); |
| 3137 result.encodingSelector = @selector(getArrayCount); |
| 3138 break; |
| 3139 } |
| 3140 } |
| 3141 } |
| 3142 if (result.impToAdd) { |
| 3143 const char *encoding = |
| 3144 GPBMessageEncodingForSelector(result.encodingSelector, YES); |
| 3145 BOOL methodAdded = class_addMethod(descriptor.messageClass, sel, |
| 3146 result.impToAdd, encoding); |
| 3147 return methodAdded; |
| 3148 } |
| 3149 return [super resolveInstanceMethod:sel]; |
| 3150 } |
| 3151 |
| 3152 + (BOOL)resolveClassMethod:(SEL)sel { |
| 3153 // Extensions scoped to a Message and looked up via class methods. |
| 3154 if (GPBResolveExtensionClassMethod(self, sel)) { |
| 3155 return YES; |
| 3156 } |
| 3157 return [super resolveClassMethod:sel]; |
| 3158 } |
| 3159 |
| 3160 #pragma mark - NSCoding Support |
| 3161 |
| 3162 + (BOOL)supportsSecureCoding { |
| 3163 return YES; |
| 3164 } |
| 3165 |
| 3166 - (instancetype)initWithCoder:(NSCoder *)aDecoder { |
| 3167 self = [self init]; |
| 3168 if (self) { |
| 3169 NSData *data = |
| 3170 [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; |
| 3171 if (data.length) { |
| 3172 [self mergeFromData:data extensionRegistry:nil]; |
| 3173 } |
| 3174 } |
| 3175 return self; |
| 3176 } |
| 3177 |
| 3178 - (void)encodeWithCoder:(NSCoder *)aCoder { |
| 3179 NSData *data = [self data]; |
| 3180 if (data.length) { |
| 3181 [aCoder encodeObject:data forKey:kGPBDataCoderKey]; |
| 3182 } |
| 3183 } |
| 3184 |
| 3185 #pragma mark - KVC Support |
| 3186 |
| 3187 + (BOOL)accessInstanceVariablesDirectly { |
| 3188 // Make sure KVC doesn't use instance variables. |
| 3189 return NO; |
| 3190 } |
| 3191 |
| 3192 @end |
OLD | NEW |