1#import "CPTNumericData.h" 2#import "CPTNumericData+TypeConversion.h" 3#import "CPTMutableNumericData.h" 4#import "CPTExceptions.h" 5#import "CPTUtilities.h" 6#import "complex.h" 7 8/** @cond */ 9@interface CPTNumericData() 10 11-(void)commonInitWithData:(NSData *)newData 12 dataType:(CPTNumericDataType)newDataType 13 shape:(NSArray *)shapeArray; 14 15-(NSData *)dataFromArray:(NSArray *)newData dataType:(CPTNumericDataType)newDataType; 16 17@end 18/** @endcond */ 19 20#pragma mark - 21 22/** @brief An annotated NSData type. 23 * 24 * CPTNumericData combines a data buffer with information 25 * about the data (shape, data type, size, etc.). 26 * The data is assumed to be an array of one or more dimensions 27 * of a single type of numeric data. Each numeric value in the array, 28 * which can be more than one byte in size, is referred to as a "sample". 29 * The structure of this object is similar to the NumPy ndarray 30 * object. 31 * 32 * The supported data types are: 33 * - 1, 2, 4, and 8-byte signed integers 34 * - 1, 2, 4, and 8-byte unsigned integers 35 * - <code>float</code> and <code>double</code> floating point numbers 36 * - <code>float complex</code> and <code>double complex</code> floating point complex numbers 37 * - NSDecimal base-10 numbers 38 * 39 * All integer and floating point types can be represented using big endian or little endian 40 * byte order. Complex and decimal types support only the the host system's native byte order. 41 **/ 42@implementation CPTNumericData 43 44/** @property data 45 * @brief The data buffer. 46 **/ 47@synthesize data; 48 49/** @property bytes 50 * @brief Returns a pointer to the data buffer’s contents. 51 **/ 52@dynamic bytes; 53 54/** @property length 55 * @brief Returns the number of bytes contained in the data buffer. 56 **/ 57@dynamic length; 58 59/** @property dataType 60 * @brief The type of data stored in the data buffer. 61 **/ 62@synthesize dataType; 63 64/** @property dataTypeFormat 65 * @brief The format of the data stored in the data buffer. 66 **/ 67@dynamic dataTypeFormat; 68 69/** @property sampleBytes 70 * @brief The number of bytes in a single sample of data. 71 **/ 72@dynamic sampleBytes; 73 74/** @property byteOrder 75 * @brief The byte order used to store each sample in the data buffer. 76 **/ 77@dynamic byteOrder; 78 79/** @property shape 80 * @brief The shape of the data buffer array. 81 * 82 * The shape describes the dimensions of the sample array stored in 83 * the data buffer. Each entry in the shape array represents the 84 * size of the corresponding array dimension and should be an unsigned 85 * integer encoded in an instance of NSNumber. 86 **/ 87@synthesize shape; 88 89/** @property numberOfDimensions 90 * @brief The number dimensions in the data buffer array. 91 **/ 92@dynamic numberOfDimensions; 93 94/** @property numberOfSamples 95 * @brief The number of samples of dataType stored in the data buffer. 96 **/ 97@dynamic numberOfSamples; 98 99#pragma mark - 100#pragma mark Factory Methods 101 102/** @brief Creates and returns a new CPTNumericData instance. 103 * @param newData The data buffer. 104 * @param newDataType The type of data stored in the buffer. 105 * @param shapeArray The shape of the data buffer array. 106 * @return A new CPTNumericData instance. 107 **/ 108+(CPTNumericData *)numericDataWithData:(NSData *)newData 109 dataType:(CPTNumericDataType)newDataType 110 shape:(NSArray *)shapeArray 111{ 112 return [[[CPTNumericData alloc] initWithData:newData 113 dataType:newDataType 114 shape:shapeArray] 115 autorelease]; 116} 117 118/** @brief Creates and returns a new CPTNumericData instance. 119 * @param newData The data buffer. 120 * @param newDataTypeString The type of data stored in the buffer. 121 * @param shapeArray The shape of the data buffer array. 122 * @return A new CPTNumericData instance. 123 **/ 124+(CPTNumericData *)numericDataWithData:(NSData *)newData 125 dataTypeString:(NSString *)newDataTypeString 126 shape:(NSArray *)shapeArray 127{ 128 return [[[CPTNumericData alloc] initWithData:newData 129 dataType:CPTDataTypeWithDataTypeString(newDataTypeString) 130 shape:shapeArray] 131 autorelease]; 132} 133 134/** @brief Creates and returns a new CPTNumericData instance. 135 * 136 * Objects in newData should be instances of NSNumber, NSDecimalNumber, NSString, or NSNull. 137 * Numbers and strings will be converted to newDataType and stored in the receiver. 138 * Any instances of NSNull will be treated as "not a number" (NAN) values for floating point types and "0" for integer types. 139 * @param newData An array of numbers. 140 * @param newDataType The type of data stored in the buffer. 141 * @param shapeArray The shape of the data buffer array. 142 * @return A new CPTNumericData instance. 143 **/ 144+(CPTNumericData *)numericDataWithArray:(NSArray *)newData 145 dataType:(CPTNumericDataType)newDataType 146 shape:(NSArray *)shapeArray 147{ 148 return [[[CPTNumericData alloc] initWithArray:newData 149 dataType:newDataType 150 shape:shapeArray] 151 autorelease]; 152} 153 154/** @brief Creates and returns a new CPTNumericData instance. 155 * 156 * Objects in newData should be instances of NSNumber, NSDecimalNumber, NSString, or NSNull. 157 * Numbers and strings will be converted to newDataTypeString and stored in the receiver. 158 * Any instances of NSNull will be treated as "not a number" (NAN) values for floating point types and "0" for integer types. 159 * @param newData An array of numbers. 160 * @param newDataTypeString The type of data stored in the buffer. 161 * @param shapeArray The shape of the data buffer array. 162 * @return A new CPTNumericData instance. 163 **/ 164+(CPTNumericData *)numericDataWithArray:(NSArray *)newData 165 dataTypeString:(NSString *)newDataTypeString 166 shape:(NSArray *)shapeArray 167{ 168 return [[[CPTNumericData alloc] initWithArray:newData 169 dataType:CPTDataTypeWithDataTypeString(newDataTypeString) 170 shape:shapeArray] 171 autorelease]; 172} 173 174#pragma mark - 175#pragma mark Init/Dealloc 176 177/** @brief Initializes a newly allocated CPTNumericData object with the provided data. This is the designated initializer. 178 * @param newData The data buffer. 179 * @param newDataType The type of data stored in the buffer. 180 * @param shapeArray The shape of the data buffer array. 181 * @return The initialized CPTNumericData instance. 182 **/ 183-(id)initWithData:(NSData *)newData 184 dataType:(CPTNumericDataType)newDataType 185 shape:(NSArray *)shapeArray 186{ 187 if ( (self = [super init]) ) { 188 [self commonInitWithData:newData 189 dataType:newDataType 190 shape:shapeArray]; 191 } 192 193 return self; 194} 195 196/** @brief Initializes a newly allocated CPTNumericData object with the provided data. 197 * @param newData The data buffer. 198 * @param newDataTypeString The type of data stored in the buffer. 199 * @param shapeArray The shape of the data buffer array. 200 * @return The initialized CPTNumericData instance. 201 **/ 202-(id)initWithData:(NSData *)newData 203 dataTypeString:(NSString *)newDataTypeString 204 shape:(NSArray *)shapeArray 205{ 206 return [self initWithData:newData 207 dataType:CPTDataTypeWithDataTypeString(newDataTypeString) 208 shape:shapeArray]; 209} 210 211/** @brief Initializes a newly allocated CPTNumericData object with the provided data. 212 * 213 * Objects in newData should be instances of NSNumber, NSDecimalNumber, NSString, or NSNull. 214 * Numbers and strings will be converted to newDataType and stored in the receiver. 215 * Any instances of NSNull will be treated as "not a number" (NAN) values for floating point types and "0" for integer types. 216 * @param newData An array of numbers. 217 * @param newDataType The type of data stored in the buffer. 218 * @param shapeArray The shape of the data buffer array. 219 * @return The initialized CPTNumericData instance. 220 **/ 221-(id)initWithArray:(NSArray *)newData 222 dataType:(CPTNumericDataType)newDataType 223 shape:(NSArray *)shapeArray 224{ 225 return [self initWithData:[self dataFromArray:newData dataType:newDataType] 226 dataType:newDataType 227 shape:shapeArray]; 228} 229 230/** @brief Initializes a newly allocated CPTNumericData object with the provided data. 231 * 232 * Objects in newData should be instances of NSNumber, NSDecimalNumber, NSString, or NSNull. 233 * Numbers and strings will be converted to newDataTypeString and stored in the receiver. 234 * Any instances of NSNull will be treated as "not a number" (NAN) values for floating point types and "0" for integer types. 235 * @param newData An array of numbers. 236 * @param newDataTypeString The type of data stored in the buffer. 237 * @param shapeArray The shape of the data buffer array. 238 * @return The initialized CPTNumericData instance. 239 **/ 240-(id)initWithArray:(NSArray *)newData 241 dataTypeString:(NSString *)newDataTypeString 242 shape:(NSArray *)shapeArray 243{ 244 return [self initWithArray:newData 245 dataType:CPTDataTypeWithDataTypeString(newDataTypeString) 246 shape:shapeArray]; 247} 248 249-(void)commonInitWithData:(NSData *)newData 250 dataType:(CPTNumericDataType)newDataType 251 shape:(NSArray *)shapeArray 252{ 253 NSParameterAssert(CPTDataTypeIsSupported(newDataType)); 254 255 data = [newData copy]; 256 dataType = newDataType; 257 258 if ( shapeArray == nil ) { 259 shape = [[NSArray arrayWithObject:[NSNumber numberWithUnsignedInteger:self.numberOfSamples]] retain]; 260 } 261 else { 262 NSUInteger prod = 1; 263 for ( NSNumber *cNum in shapeArray ) { 264 prod *= [cNum unsignedIntegerValue]; 265 } 266 267 if ( prod != self.numberOfSamples ) { 268 [NSException raise:CPTNumericDataException 269 format:@"Shape product (%u) does not match data size (%u)", prod, self.numberOfSamples]; 270 } 271 272 shape = [shapeArray copy]; 273 } 274} 275 276-(void)dealloc 277{ 278 [data release]; 279 [shape release]; 280 281 [super dealloc]; 282} 283 284#pragma mark - 285#pragma mark Accessors 286 287-(NSUInteger)numberOfDimensions 288{ 289 return self.shape.count; 290} 291 292-(const void *)bytes 293{ 294 return self.data.bytes; 295} 296 297-(NSUInteger)length 298{ 299 return self.data.length; 300} 301 302-(NSUInteger)numberOfSamples 303{ 304 return (self.length / self.dataType.sampleBytes); 305} 306 307-(CPTDataTypeFormat)dataTypeFormat 308{ 309 return self.dataType.dataTypeFormat; 310} 311 312-(size_t)sampleBytes 313{ 314 return self.dataType.sampleBytes; 315} 316 317-(CFByteOrder)byteOrder 318{ 319 return self.dataType.byteOrder; 320} 321 322#pragma mark - 323#pragma mark Samples 324 325/** @brief Gets the value of a given sample in the data buffer. 326 * @param sample The index into the sample array. The array is treated as if it only has one dimension. 327 * @return The sample value wrapped in an instance of NSNumber or <code>nil</code> if the sample index is out of bounds. 328 * 329 * NSNumber does not support complex numbers. Complex number types will be cast to 330 * <code>float</code> or <code>double</code> before being wrapped in an instance of NSNumber. 331 **/ 332-(NSNumber *)sampleValue:(NSUInteger)sample 333{ 334 NSNumber *result = nil; 335 336 if ( sample < self.numberOfSamples ) { 337 // Code generated with "CPTNumericData+TypeConversions_Generation.py" 338 // ======================================================================== 339 340 switch ( self.dataTypeFormat ) { 341 case CPTUndefinedDataType: 342 [NSException raise:NSInvalidArgumentException format:@"Unsupported data type (CPTUndefinedDataType)"]; 343 break; 344 case CPTIntegerDataType: 345 switch ( self.sampleBytes ) { 346 case sizeof(int8_t): 347 result = [NSNumber numberWithChar:*(int8_t *)[self samplePointer:sample]]; 348 break; 349 case sizeof(int16_t): 350 result = [NSNumber numberWithShort:*(int16_t *)[self samplePointer:sample]]; 351 break; 352 case sizeof(int32_t): 353 result = [NSNumber numberWithLong:*(int32_t *)[self samplePointer:sample]]; 354 break; 355 case sizeof(int64_t): 356 result = [NSNumber numberWithLongLong:*(int64_t *)[self samplePointer:sample]]; 357 break; 358 } 359 break; 360 case CPTUnsignedIntegerDataType: 361 switch ( self.sampleBytes ) { 362 case sizeof(uint8_t): 363 result = [NSNumber numberWithUnsignedChar:*(uint8_t *)[self samplePointer:sample]]; 364 break; 365 case sizeof(uint16_t): 366 result = [NSNumber numberWithUnsignedShort:*(uint16_t *)[self samplePointer:sample]]; 367 break; 368 case sizeof(uint32_t): 369 result = [NSNumber numberWithUnsignedLong:*(uint32_t *)[self samplePointer:sample]]; 370 break; 371 case sizeof(uint64_t): 372 result = [NSNumber numberWithUnsignedLongLong:*(uint64_t *)[self samplePointer:sample]]; 373 break; 374 } 375 break; 376 case CPTFloatingPointDataType: 377 switch ( self.sampleBytes ) { 378 case sizeof(float): 379 result = [NSNumber numberWithFloat:*(float *)[self samplePointer:sample]]; 380 break; 381 case sizeof(double): 382 result = [NSNumber numberWithDouble:*(double *)[self samplePointer:sample]]; 383 break; 384 } 385 break; 386 case CPTComplexFloatingPointDataType: 387 switch ( self.sampleBytes ) { 388 case sizeof(float complex): 389 result = [NSNumber numberWithFloat:*(float complex *)[self samplePointer:sample]]; 390 break; 391 case sizeof(double complex): 392 result = [NSNumber numberWithDouble:*(double complex *)[self samplePointer:sample]]; 393 break; 394 } 395 break; 396 case CPTDecimalDataType: 397 switch ( self.sampleBytes ) { 398 case sizeof(NSDecimal): 399 result = [NSDecimalNumber decimalNumberWithDecimal:*(NSDecimal *)[self samplePointer:sample]]; 400 break; 401 } 402 break; 403 } 404 405 // End of code generated with "CPTNumericData+TypeConversions_Generation.py" 406 // ======================================================================== 407 } 408 409 return result; 410} 411 412/** @brief Gets a pointer to a given sample in the data buffer. 413 * @param sample The index into the sample array. The array is treated as if it only has one dimension. 414 * @return A pointer to the sample or <code>NULL</code> if the sample index is out of bounds. 415 **/ 416-(void *)samplePointer:(NSUInteger)sample 417{ 418 if ( sample < self.numberOfSamples ) { 419 return (void *) ((char *)self.bytes + sample * self.sampleBytes); 420 } 421 else { 422 return NULL; 423 } 424} 425 426/** @brief Gets an array data samples from the receiver. 427 * @return An NSArray of NSNumber objects representing the data from the receiver. 428 **/ 429-(NSArray *)sampleArray 430{ 431 NSUInteger sampleCount = self.numberOfSamples; 432 NSMutableArray *samples = [[NSMutableArray alloc] initWithCapacity:sampleCount]; 433 434 for ( NSUInteger i = 0; i < sampleCount; i++ ) { 435 [samples addObject:[self sampleValue:i]]; 436 } 437 438 NSArray *result = [NSArray arrayWithArray:samples]; 439 [samples release]; 440 441 return result; 442} 443 444-(NSData *)dataFromArray:(NSArray *)newData dataType:(CPTNumericDataType)newDataType 445{ 446 NSParameterAssert(CPTDataTypeIsSupported(newDataType)); 447 NSParameterAssert(newDataType.dataTypeFormat != CPTUndefinedDataType); 448 NSParameterAssert(newDataType.dataTypeFormat != CPTComplexFloatingPointDataType); 449 450 NSMutableData *sampleData = [[NSMutableData alloc] initWithLength:newData.count * newDataType.sampleBytes]; 451 452 // Code generated with "CPTNumericData+TypeConversions_Generation.py" 453 // ======================================================================== 454 455 switch ( newDataType.dataTypeFormat ) { 456 case CPTUndefinedDataType: 457 // Unsupported 458 break; 459 case CPTIntegerDataType: 460 switch ( newDataType.sampleBytes ) { 461 case sizeof(int8_t): { 462 int8_t *toBytes = (int8_t *)sampleData.mutableBytes; 463 for ( id sample in newData ) { 464 if ( [sample respondsToSelector:@selector(charValue)] ) { 465 *toBytes++ = (int8_t)[(NSNumber *)sample charValue]; 466 } 467 else { 468 *toBytes++ = 0; 469 } 470 } 471 } 472 break; 473 case sizeof(int16_t): { 474 int16_t *toBytes = (int16_t *)sampleData.mutableBytes; 475 for ( id sample in newData ) { 476 if ( [sample respondsToSelector:@selector(shortValue)] ) { 477 *toBytes++ = (int16_t)[(NSNumber *)sample shortValue]; 478 } 479 else { 480 *toBytes++ = 0; 481 } 482 } 483 } 484 break; 485 case sizeof(int32_t): { 486 int32_t *toBytes = (int32_t *)sampleData.mutableBytes; 487 for ( id sample in newData ) { 488 if ( [sample respondsToSelector:@selector(longValue)] ) { 489 *toBytes++ = (int32_t)[(NSNumber *)sample longValue]; 490 } 491 else { 492 *toBytes++ = 0; 493 } 494 } 495 } 496 break; 497 case sizeof(int64_t): { 498 int64_t *toBytes = (int64_t *)sampleData.mutableBytes; 499 for ( id sample in newData ) { 500 if ( [sample respondsToSelector:@selector(longLongValue)] ) { 501 *toBytes++ = (int64_t)[(NSNumber *)sample longLongValue]; 502 } 503 else { 504 *toBytes++ = 0; 505 } 506 } 507 } 508 break; 509 } 510 break; 511 case CPTUnsignedIntegerDataType: 512 switch ( newDataType.sampleBytes ) { 513 case sizeof(uint8_t): { 514 uint8_t *toBytes = (uint8_t *)sampleData.mutableBytes; 515 for ( id sample in newData ) { 516 if ( [sample respondsToSelector:@selector(unsignedCharValue)] ) { 517 *toBytes++ = (uint8_t)[(NSNumber *)sample unsignedCharValue]; 518 } 519 else { 520 *toBytes++ = 0; 521 } 522 } 523 } 524 break; 525 case sizeof(uint16_t): { 526 uint16_t *toBytes = (uint16_t *)sampleData.mutableBytes; 527 for ( id sample in newData ) { 528 if ( [sample respondsToSelector:@selector(unsignedShortValue)] ) { 529 *toBytes++ = (uint16_t)[(NSNumber *)sample unsignedShortValue]; 530 } 531 else { 532 *toBytes++ = 0; 533 } 534 } 535 } 536 break; 537 case sizeof(uint32_t): { 538 uint32_t *toBytes = (uint32_t *)sampleData.mutableBytes; 539 for ( id sample in newData ) { 540 if ( [sample respondsToSelector:@selector(unsignedLongValue)] ) { 541 *toBytes++ = (uint32_t)[(NSNumber *)sample unsignedLongValue]; 542 } 543 else { 544 *toBytes++ = 0; 545 } 546 } 547 } 548 break; 549 case sizeof(uint64_t): { 550 uint64_t *toBytes = (uint64_t *)sampleData.mutableBytes; 551 for ( id sample in newData ) { 552 if ( [sample respondsToSelector:@selector(unsignedLongLongValue)] ) { 553 *toBytes++ = (uint64_t)[(NSNumber *)sample unsignedLongLongValue]; 554 } 555 else { 556 *toBytes++ = 0; 557 } 558 } 559 } 560 break; 561 } 562 break; 563 case CPTFloatingPointDataType: 564 switch ( newDataType.sampleBytes ) { 565 case sizeof(float): { 566 float *toBytes = (float *)sampleData.mutableBytes; 567 for ( id sample in newData ) { 568 if ( [sample respondsToSelector:@selector(floatValue)] ) { 569 *toBytes++ = (float)[(NSNumber *)sample floatValue]; 570 } 571 else { 572 *toBytes++ = NAN; 573 } 574 } 575 } 576 break; 577 case sizeof(double): { 578 double *toBytes = (double *)sampleData.mutableBytes; 579 for ( id sample in newData ) { 580 if ( [sample respondsToSelector:@selector(doubleValue)] ) { 581 *toBytes++ = (double)[(NSNumber *)sample doubleValue]; 582 } 583 else { 584 *toBytes++ = NAN; 585 } 586 } 587 } 588 break; 589 } 590 break; 591 case CPTComplexFloatingPointDataType: 592 switch ( newDataType.sampleBytes ) { 593 case sizeof(float complex): { 594 float complex *toBytes = (float complex *)sampleData.mutableBytes; 595 for ( id sample in newData ) { 596 if ( [sample respondsToSelector:@selector(floatValue)] ) { 597 *toBytes++ = (float complex)[(NSNumber *)sample floatValue]; 598 } 599 else { 600 *toBytes++ = NAN; 601 } 602 } 603 } 604 break; 605 case sizeof(double complex): { 606 double complex *toBytes = (double complex *)sampleData.mutableBytes; 607 for ( id sample in newData ) { 608 if ( [sample respondsToSelector:@selector(doubleValue)] ) { 609 *toBytes++ = (double complex)[(NSNumber *)sample doubleValue]; 610 } 611 else { 612 *toBytes++ = NAN; 613 } 614 } 615 } 616 break; 617 } 618 break; 619 case CPTDecimalDataType: 620 switch ( newDataType.sampleBytes ) { 621 case sizeof(NSDecimal): { 622 NSDecimal *toBytes = (NSDecimal *)sampleData.mutableBytes; 623 for ( id sample in newData ) { 624 if ( [sample respondsToSelector:@selector(decimalValue)] ) { 625 *toBytes++ = (NSDecimal)[(NSNumber *)sample decimalValue]; 626 } 627 else { 628 *toBytes++ = CPTDecimalNaN(); 629 } 630 } 631 } 632 break; 633 } 634 break; 635 } 636 637 // End of code generated with "CPTNumericData+TypeConversions_Generation.py" 638 // ======================================================================== 639 640 if ( (newDataType.byteOrder != CFByteOrderGetCurrent()) && (newDataType.byteOrder != CFByteOrderUnknown) ) { 641 [self swapByteOrderForData:sampleData sampleSize:newDataType.sampleBytes]; 642 } 643 644 return [sampleData autorelease]; 645} 646 647#pragma mark - 648#pragma mark Description 649 650-(NSString *)description 651{ 652 NSUInteger sampleCount = self.numberOfSamples; 653 NSMutableString *descriptionString = [NSMutableString stringWithCapacity:sampleCount * 3]; 654 [descriptionString appendFormat:@"<%@ [", [super description]]; 655 for ( NSUInteger i = 0; i < sampleCount; i++ ) { 656 if ( i > 0 ) { 657 [descriptionString appendFormat:@","]; 658 } 659 [descriptionString appendFormat:@" %@", [self sampleValue:i]]; 660 } 661 [descriptionString appendFormat:@" ] {%@, %@}>", CPTDataTypeStringFromDataType(self.dataType), self.shape]; 662 663 return descriptionString; 664} 665 666#pragma mark - 667#pragma mark NSMutableCopying 668 669-(id)mutableCopyWithZone:(NSZone *)zone 670{ 671 return [[CPTMutableNumericData allocWithZone:zone] initWithData:self.data 672 dataType:self.dataType 673 shape:self.shape]; 674} 675 676#pragma mark - 677#pragma mark NSCopying 678 679-(id)copyWithZone:(NSZone *)zone 680{ 681 return [[[self class] allocWithZone:zone] initWithData:self.data 682 dataType:self.dataType 683 shape:self.shape]; 684} 685 686#pragma mark - 687#pragma mark NSCoding 688 689-(void)encodeWithCoder:(NSCoder *)encoder 690{ 691 //[super encodeWithCoder:encoder]; 692 693 if ( [encoder allowsKeyedCoding] ) { 694 [encoder encodeObject:self.data forKey:@"CPTNumericData.data"]; 695 696 CPTNumericDataType selfDataType = self.dataType; 697 [encoder encodeInteger:selfDataType.dataTypeFormat forKey:@"CPTNumericData.dataType.dataTypeFormat"]; 698 [encoder encodeInteger:selfDataType.sampleBytes forKey:@"CPTNumericData.dataType.sampleBytes"]; 699 [encoder encodeInteger:selfDataType.byteOrder forKey:@"CPTNumericData.dataType.byteOrder"]; 700 701 [encoder encodeObject:self.shape forKey:@"CPTNumericData.shape"]; 702 } 703 else { 704 [encoder encodeObject:self.data]; 705 706 CPTNumericDataType selfDataType = self.dataType; 707 [encoder encodeValueOfObjCType:@encode(CPTDataTypeFormat) at:&(selfDataType.dataTypeFormat)]; 708 [encoder encodeValueOfObjCType:@encode(NSUInteger) at:&(selfDataType.sampleBytes)]; 709 [encoder encodeValueOfObjCType:@encode(CFByteOrder) at:&(selfDataType.byteOrder)]; 710 711 [encoder encodeObject:self.shape]; 712 } 713} 714 715-(id)initWithCoder:(NSCoder *)decoder 716{ 717 if ( (self = [super init]) ) { 718 NSData *newData; 719 CPTNumericDataType newDataType; 720 NSArray *shapeArray; 721 722 if ( [decoder allowsKeyedCoding] ) { 723 newData = [decoder decodeObjectForKey:@"CPTNumericData.data"]; 724 725 newDataType = CPTDataType([decoder decodeIntegerForKey:@"CPTNumericData.dataType.dataTypeFormat"], 726 [decoder decodeIntegerForKey:@"CPTNumericData.dataType.sampleBytes"], 727 [decoder decodeIntegerForKey:@"CPTNumericData.dataType.byteOrder"]); 728 729 shapeArray = [decoder decodeObjectForKey:@"CPTNumericData.shape"]; 730 } 731 else { 732 newData = [decoder decodeObject]; 733 734 [decoder decodeValueOfObjCType:@encode(CPTDataTypeFormat) at:&(newDataType.dataTypeFormat)]; 735 [decoder decodeValueOfObjCType:@encode(NSUInteger) at:&(newDataType.sampleBytes)]; 736 [decoder decodeValueOfObjCType:@encode(CFByteOrder) at:&(newDataType.byteOrder)]; 737 738 shapeArray = [decoder decodeObject]; 739 } 740 741 [self commonInitWithData:newData dataType:newDataType shape:shapeArray]; 742 } 743 744 return self; 745} 746 747@end 748