KWValue.m 9.3 KB

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