This is MAValueData.m in view mode; [Download] [Up]
/* MAValueData - NSData that knows what type of data it stores. Copyright (C) 1995, Adam Fedor. */ #ifdef NEXT_FOUNDATION #import <foundation/NSArray.h> #import <foundation/NSString.h> #import <foundation/NSCoder.h> #else #import <Foundation/NSArray.h> #import <Foundation/NSString.h> #import <Foundation/NSCoder.h> #endif #include <string.h> #include "MathArray/MAValueData.h" #include "MathArrayPrivate.h" #include "MathArray/array_encoding.h" @implementation MAValueData /* This is a class for storing arrays of arbitrary data. It is much like NSData, only it 'knows' what type of data it stores (like NSValue), and can access it appropriately */ + allocWithZone:(NSZone *)zone { return NSAllocateObject(self, 0, zone); } /* Create a new object using the data given in values, which is assumed to be of Objective-C type and contain count values. */ + dataWithValues:(const void *)values count:(unsigned)count objCType:(const char *)type { return [[[self alloc] initWithValues:values count:count objCType:type] autorelease]; } /* Create a new object using the data given in values, which is assumed to be of Objective-C type and contain count values. The array becomes the owner of values, as in the NSData method of a similar name. */ + dataWithValuesNoCopy:(void *)values count:(unsigned)count objCType:(const char *)type { return [[[self alloc] initWithValuesNoCopy:values count:count objCType:type] autorelease]; } /* Create a new object using the data given in values, which is assumed to contain NSPoint values. */ + dataWithPoints:(const void *)pointArray count:(unsigned)count { return [[[self alloc] initWithValues:pointArray count:count objCType:@encode(NSPoint)] autorelease]; } /* Create a new object using the data given in values, which is assumed to contain NSRect values. */ + dataWithRects:(const void *)rectArray count:(unsigned)count { return [[[self alloc] initWithValues:rectArray count:count objCType:@encode(NSRect)] autorelease]; } /* Create a new object using the NSValues contained in the NSArray list. */ + dataWithValueList:(NSArray *)valueList { return [[[self alloc] initWithValueList:valueList] autorelease]; } - (unsigned)_initType:(const char *)type { unsigned size = 0; if (!type) MA_RAISE_PARAMETER; size = math_aligned_size(type); c_type = [[NSString stringWithCString:type] retain]; return size; } - _allocData { // Allocate our storage, but don't initialize (for subclassing) data = [NSData alloc]; return data; } /* The following two methods need to be overriden from NSData */ - initWithBytesNoCopy:(void *)bytes length:(unsigned)length { #ifndef GNU_FOUNDATION // Haven't resolved the designated initializer concept in libobjects yet [super init]; #endif data = [[self _allocData] initWithBytesNoCopy:bytes length:length]; return self; } - initWithBytes:(const void *)bytes length:(unsigned)length { #ifndef GNU_FOUNDATION // Haven't resolved the designated initializer concept in libobjects yet [super init]; #endif data = [[self _allocData] initWithBytes:bytes length:length]; return self; } /* Initializes a newly created MAValueData using the data given in values, which is assumed to be of Objective-C type and contain count values. */ - initWithValues:(const void *)values count:(unsigned)count objCType:(const char *)type { unsigned type_size = [self _initType:type]; return [self initWithBytes:values length:count*type_size]; } /* Initializes a newly created MAValueData using the data given in values, which is assumed to be of Objective-C type and contain count values. The array becomes the owner of values, as in the NSData method of a similar name. */ - initWithValuesNoCopy:(void *)values count:(unsigned)count objCType:(const char *)type { unsigned type_size = [self _initType:type]; return [self initWithBytesNoCopy:values length:count*type_size]; } /* Initializes a newly created MAValueData with data obtained from the NSData object vdata, which is assumed to contain values of Objective-C type type. */ - initWithData:(NSData *)vdata objCType:(const char *)type { //[super init]; [self _initType:type]; data = [[self _allocData] initWithData: vdata]; return self; } /* Same as initWithData:objcType: but simple retains the data and does not copy it (if possible) */ - initWithDataNoCopy:(NSData *)vdata objCType:(const char *)type { //[super init]; [self _initType:type]; if ([[self _allocData] respondsToSelector:@selector(mutableBytes)] && ![vdata respondsToSelector:@selector(mutableBytes)]) data = [vdata mutableCopy]; else data = [vdata retain]; return self; } /* Initializes the receiver with values from the valueArray list which must contain values of the same objCType */ - initWithValueList:(NSArray *)valueList { int i, count; NSMutableData *vdata; if (![[valueList objectAtIndex:0] respondsToSelector:@selector(objCType)]) MA_RAISE_PARAMETER [self _initType:[[valueList objectAtIndex:0] objCType]]; count = [valueList count]; vdata = [NSMutableData dataWithLength:count*math_aligned_size([c_type cString])]; for (i=0; i < count; i++) { NSValue *value = [valueList objectAtIndex:i]; if (![value respondsToSelector:@selector(objCType)]) MA_RAISE_PARAMETER // FIXME: check for same types [value getValue:&vdata[i*math_aligned_size([c_type cString])]]; } return [self initWithData:vdata]; } - (void)dealloc { [c_type release]; [data release]; [super dealloc]; } - (const void *)bytes { return [data bytes]; } - (unsigned)length { return [data length]; } /* Returns an array containing NSPoint values */ - (const NSPoint *)pointArray { return (const NSPoint *)[self bytes]; } /* Returns an array containing NSRect values */ - (const NSRect *)rectArray { return (const NSRect *)[self bytes]; } /* Returns a NSArray containing NSValues representing the values in the receiver. */ - (NSArray *)valueList { int i, count; NSMutableArray *array; count = [self count]; array = [NSMutableArray arrayWithCapacity:count]; for (i=0; i < count; i++) [array addObject:[self valueAtIndex:i]]; return [array copy]; } /* Returns as an NSValue, the value stored at the specified index */ - (NSValue *)valueAtIndex:(unsigned)index { const void *value; value = [data bytes] + index * math_aligned_size([c_type cString]); /* I call MANumber instead of NSValue because MANumber will automatically allocate the correct NSNumber or NSValue object depending on c_type. NSValue won't do this (even though it should) */ return [MANumber value:value withObjCType:[c_type cString]]; } - (void) getValues:(void *)buffer range: (NSRange)range { range.location *= math_aligned_size([c_type cString]); range.length *= math_aligned_size([c_type cString]); [data getBytes:buffer range:range]; } /* Returns the number of values stored in the receiver. */ - (unsigned)count { return [self length]/math_aligned_size([c_type cString]); } /* Returns the Objective-C type of data sotred in the receiver */ - (const char *)objCType { return [c_type cString]; } - deepen { c_type = [c_type copyWithZone:[self zone]]; data = [data copyWithZone:[self zone]]; return self; } - copyWithZone:(NSZone *)zone { if (NSShouldRetainWithZone(self, zone)) return [self retain]; else return [[super copyWithZone:zone] deepen]; } - copy { return [self copyWithZone:[self zone]]; } - mutableCopyWithZone:(NSZone *)zone { MAMutableValueData *new = [MAMutableValueData allocWithZone:zone]; [new initWithValues:[self bytes] count:[self count] objCType:[c_type cString]]; return new; } - mutableCopy { return [self mutableCopyWithZone:[self zone]]; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:data]; [coder encodeObject:c_type]; } - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; data = [[coder decodeObject] retain]; c_type = [[coder decodeObject] retain]; return self; } @end @interface MAValueData (Private) - deepen; @end @implementation MAMutableValueData + allocWithZone:(NSZone *)zone { return NSAllocateObject(self, 0, zone); } + dataWithCount:(unsigned)count objCType:(const char *)type { return [[[self alloc] initWithCount:count objCType:type] autorelease]; } - (unsigned)_initType:(const char *)type { unsigned size; if (!type) { MA_RAISE_PARAMETER; /* NOT REACHED */ } size = math_aligned_size(type); c_type = [[NSString stringWithCString:type] retain]; return size; } - _allocData { // Allocate our storage, but don't initialize (for subclassing) data = (NSData *)[NSMutableData alloc]; return data; } /* The following two methods must be overriden from NSMutableData */ - initWithCapacity:(unsigned)capacity { [super init]; data = [(NSMutableData *)[self _allocData] initWithCapacity:capacity]; return self; } - initWithLength:(unsigned)length { [super init]; data = [(NSMutableData *)[self _allocData] initWithLength:length]; return self; } - initWithCount:(unsigned)count objCType:(const char *)type { unsigned type_size = [self _initType:type]; return [self initWithLength:count*type_size]; } - (void)setLength:(unsigned)length { [(NSMutableData *)data setLength:length]; } - (void *)mutableBytes { return [(NSMutableData *)data mutableBytes]; } - (void)setValue:(NSValue *)value atIndex:(unsigned)index; { unsigned size; size = math_aligned_size([self objCType]); if (!value) { [NSException raise:MAParameterException format:@"Tried to set with nil value"]; } if (strcmp([value objCType], [self objCType]) != 0) { [NSException raise:MAParameterException format:@"Tried to set with value of different type"]; } [value getValue:[(NSMutableData *)data mutableBytes]+index*size]; } - (void)increaseCountBy:(unsigned)extraCount { [self setLength:[self length] + extraCount * math_aligned_size([c_type cString])]; } - (void)setCount:(unsigned)count { [self setLength:count * math_aligned_size([c_type cString])]; } - (void)appendValues:(const void *)values count:(unsigned)count { [(NSMutableData *)data appendBytes:values length:count*math_aligned_size([c_type cString])]; } - (void)appendValueData:(MAValueData *)other { NSString *c_other; if (!other) { MA_RAISE_PARAMETER; /* NOT REACHED */ } c_other = [NSString stringWithCString:[other objCType]]; if (![c_type isEqual:c_other]) { [NSException raise:MAArrayMismatchException format:@"ValueData data types do not match"]; /* NOT REACHED */ } [(NSMutableData *)data appendData:other]; } - (void)replaceValuesInRange:(NSRange)aRange withValues:(const void *)values { unsigned size; size = math_aligned_size([c_type cString]); aRange = NSMakeRange(aRange.location*size, aRange.length*size); [(NSMutableData *)data replaceBytesInRange:aRange withBytes:values]; } - copyWithZone:(NSZone *)zone { MAMutableValueData *copy = NSCopyObject(self, 0, zone); return [copy deepen]; } @end @implementation MAMutableValueData (ValueCasting) /* This method changes what type of data the receiver thinks it is holding. It doesn't cast the data to the new form! You need to write your own routine to do that, if that is what you want. Adjusts the count automatically if the original type is of a different size than the new type. Raises an exception if the size of the new type exceeds the size of the data */ -(void)setObjCType:(const char *)type { if (math_aligned_size(type) > [self length]) { [NSException raise:MAParameterException format:@"New type exceeds length of data"]; /* NOT REACHED */ } // FIXME: what if sizes don't divide evenly? [c_type release]; c_type = [[NSString stringWithCString:type] retain]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.