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