main
  1//
  2// Licensed under the terms in License.txt
  3//
  4// Copyright 2010 Allen Ding. All rights reserved.
  5//
  6
  7#import "KWValue.h"
  8#import "KWObjCUtilities.h"
  9#import "NSNumber+KiwiAdditions.h"
 10
 11@interface KWValue()
 12
 13#pragma mark -
 14#pragma mark Properties
 15
 16@property (nonatomic, readonly) id value;
 17
 18@end
 19
 20@implementation KWValue
 21
 22#pragma mark -
 23#pragma mark Initializing
 24
 25- (id)initWithBytes:(const void *)bytes objCType:(const char *)anObjCType {
 26    if ((self = [super init])) {
 27        objCType = anObjCType;
 28        value = [[NSValue alloc] initWithBytes:bytes objCType:anObjCType];
 29    }
 30
 31    return self;
 32}
 33
 34+ (id)valueWithBytes:(const void *)bytes objCType:(const char *)type {
 35    return [[[self alloc] initWithBytes:bytes objCType:type] autorelease];
 36}
 37
 38+ (id)valueWithBool:(BOOL)aValue {
 39    return [self valueWithBytes:&aValue objCType:@encode(BOOL)];
 40}
 41
 42+ (id)valueWithChar:(char)aValue {
 43    return [self valueWithBytes:&aValue objCType:@encode(char)];
 44}
 45
 46+ (id)valueWithDouble:(double)aValue {
 47    return [self valueWithBytes:&aValue objCType:@encode(double)];
 48}
 49
 50+ (id)valueWithFloat:(float)aValue {
 51    return [self valueWithBytes:&aValue objCType:@encode(float)];
 52}
 53
 54+ (id)valueWithInt:(int)aValue {
 55    return [self valueWithBytes:&aValue objCType:@encode(int)];
 56}
 57
 58+ (id)valueWithInteger:(NSInteger)aValue {
 59    return [self valueWithBytes:&aValue objCType:@encode(NSInteger)];
 60}
 61
 62+ (id)valueWithLong:(long)aValue {
 63    return [self valueWithBytes:&aValue objCType:@encode(long)];
 64}
 65
 66+ (id)valueWithLongLong:(long long)value {
 67    return [self valueWithBytes:&value objCType:@encode(long long)];
 68}
 69
 70+ (id)valueWithShort:(short)aValue {
 71    return [self valueWithBytes:&aValue objCType:@encode(short)];
 72}
 73
 74+ (id)valueWithUnsignedChar:(unsigned char)aValue {
 75    return [self valueWithBytes:&aValue objCType:@encode(unsigned char)];
 76}
 77
 78+ (id)valueWithUnsignedInt:(unsigned int)aValue {
 79    return [self valueWithBytes:&aValue objCType:@encode(unsigned int)];
 80}
 81
 82+ (id)valueWithUnsignedInteger:(NSUInteger)aValue {
 83    return [self valueWithBytes:&aValue objCType:@encode(NSUInteger)];
 84}
 85
 86+ (id)valueWithUnsignedLong:(unsigned long)aValue {
 87    return [self valueWithBytes:&aValue objCType:@encode(unsigned long)];
 88}
 89
 90+ (id)valueWithUnsignedLongLong:(unsigned long long)aValue {
 91    return [self valueWithBytes:&aValue objCType:@encode(long long)];
 92}
 93
 94+ (id)valueWithUnsignedShort:(unsigned short)aValue {
 95    return [self valueWithBytes:&aValue objCType:@encode(unsigned short)];
 96}
 97
 98- (void)dealloc {
 99    [value release];
100    [super dealloc];
101}
102
103#pragma mark -
104#pragma mark Properties
105
106@synthesize objCType;
107
108- (BOOL)isNumeric {
109    return KWObjCTypeIsNumeric(self.objCType);
110}
111
112@synthesize value;
113
114#pragma mark -
115#pragma mark Accessing Numeric Values
116
117- (NSNumber *)numberValue {
118    if (!KWObjCTypeIsNumeric(self.objCType))
119        [NSException raise:NSInternalInconsistencyException format:@"cannot return number value because wrapped value is non-numeric"];
120
121    NSData *data = [self dataValue];
122    return [NSNumber numberWithBytes:[data bytes] objCType:self.objCType];
123}
124
125- (BOOL)boolValue {
126    return [[self numberValue] boolValue];
127}
128
129- (char)charValue {
130    return [[self numberValue] charValue];
131}
132
133- (double)doubleValue {
134    return [[self numberValue] doubleValue];
135}
136
137- (float)floatValue {
138    return [[self numberValue] floatValue];
139}
140
141- (int)intValue {
142    return [[self numberValue] intValue];
143}
144
145- (NSInteger)integerValue {
146    return [[self numberValue] integerValue];
147}
148
149- (long)longValue {
150    return [[self numberValue] longValue];
151}
152
153- (long long)longLongValue {
154    return [[self numberValue] longLongValue];
155}
156- (short)shortValue {
157    return [[self numberValue] shortValue];
158}
159
160- (unsigned char)unsignedCharValue {
161    return [[self numberValue] unsignedCharValue];
162}
163
164- (unsigned int)unsignedIntValue {
165    return [[self numberValue] unsignedIntValue];
166}
167
168- (NSUInteger)unsignedIntegerValue {
169    return [[self numberValue] unsignedIntegerValue];
170}
171
172- (unsigned long)unsignedLongValue {
173    return [[self numberValue] unsignedLongValue];
174}
175
176- (unsigned long long)unsignedLongLongValue {
177    return [[self numberValue] unsignedLongLongValue];
178}
179
180- (unsigned short)unsignedShortValue {
181    return [[self numberValue] unsignedShortValue];
182}
183
184#pragma mark -
185#pragma mark Accessing Data
186
187- (NSData *)dataValue {
188    NSUInteger length = KWObjCTypeLength(self.objCType);
189    void *buffer = malloc(length);
190    [self.value getValue:buffer];
191    NSData *data = [NSData dataWithBytes:buffer length:length];
192    free(buffer);
193    return data;
194}
195
196- (void)getValue:(void *)buffer {
197    [self.value getValue:buffer];
198}
199
200#pragma mark -
201#pragma mark Accessing Numeric Data
202
203- (NSData *)dataForObjCType:(const char *)anObjCType {
204    // Yeah, this is ugly.
205    if (KWObjCTypeEqualToObjCType(anObjCType, @encode(BOOL)))
206        return [self boolData];
207    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(char)))
208        return [self charData];
209    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(double)))
210        return [self doubleData];
211    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(float)))
212        return [self floatData];
213    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(int)))
214        return [self intData];
215    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(NSInteger)))
216        return [self integerData];
217    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(long)))
218        return [self longData];
219    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(long long)))
220        return [self longLongData];
221    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(short)))
222        return [self shortData];
223    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(unsigned char)))
224        return [self unsignedCharData];
225    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(unsigned int)))
226        return [self unsignedIntData];
227    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(NSUInteger)))
228        return [self unsignedIntegerData];
229    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(unsigned long)))
230        return [self unsignedLongData];
231    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(unsigned long long)))
232        return [self unsignedLongLongData];
233    else if (KWObjCTypeEqualToObjCType(anObjCType, @encode(unsigned short)))
234        return [self unsignedShortData];
235    else
236        return nil;
237}
238
239- (NSData *)boolData {
240    BOOL aValue = [self boolValue];
241    return [NSData dataWithBytes:&aValue length:sizeof(BOOL)];
242}
243
244- (NSData *)charData {
245    char aValue = [self charValue];
246    return [NSData dataWithBytes:&aValue length:sizeof(char)];
247}
248
249- (NSData *)doubleData {
250    double aValue = [self doubleValue];
251    return [NSData dataWithBytes:&aValue length:sizeof(double)];
252}
253
254- (NSData *)floatData {
255    float aValue = [self floatValue];
256    return [NSData dataWithBytes:&aValue length:sizeof(float)];
257}
258
259- (NSData *)intData {
260    int aValue = [self intValue];
261    return [NSData dataWithBytes:&aValue length:sizeof(int)];
262}
263
264- (NSData *)integerData {
265    NSInteger aValue = [self integerValue];
266    return [NSData dataWithBytes:&aValue length:sizeof(NSInteger)];
267}
268
269- (NSData *)longData {
270    long aValue = [self longValue];
271    return [NSData dataWithBytes:&aValue length:sizeof(long)];
272}
273
274- (NSData *)longLongData {
275    long long aValue = [self longLongValue];
276    return [NSData dataWithBytes:&aValue length:sizeof(long long)];
277}
278
279- (NSData *)shortData {
280    short aValue = [self shortValue];
281    return [NSData dataWithBytes:&aValue length:sizeof(short)];
282}
283
284- (NSData *)unsignedCharData {
285    unsigned char aValue = [self unsignedCharValue];
286    return [NSData dataWithBytes:&aValue length:sizeof(unsigned char)];
287}
288
289- (NSData *)unsignedIntData {
290    unsigned int aValue = [self unsignedIntValue];
291    return [NSData dataWithBytes:&aValue length:sizeof(unsigned int)];
292}
293
294- (NSData *)unsignedIntegerData {
295    NSUInteger aValue = [self unsignedIntegerValue];
296    return [NSData dataWithBytes:&aValue length:sizeof(NSUInteger)];
297}
298
299- (NSData *)unsignedLongData {
300    unsigned long aValue = [self unsignedLongValue];
301    return [NSData dataWithBytes:&aValue length:sizeof(unsigned long)];
302}
303
304- (NSData *)unsignedLongLongData {
305    unsigned long long aValue = [self unsignedLongLongValue];
306    return [NSData dataWithBytes:&aValue length:sizeof(unsigned long long)];
307}
308
309- (NSData *)unsignedShortData {
310    unsigned short aValue = [self unsignedShortValue];
311    return [NSData dataWithBytes:&aValue length:sizeof(unsigned short)];
312}
313
314#pragma mark -
315#pragma mark Comparing Objects
316
317- (NSUInteger)hash {
318    if (self.isNumeric)
319        return [[self numberValue] hash];
320
321    return [self.value hash];
322}
323
324- (NSComparisonResult)compare:(KWValue *)aValue {
325    return [[self numberValue] compare:[aValue numberValue]];
326}
327
328- (BOOL)isEqual:(id)object {
329    if ([object isKindOfClass:[KWValue class]])
330        return [self isEqualToKWValue:object];
331
332    if ([object isKindOfClass:[NSNumber class]])
333      return [self isEqualToNumber:object];
334
335    return NO;
336}
337
338- (BOOL)isEqualToKWValue:(KWValue *)aValue {
339    if (self.isNumeric && aValue.isNumeric)
340        return [self isEqualToNumber:[aValue numberValue]];
341    else
342        return [self.value isEqual:aValue.value];
343}
344
345- (BOOL)isEqualToNumber:(NSNumber *)aValue {
346    return [[self numberValue] isEqualToNumber:aValue];
347}
348
349#pragma mark -
350#pragma mark Representing Values
351
352- (NSString *)description {
353    if ([self isNumeric])
354        return [[self numberValue] description];
355
356    return [self.value description];
357}
358
359@end