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