5 // Created by Wincent Colaiuta on 09 June 2005.
7 // Copyright 2005-2007 Wincent Colaiuta.
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #import "NSValue+WOTest.h"
26 #import <objc/objc-runtime.h>
30 #import "NSObject+WOTest.h"
31 #import "NSScanner+WOTest.h"
32 #import "NSString+WOTest.h"
34 @implementation NSValue (WOTest)
37 #pragma mark Value creation methods
39 + (NSValue *)WOTest_valueWithChar:(char)aChar
41 return [NSValue value:&aChar withObjCType:@encode(char)];
44 + (NSValue *)WOTest_valueWithInt:(int)anInt
46 return [NSValue value:&anInt withObjCType:@encode(int)];
49 + (NSValue *)WOTest_valueWithShort:(short)aShort
51 return [NSValue value:&aShort withObjCType:@encode(short)];
54 + (NSValue *)WOTest_valueWithLong:(long)aLong
56 return [NSValue value:&aLong withObjCType:@encode(long)];
59 + (NSValue *)WOTest_valueWithLongLong:(long long)aLongLong
61 return [NSValue value:&aLongLong withObjCType:@encode(long long)];
64 + (NSValue *)WOTest_valueWithUnsignedChar:(unsigned char)anUnsignedChar
66 return [NSValue value:&anUnsignedChar withObjCType:@encode(unsigned char)];
69 + (NSValue *)WOTest_valueWithUnsignedInt:(unsigned int)anUnsignedInt
71 return [NSValue value:&anUnsignedInt withObjCType:@encode(unsigned int)];
74 + (NSValue *)WOTest_valueWithUnsignedShort:(unsigned short)anUnsignedShort
76 return [NSValue value:&anUnsignedShort withObjCType:@encode(unsigned short)];
79 + (NSValue *)WOTest_valueWithUnsignedLong:(unsigned long)anUnsignedLong
81 return [NSValue value:&anUnsignedLong withObjCType:@encode(unsigned long)];
84 + (NSValue *)WOTest_valueWithUnsignedLongLong:(unsigned long long)anUnsignedLongLong
86 return [NSValue value:&anUnsignedLongLong withObjCType:@encode(unsigned long long)];
89 + (NSValue *)WOTest_valueWithFloat:(float)aFloat
91 return [NSValue value:&aFloat withObjCType:@encode(float)];
94 + (NSValue *)WOTest_valueWithDouble:(double)aDouble
96 return [NSValue value:&aDouble withObjCType:@encode(double)];
99 + (NSValue *)WOTest_valueWithC99Bool:(_Bool)aC99Bool
101 return [NSValue value:&aC99Bool withObjCType:@encode(_Bool)];
104 + (NSValue *)WOTest_valueWithConstantCharacterString:(const char *)aConstantCharString
106 return [NSValue value:&aConstantCharString withObjCType:@encode(const char *)];
109 + (NSValue *)WOTest_valueWithCharacterString:(char *)aCharacterString
111 return [NSValue value:&aCharacterString withObjCType:@encode(char *)];
114 + (NSValue *)WOTest_valueWithObject:(id)anObject
116 return [NSValue value:&anObject withObjCType:@encode(id)];
119 + (NSValue *)WOTest_valueWithClass:(Class)aClass
121 return [NSValue value:&aClass withObjCType:@encode(Class)];
124 + (NSValue *)WOTest_valueWithSelector:(SEL)aSelector
126 return [NSValue value:&aSelector withObjCType:@encode(SEL)];
130 #pragma mark Parsing type strings
132 // TODO: investigate whether NSGetSizeAndAlignment() could save some code here...
133 + (size_t)WOTest_maximumEmbeddedSizeForType:(NSString *)typeString
135 NSParameterAssert(typeString != nil);
136 size_t size = 16; // worst case scenario
138 if ([self WOTest_typeIsCompound:typeString])
139 return [self WOTest_sizeForType:typeString];
141 if ([self WOTest_typeIsBitfield:typeString])
144 #if defined (__i386__)
146 if ([self WOTest_typeIsC99Bool:typeString] ||
147 [self WOTest_typeIsUnsignedChar:typeString] ||
148 [self WOTest_typeIsChar:typeString] ||
149 [self WOTest_typeIsUnsignedChar:typeString])
150 size = 1; // scalars of size/alignment 1
151 else if ([self WOTest_typeIsUnsignedShort:typeString] ||
152 [self WOTest_typeIsShort:typeString])
153 size = 2; // scalars of size/alignment 2
154 else if ([self WOTest_typeIsUnsignedInt:typeString] ||
155 [self WOTest_typeIsInt:typeString] ||
156 [self WOTest_typeIsUnsignedLong:typeString] ||
157 [self WOTest_typeIsLong:typeString] ||
158 [self WOTest_typeIsFloat:typeString])
159 size = 4; // scalars of size/alignment 4
160 else if ([self WOTest_typeIsUnsignedLongLong:typeString] ||
161 [self WOTest_typeIsLongLong:typeString] ||
162 [self WOTest_typeIsDouble:typeString])
163 size = 8; // scalars of size/alignment 8
164 else if ([self WOTest_typeIsPointer:typeString] ||
165 [self WOTest_typeIsPointerToVoid:typeString] ||
166 [self WOTest_typeIsObject:typeString] ||
167 [self WOTest_typeIsClass:typeString] ||
168 [self WOTest_typeIsSelector:typeString] ||
169 [self WOTest_typeIsCharacterString:typeString] ||
170 [self WOTest_typeIsConstantCharacterString:typeString])
171 size = 4; // pointers (size/alignment 4)
173 // documented in "Mac OS X ABI Function Call Guide" but not supported:
174 // long double 16 bytes
175 // vector (64 bits) 8 bytes
176 // vector (128 bits) 16 bytes
177 [NSException raise:NSInternalInconsistencyException
178 format:@"Type %@ not supported by WOTest_maximumEmbeddedSizeForType:", typeString];
180 #elif defined (__ppc__)
182 if ([self WOTest_typeIsUnsignedChar:typeString] ||
183 [self WOTest_typeIsChar:typeString])
184 size = 1; // scalars of size/alignment 1
185 else if ([self WOTest_typeIsUnsignedShort:typeString] ||
186 [self WOTest_typeIsShort:typeString])
187 size = 2; // scalars of size/alignment 2
188 else if ([self WOTest_typeIsC99Bool:typeString] ||
189 [self WOTest_typeIsUnsignedInt:typeString] ||
190 [self WOTest_typeIsInt:typeString] ||
191 [self WOTest_typeIsUnsignedLong:typeString] ||
192 [self WOTest_typeIsLong:typeString] ||
193 [self WOTest_typeIsFloat:typeString])
194 size = 4; // scalars of size/alignment 4
195 else if ([self WOTest_typeIsUnsignedLongLong:typeString] ||
196 [self WOTest_typeIsLongLong:typeString] ||
197 [self WOTest_typeIsDouble:typeString])
198 size = 8; // scalars of size/alignment 8
199 else if ([self WOTest_typeIsPointer:typeString] ||
200 [self WOTest_typeIsPointerToVoid:typeString] ||
201 [self WOTest_typeIsObject:typeString] ||
202 [self WOTest_typeIsClass:typeString] ||
203 [self WOTest_typeIsSelector:typeString] ||
204 [self WOTest_typeIsCharacterString:typeString] ||
205 [self WOTest_typeIsConstantCharacterString:typeString])
206 size = 4; // pointers (size/alignment 4)
208 // documented in "Mac OS X ABI Function Call Guide" but not supported:
209 // long double 8 bytes (Mac OS X < 10.4, GCC < 4.0)
210 // long double 16 bytes (Mac OS X >= 10.4, GCC >= 4.0)
212 [NSException raise:NSInternalInconsistencyException
213 format:@"Type %@ not supported by WOTest_maximumEmbeddedSizeForType:", typeString];
215 #elif defined (__ppc64__)
217 if ([self WOTest_typeIsC99Bool:typeString] ||
218 [self WOTest_typeIsUnsignedChar:typeString] ||
219 [self WOTest_typeIsChar:typeString])
220 size = 1; // scalars of size/alignment 1
221 else if ([self WOTest_typeIsUnsignedShort:typeString] ||
222 [self WOTest_typeIsShort:typeString])
223 size = 2; // scalars of size/alignment 2
224 else if ([self WOTest_typeIsUnsignedInt:typeString] ||
225 [self WOTest_typeIsInt:typeString] ||
226 [self WOTest_typeIsFloat:typeString])
227 size = 4; // scalars of size/alignment 4
228 else if ([self WOTest_typeIsUnsignedLong:typeString] ||
229 [self WOTest_typeIsLong:typeString] ||
230 [self WOTest_typeIsUnsignedLongLong:typeString] ||
231 [self WOTest_typeIsLongLong:typeString] ||
232 [self WOTest_typeIsDouble:typeString])
233 size = 8; // scalars of size/alignment 8
234 else if ([self WOTest_typeIsPointer:typeString] ||
235 [self WOTest_typeIsPointerToVoid:typeString] ||
236 [self WOTest_typeIsObject:typeString] ||
237 [self WOTest_typeIsClass:typeString] ||
238 [self WOTest_typeIsSelector:typeString] ||
239 [self WOTest_typeIsCharacterString:typeString] ||
240 [self WOTest_typeIsConstantCharacterString:typeString])
241 size = 8; // pointers (size/alignment 8)
243 // documented in "Mac OS X ABI Function Call Guide" but not supported:
244 // long double 16 bytes
246 [NSException raise:NSInternalInconsistencyException
247 format:@"Type %@ not supported by WOTest_maximumEmbeddedSizeForType:", typeString];
251 #error Unsupported architecture
258 + (size_t)WOTest_sizeForType:(NSString *)typeString
260 NSParameterAssert(typeString != nil);
263 if ([self WOTest_typeIsChar:typeString])
265 else if ([self WOTest_typeIsInt:typeString])
267 else if ([self WOTest_typeIsShort:typeString])
268 size = sizeof(short);
269 else if ([self WOTest_typeIsLong:typeString])
271 else if ([self WOTest_typeIsLongLong:typeString])
272 size = sizeof(long long);
273 else if ([self WOTest_typeIsUnsignedChar:typeString])
274 size = sizeof(unsigned char);
275 else if ([self WOTest_typeIsUnsignedInt:typeString])
276 size = sizeof(unsigned int);
277 else if ([self WOTest_typeIsUnsignedShort:typeString])
278 size = sizeof(unsigned short);
279 else if ([self WOTest_typeIsUnsignedLong:typeString])
280 size = sizeof(unsigned long);
281 else if ([self WOTest_typeIsUnsignedLongLong:typeString])
282 size = sizeof(unsigned long long);
283 else if ([self WOTest_typeIsFloat:typeString])
284 size = sizeof(float);
285 else if ([self WOTest_typeIsDouble:typeString])
286 size = sizeof(double);
287 else if ([self WOTest_typeIsC99Bool:typeString])
288 size = sizeof(_Bool);
289 else if ([self WOTest_typeIsVoid:typeString])
291 else if ([self WOTest_typeIsConstantCharacterString:typeString])
292 size = sizeof(const char *);
293 else if ([self WOTest_typeIsCharacterString:typeString])
294 size = sizeof(char *);
295 else if ([self WOTest_typeIsObject:typeString])
297 else if ([self WOTest_typeIsClass:typeString])
298 size = sizeof(Class);
299 else if ([self WOTest_typeIsSelector:typeString])
301 else if ([self WOTest_typeIsPointerToVoid:typeString])
302 size = sizeof(void *);
303 else // handle complex types and special cases
306 if ([self WOTest_typeIsPointer:typeString])
307 size = sizeof(void *);
308 else if ([self WOTest_typeIsArray:typeString])
310 NSScanner *scanner = [NSScanner scannerWithString:typeString];
311 unichar startMarker, endMarker;
313 NSString *elementType;
314 if ([scanner WOTest_scanCharacter:&startMarker] &&
315 (startMarker == _C_ARY_B) && [scanner scanInt:&count] &&
316 [scanner WOTest_scanTypeIntoString:&elementType] &&
317 [scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_ARY_E) &&
321 size = [self WOTest_sizeForType:elementType] * count;
324 [NSException raise:NSInternalInconsistencyException
325 format:@"scanner error in sizeForType for type %@", typeString];
327 else if ([self WOTest_typeIsStruct:typeString])
329 NSScanner *scanner = [NSScanner scannerWithString:typeString];
330 unichar startMarker, endMarker;
332 if ([scanner WOTest_scanCharacter:&startMarker] &&
333 (startMarker == _C_STRUCT_B))
335 // scan optional identifier
336 if ([scanner WOTest_scanIdentifierIntoString:nil])
337 [scanner WOTest_scanCharacter:NULL]; // scan past "="
339 NSString *memberType;
340 size_t largestMember = 0;
341 while ([scanner WOTest_scanTypeIntoString:&memberType])
343 size_t memberSize = [self WOTest_maximumEmbeddedSizeForType:memberType];
344 largestMember = MAX(largestMember, memberSize);
346 if (memberSize != 0) // watch out for division by zero
348 // check for alignment gap
349 size_t modulo = (size % memberSize);
350 if (modulo != 0) // fill alignment gap
351 size += (memberSize - modulo);
357 #if defined (__i386__) || defined (__ppc64)
359 // Special rules for i386:
360 // 1. Composite data types (structs/arrays/unions) take on the alignment of the member with the highest alignment
361 // 2. Size of composite type is a multiple of its alignment
363 // Special rules for ppc64 (equivalent):
364 // 1. Embedding alignment of composite types (array/struct) is same as largest embedding align of members.
365 // 2. Total size of the composite is rounded up to multiple of its embedding alignment.
367 // Special rules for ppc: None.
369 if (largestMember != 0) // watch out for division by zero
371 // check for alignment gap
372 size_t modulo = (size % largestMember);
373 if (modulo != 0) // fill alignment gap
374 size += (largestMember - modulo);
379 if ([scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_STRUCT_E) && [scanner isAtEnd])
380 return size; // all done
383 [NSException raise:NSInternalInconsistencyException format:@"scanner error in sizeForType for type %@", typeString];
385 else if ([self WOTest_typeIsUnion:typeString])
387 NSScanner *scanner = [NSScanner scannerWithString:typeString];
388 unichar startMarker, endMarker;
390 if ([scanner WOTest_scanCharacter:&startMarker] && (startMarker == _C_UNION_B))
392 // scan optional identifier
393 if ([scanner WOTest_scanIdentifierIntoString:nil])
394 [scanner WOTest_scanCharacter:NULL]; // scan past "="
396 NSString *memberType;
397 while ([scanner WOTest_scanTypeIntoString:&memberType])
398 // size of union is size of largest type in the union
399 size = MAX(size, [self WOTest_maximumEmbeddedSizeForType:memberType]);
401 if ([scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_UNION_E) && [scanner isAtEnd])
402 return size; // all done
405 [NSException raise:NSInternalInconsistencyException format:@"scanner error in sizeForType for type %@", typeString];
407 else if ([self WOTest_typeIsBitfield:typeString])
409 else if ([self WOTest_typeIsUnknown:typeString])
411 // could be a function pointer, but could be something else
412 [NSException raise:NSInternalInconsistencyException format: @"Cannot calculate buffer size for type %@", typeString];
414 else // we officially have no idea whatsoever
415 [NSException raise:NSInternalInconsistencyException
416 format:@"Cannot calculate buffer size for unknown type %@", typeString];
422 /*! Returns YES if \p typeString contains a numeric scalar value (char, int, short, long, long long, unsigned char, unsigned int, unsigned short, unsigned long, unsigned long long, float, double, C99 _Bool). Returns NO if the receiver contains any other type, object or pointer (id, Class, SEL, void, char *, as well as arrays, structures and pointers). */
423 + (BOOL)WOTest_typeIsNumericScalar:(NSString *)typeString
425 if (!typeString) return NO;
426 return ([self WOTest_typeIsChar:typeString] ||
427 [self WOTest_typeIsInt:typeString] ||
428 [self WOTest_typeIsShort:typeString] ||
429 [self WOTest_typeIsLong:typeString] ||
430 [self WOTest_typeIsLongLong:typeString] ||
431 [self WOTest_typeIsUnsignedChar:typeString] ||
432 [self WOTest_typeIsUnsignedInt:typeString] ||
433 [self WOTest_typeIsUnsignedShort:typeString] ||
434 [self WOTest_typeIsUnsignedLong:typeString] ||
435 [self WOTest_typeIsUnsignedLongLong:typeString] ||
436 [self WOTest_typeIsFloat:typeString] ||
437 [self WOTest_typeIsDouble:typeString] ||
438 [self WOTest_typeIsC99Bool:typeString]);
441 + (BOOL)WOTest_typeIsCompound:(NSString *)typeString
443 if (!typeString) return NO;
444 return ([self WOTest_typeIsStruct:typeString] || [self WOTest_typeIsUnion:typeString] || [self WOTest_typeIsArray:typeString]);
447 + (BOOL)WOTest_typeIsChar:(NSString *)typeString
449 if (!typeString) return NO;
450 const char *type = [typeString UTF8String];
451 return ((strlen(type) == 1) && *type == _C_CHR);
454 + (BOOL)WOTest_typeIsInt:(NSString *)typeString
456 if (!typeString) return NO;
457 const char *type = [typeString UTF8String];
458 return ((strlen(type) == 1) && *type == _C_INT);
461 + (BOOL)WOTest_typeIsShort:(NSString *)typeString
463 if (!typeString) return NO;
464 const char *type = [typeString UTF8String];
465 return ((strlen(type) == 1) && *type == _C_SHT);
468 + (BOOL)WOTest_typeIsLong:(NSString *)typeString
470 if (!typeString) return NO;
471 const char *type = [typeString UTF8String];
472 return ((strlen(type) == 1) && *type == _C_LNG);
475 + (BOOL)WOTest_typeIsLongLong:(NSString *)typeString
477 if (!typeString) return NO;
478 const char *type = [typeString UTF8String];
479 return ((strlen(type) == 1) && *type == _C_LNGLNG);
482 + (BOOL)WOTest_typeIsUnsignedChar:(NSString *)typeString
484 if (!typeString) return NO;
485 const char *type = [typeString UTF8String];
486 return ((strlen(type) == 1) && *type == _C_UCHR);
489 + (BOOL)WOTest_typeIsUnsignedInt:(NSString *)typeString
491 if (!typeString) return NO;
492 const char *type = [typeString UTF8String];
493 return ((strlen(type) == 1) && *type == _C_UINT);
496 + (BOOL)WOTest_typeIsUnsignedShort:(NSString *)typeString
498 if (!typeString) return NO;
499 const char *type = [typeString UTF8String];
500 return ((strlen(type) == 1) && *type == _C_USHT);
503 + (BOOL)WOTest_typeIsUnsignedLong:(NSString *)typeString
505 if (!typeString) return NO;
506 const char *type = [typeString UTF8String];
507 return ((strlen(type) == 1) && *type == _C_ULNG);
510 + (BOOL)WOTest_typeIsUnsignedLongLong:(NSString *)typeString
512 if (!typeString) return NO;
513 const char *type = [typeString UTF8String];
514 return ((strlen(type) == 1) && *type == _C_ULNGLNG);
517 + (BOOL)WOTest_typeIsFloat:(NSString *)typeString
519 if (!typeString) return NO;
520 const char *type = [typeString UTF8String];
521 return ((strlen(type) == 1) && *type == _C_FLT);
524 + (BOOL)WOTest_typeIsDouble:(NSString *)typeString
526 if (!typeString) return NO;
527 const char *type = [typeString UTF8String];
528 return ((strlen(type) == 1) && *type == _C_DBL);
531 + (BOOL)WOTest_typeIsC99Bool:(NSString *)typeString
533 if (!typeString) return NO;
534 const char *type = [typeString UTF8String];
535 return ((strlen(type) == 1) && *type == _C_99BOOL);
538 + (BOOL)WOTest_typeIsVoid:(NSString *)typeString
540 if (!typeString) return NO;
541 const char *type = [typeString UTF8String];
542 return ((strlen(type) == 1) && *type == _C_VOID);
545 + (BOOL)WOTest_typeIsConstantCharacterString:(NSString *)typeString
547 if (!typeString) return NO;
548 const char *type = [typeString UTF8String];
549 return ((strlen(type) == 2) && (strcmp(type, "r*") == 0));
552 + (BOOL)WOTest_typeIsCharacterString:(NSString *)typeString
554 if (!typeString) return NO;
555 const char *type = [typeString UTF8String];
556 return ((strlen(type) == 1) && *type == _C_CHARPTR);
559 + (BOOL)WOTest_typeIsObject:(NSString *)typeString
561 if (!typeString) return NO;
562 const char *type = [typeString UTF8String];
563 return ((strlen(type) == 1) && *type == _C_ID);
566 + (BOOL)WOTest_typeIsClass:(NSString *)typeString
568 if (!typeString) return NO;
569 const char *type = [typeString UTF8String];
570 return ((strlen(type) == 1) && *type == _C_CLASS);
573 + (BOOL)WOTest_typeIsSelector:(NSString *)typeString
575 if (!typeString) return NO;
576 const char *type = [typeString UTF8String];
577 return ((strlen(type) == 1) && *type == _C_SEL);
580 + (BOOL)WOTest_typeIsPointerToVoid:(NSString *)typeString
582 if (!typeString) return NO;
583 const char *type = [typeString UTF8String];
584 return ((strlen(type) == 2) && (strcmp(type, "^v") == 0));
587 + (BOOL)WOTest_typeIsPointer:(NSString *)typeString
589 NSScanner *scanner = [NSScanner scannerWithString:typeString];
590 return [scanner scanPointerIntoString:nil];
593 + (BOOL)WOTest_typeIsArray:(NSString *)typeString
595 NSScanner *scanner = [NSScanner scannerWithString:typeString];
596 return [scanner WOTest_scanArrayIntoString:nil];
599 + (BOOL)WOTest_typeIsStruct:(NSString *)typeString
601 NSScanner *scanner = [NSScanner scannerWithString:typeString];
602 return [scanner WOTest_scanStructIntoString:nil];
605 + (BOOL)WOTest_typeIsUnion:(NSString *)typeString
607 NSScanner *scanner = [NSScanner scannerWithString:typeString];
608 return [scanner WOTest_scanUnionIntoString:nil];
611 + (BOOL)WOTest_typeIsBitfield:(NSString *)typeString
613 NSScanner *scanner = [NSScanner scannerWithString:typeString];
614 return [scanner WOTest_scanBitfieldIntoString:nil];
617 + (BOOL)WOTest_typeIsUnknown:(NSString *)typeString
619 if (!typeString) return NO;
620 const char *type = [typeString UTF8String];
621 return ((strlen(type) == 1) && *type == _C_UNDEF);
625 #pragma mark High-level test methods
627 - (BOOL)WOTest_testIsEqualToValue:(NSValue *)otherValue
629 if (!otherValue) return NO;
631 if ([self WOTest_isObject])
633 if ([otherValue WOTest_isObject])
635 // can only compare objects with objects
636 id selfObject = [self nonretainedObjectValue];
637 id otherObject = [otherValue nonretainedObjectValue];
639 // avoid the message send if pointers are equal
640 // this also allows two nil object pointers to be considered equal, as they should
641 if (selfObject == otherObject)
645 if (selfObject && otherObject && [NSObject WOTest_object:selfObject respondsToSelector:@selector(isEqual:)])
646 return [selfObject isEqual:otherObject];
652 else if ([otherValue WOTest_isNumericScalar])
654 // check for special case: comparing an object with nil
655 if (strcmp([otherValue objCType], @encode(typeof(nil))) == 0)
657 typeof(nil) nilId = nil;
658 NSValue *nilValue = [NSValue valueWithBytes:&nilId objCType:@encode(typeof(nil))];
659 if ([otherValue WOTest_compare:nilValue] == NSOrderedSame) // comparing other value (nil) with self object
660 return ([self nonretainedObjectValue] == nil);
663 // will raise exception (comparing numeric scalar with object)
664 return ([self WOTest_compare:otherValue] == NSOrderedSame);
666 else if ([otherValue WOTest_isPointerToVoid])
667 // encodings changed on Leopard such that comparisons such as WO_TEST_EQ(foo, nil) no longer worked;
668 // in this case foo is encoded as type "@" (object) and nil as "^v" (pointer to void)
669 // so we end up here and just compare pointers numerically
670 return ((void *)[self nonretainedObjectValue] == [otherValue pointerValue]);
672 else if ([self WOTest_isNumericScalar])
674 // check for special case: comparing with nil
675 typeof(nil) nilId = nil;
676 NSValue *nilValue = [NSValue valueWithBytes:&nilId objCType:@encode(typeof(nil))];
677 if ((strcmp([self objCType], @encode(typeof(nil))) == 0) && ([self WOTest_compare:nilValue] == NSOrderedSame))
679 // self is nil (or at least looks like nil)
680 if ([otherValue WOTest_isObject]) // comparing self (nil) with otherObject
681 return ([otherValue nonretainedObjectValue] == nil);
682 else if ([otherValue WOTest_isPointerToVoid]) // special case can compare to pointer to void if zero
683 return ((id)[otherValue pointerValue] == nil);
686 // could raise exception (comparing numeric scalar with object)
687 return ([self WOTest_compare:otherValue] == NSOrderedSame);
689 else if ([self WOTest_isPointerToVoid])
691 if ([otherValue WOTest_isObject])
692 // special case for pointer-to-void vs object comparisons (necessary on Leopard)
693 return ([self pointerValue] == (void *)[otherValue nonretainedObjectValue]);
694 else if ([otherValue WOTest_isPointerToVoid])
695 // this special case already necessary on Leopard, otherwise nil-to-nil comparison fails
696 return ([self pointerValue] == [otherValue pointerValue]);
698 // fall through to standard case
699 return ([self WOTest_compare:otherValue] == NSOrderedSame);
701 else if (([self WOTest_isCharArray] || [self WOTest_isCharacterString] || [self WOTest_isConstantCharacterString]) &&
702 ([otherValue WOTest_isCharArray] || [otherValue WOTest_isCharacterString] ||
703 [otherValue WOTest_isConstantCharacterString]))
705 // another special case
706 NSString *selfString = [self WOTest_stringValue];
707 NSString *otherString = [otherValue WOTest_stringValue];
708 if (selfString && otherString)
709 return [selfString isEqualToString:otherString];
712 // fallback case (Class objects, SEL, structs, unions, pointers etc)
713 return [self isEqualToValue:otherValue];
716 - (BOOL)WOTest_testIsGreaterThanValue:(NSValue *)aValue
718 return ([self WOTest_compare:aValue] == NSOrderedDescending);
721 - (BOOL)WOTest_testIsLessThanValue:(NSValue *)aValue
723 return ([self WOTest_compare:aValue] == NSOrderedAscending);
726 - (BOOL)WOTest_testIsNotGreaterThanValue:(NSValue *)aValue
728 return ([self WOTest_compare:aValue] != NSOrderedDescending);
731 - (BOOL)WOTest_testIsNotLessThanValue:(NSValue *)aValue
733 return ([self WOTest_compare:aValue] != NSOrderedAscending);
736 - (NSComparisonResult)WOTest_compare:(NSValue *)aValue
739 [NSException raise:NSInvalidArgumentException format:@"cannot compare to nil"];
742 if ([self WOTest_isObject])
744 if (![aValue WOTest_isObject])
745 [NSException raise:NSInvalidArgumentException format:@"cannot compare object with non-object"];
747 id selfObject = [self nonretainedObjectValue];
748 id otherObject = [aValue nonretainedObjectValue];
750 if ([selfObject isKindOfClass:[otherObject class]] && [selfObject respondsToSelector:@selector(compare:)])
751 return ((NSComparisonResult (*)(id, SEL, id))objc_msgSend)(selfObject, @selector(compare:), otherObject);
752 else if ([otherObject isKindOfClass:[selfObject class]] && [otherObject respondsToSelector:@selector(compare:)])
753 return ((NSComparisonResult (*)(id, SEL, id))objc_msgSend)(otherObject, @selector(compare:), selfObject);
755 [NSException raise:NSInvalidArgumentException format:@"compared objects must be of same class and implement compare:"];
758 // numeric scalar case
759 if ([self WOTest_isNumericScalar] && [aValue WOTest_isNumericScalar])
761 if ([aValue WOTest_isChar])
762 return [self WOTest_compareWithChar:[aValue WOTest_charValue]];
763 else if ([aValue WOTest_isInt])
764 return [self WOTest_compareWithInt:[aValue WOTest_intValue]];
765 else if ([aValue WOTest_isShort])
766 return [self WOTest_compareWithShort:[aValue WOTest_shortValue]];
767 else if ([aValue WOTest_isLong])
768 return [self WOTest_compareWithLong:[aValue WOTest_longValue]];
769 else if ([aValue WOTest_isLongLong])
770 return [self WOTest_compareWithLongLong:[aValue WOTest_longLongValue]];
771 else if ([aValue WOTest_isUnsignedChar])
772 return [self WOTest_compareWithUnsignedChar:[aValue WOTest_unsignedCharValue]];
773 else if ([aValue WOTest_isUnsignedInt])
774 return [self WOTest_compareWithUnsignedInt:[aValue WOTest_unsignedIntValue]];
775 else if ([aValue WOTest_isUnsignedShort])
776 return [self WOTest_compareWithUnsignedShort:[aValue WOTest_unsignedShortValue]];
777 else if ([aValue WOTest_isUnsignedLong])
778 return [self WOTest_compareWithUnsignedLong:[aValue WOTest_unsignedLongValue]];
779 else if ([aValue WOTest_isUnsignedLongLong])
780 return [self WOTest_compareWithUnsignedLongLong:
781 [aValue WOTest_unsignedLongLongValue]];
782 else if ([aValue WOTest_isFloat])
783 return [self WOTest_compareWithFloat:[aValue WOTest_floatValue]];
784 else if ([aValue WOTest_isDouble])
785 return [self WOTest_compareWithDouble:[aValue WOTest_doubleValue]];
786 else if ([aValue WOTest_isC99Bool])
787 return [self WOTest_compareWithC99Bool:[aValue WOTest_C99BoolValue]];
790 [NSException raise:NSInvalidArgumentException format:@"non-numeric value(s) passed"];
792 // never reached, but necessary to suppress compiler warning
793 return NSOrderedSame;
797 #pragma mark Utility methods
799 - (size_t)WOTest_bufferSize
801 return [[self class] WOTest_sizeForType:[self WOTest_objCTypeString]];
804 - (void)WOTest_printSignCompareWarning:(NSString *)warning
806 NSParameterAssert(warning != nil);
808 // this conditional in here so that the warnings can be turned off in WOTest self-testing
809 if ([[WOTest sharedInstance] warnsAboutSignComparisons])
811 [[WOTest sharedInstance] writeWarning:warning];
812 [[WOTest sharedInstance] writeLastKnownLocation];
817 #pragma mark Convenience methods
819 /*! Returns the Objective-C type of the receiver as an NSString. */
820 - (NSString *)WOTest_objCTypeString
822 return [NSString stringWithUTF8String:[self objCType]];
825 - (NSString *)WOTest_description
827 // these special handlings exist because NSValue's description is not very human-friendly
828 // it gets even worse when running on Intel: for example, an integer like 500,000 (0x0007a120 hex) is displayed as "<20a10700>"
829 if ([self WOTest_isObject])
831 // look for objects that are either (NSString objects) or objects that respond to "description"
832 id valueContents = [self WOTest_objectValue];
835 // for NSString objects: just return content
836 if ([NSObject WOTest_object:valueContents isKindOfClass:[NSString class]])
837 return [[valueContents retain] autorelease];
838 else if ([NSObject WOTest_object:valueContents respondsToSelector:@selector(description)] &&
839 [NSObject WOTest_isIdReturnType:[NSObject WOTest_returnTypeForObject:valueContents
840 selector:@selector(description)]])
842 NSString *description = objc_msgSend(valueContents, @selector(description));
843 if (description && [NSObject WOTest_object:description isKindOfClass:[NSString class]])
848 // TODO: write unit tests to confirm that NSString supports all of these printf format markers and modifiers
849 else if ([self WOTest_isChar])
851 char character = [self WOTest_charValue];
852 if (character == 32) // the space character
854 else if ((character >= 33) && (character <= 126)) // other printable characters printed as an ASCII char
855 return [NSString stringWithFormat:@"'%C'", (unichar)character];
857 return [NSString stringWithFormat:@"(char)%hhd", character]; // all others printed as signed numbers
859 else if ([self WOTest_isInt])
860 return [NSString stringWithFormat:@"(int)%d", [self WOTest_intValue]];
861 else if ([self WOTest_isShort])
862 return [NSString stringWithFormat:@"(short)%hi", [self WOTest_shortValue]];
863 else if ([self WOTest_isLong])
864 return [NSString stringWithFormat:@"(long)%ld", [self WOTest_longValue]];
865 else if ([self WOTest_isLongLong])
866 return [NSString stringWithFormat:@"(long long)%lld", [self WOTest_longLongValue]];
867 else if ([self WOTest_isUnsignedChar])
869 unsigned char character = [self WOTest_unsignedCharValue];
870 if (character == 32) // the space character
872 else if ((character >= 33) && (character <= 126)) // other printable characters printed as an ASCII char
873 return [NSString stringWithFormat:@"%C", (unichar)character];
875 // all others printed as unsigned numbers
876 return [NSString stringWithFormat:@"(unsigned char)%hhu", [self WOTest_unsignedCharValue]];
878 else if ([self WOTest_isUnsignedInt])
879 return [NSString stringWithFormat:@"(unsigned int)%u", [self WOTest_unsignedIntValue]];
880 else if ([self WOTest_isUnsignedShort])
881 return [NSString stringWithFormat:@"(unsigned short)%hu", [self WOTest_unsignedShortValue]];
882 else if ([self WOTest_isUnsignedLong])
883 return [NSString stringWithFormat:@"(unsigned long)%lu", [self WOTest_unsignedLongValue]];
884 else if ([self WOTest_isUnsignedLongLong])
885 return [NSString stringWithFormat:@"(unsigned long long)%llu", [self WOTest_unsignedLongLongValue]];
886 else if ([self WOTest_isFloat])
887 return [NSString stringWithFormat:@"(float)%f", [self WOTest_floatValue]];
888 else if ([self WOTest_isDouble])
889 return [NSString stringWithFormat:@"(double)%f", [self WOTest_doubleValue]];
890 else if ([self WOTest_isC99Bool])
891 return [NSString stringWithFormat:@"(_Bool)%@", [self WOTest_C99BoolValue] ? @"true" : @"false"];
892 else if ([self WOTest_isVoid])
894 else if ([self WOTest_isConstantCharacterString])
895 return [NSString stringWithFormat:@"\"%s\"", [self WOTest_constantCharacterStringValue]];
896 else if ([self WOTest_isCharacterString])
897 return [NSString stringWithFormat:@"\"%s\"", [self WOTest_characterStringValue]];
898 else if ([self WOTest_isClass])
899 return [NSString stringWithFormat:@"(Class)%@", NSStringFromClass([self WOTest_classValue])];
900 else if ([self WOTest_isSelector])
901 return [NSString stringWithFormat:@"(SEL)%@", NSStringFromSelector([self WOTest_selectorValue])];
902 else if ([self WOTest_isPointerToVoid])
903 return [NSString stringWithFormat:@"(void *)%#08x", [self WOTest_pointerToVoidValue]];
904 return [self description]; // fallback case
908 #pragma mark Identifying generic types
910 - (BOOL)WOTest_isNumericScalar
912 return ([self WOTest_isChar] || [self WOTest_isInt] ||
913 [self WOTest_isShort] || [self WOTest_isLong] ||
914 [self WOTest_isLongLong] || [self WOTest_isUnsignedChar] ||
915 [self WOTest_isUnsignedInt] || [self WOTest_isUnsignedShort] ||
916 [self WOTest_isUnsignedLong] || [self WOTest_isUnsignedLongLong] ||
917 [self WOTest_isFloat] || [self WOTest_isDouble] ||
918 [self WOTest_isC99Bool]);
921 - (BOOL)WOTest_isPointer
923 return [[self class] WOTest_typeIsPointer:[self WOTest_objCTypeString]];
926 - (BOOL)WOTest_isArray
928 return [[self class] WOTest_typeIsArray:[self WOTest_objCTypeString]];
931 - (unsigned)WOTest_arrayCount
933 NSAssert([self WOTest_isArray],
934 @"WOTest_arrayCount sent but receiver does not contain an array");
935 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
939 // attempt the scan: it should work
940 if (!([scanner WOTest_scanCharacter:&startMarker] && (startMarker == _C_ARY_B) && [scanner scanInt:&count]))
941 [NSException raise:NSInternalInconsistencyException format:@"scanner error in WOTest_arrayCount"];
943 return (unsigned)count;
946 - (NSString *)WOTest_arrayType
948 NSAssert([self WOTest_isArray], @"WOTest_arrayType sent but receiver does not contain an array");
949 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
950 [scanner setScanLocation:1];
951 NSString *typeString;
952 if (!([scanner scanInt:nil] && [scanner WOTest_scanTypeIntoString:&typeString]))
953 [NSException raise:NSInternalInconsistencyException format:@"scanner error in WOTest_arrayType"];
957 - (BOOL)WOTest_isStruct
959 return [[self class] WOTest_typeIsStruct:[self WOTest_objCTypeString]];
962 - (BOOL)WOTest_isUnion
964 return [[self class] WOTest_typeIsUnion:[self WOTest_objCTypeString]];
967 - (BOOL)WOTest_isBitfield
969 return [[self class] WOTest_typeIsBitfield:[self WOTest_objCTypeString]];
972 - (BOOL)WOTest_isUnknown
974 return [[self class] WOTest_typeIsUnknown:[self WOTest_objCTypeString]];
978 #pragma mark Identifying and retrieving specific types
980 - (BOOL)WOTest_isChar
982 return [[self class] WOTest_typeIsChar:[self WOTest_objCTypeString]];
987 return [[self class] WOTest_typeIsInt:[self WOTest_objCTypeString]];
990 - (BOOL)WOTest_isShort
992 return [[self class] WOTest_typeIsShort:[self WOTest_objCTypeString]];
995 - (BOOL)WOTest_isLong
997 return [[self class] WOTest_typeIsLong:[self WOTest_objCTypeString]];
1000 - (BOOL)WOTest_isLongLong
1002 return [[self class] WOTest_typeIsLongLong:[self WOTest_objCTypeString]];
1005 - (BOOL)WOTest_isUnsignedChar
1007 return [[self class] WOTest_typeIsUnsignedChar:[self WOTest_objCTypeString]];
1010 - (BOOL)WOTest_isUnsignedInt
1012 return [[self class] WOTest_typeIsUnsignedInt:[self WOTest_objCTypeString]];
1015 - (BOOL)WOTest_isUnsignedShort
1017 return [[self class] WOTest_typeIsUnsignedShort:[self WOTest_objCTypeString]];
1020 - (BOOL)WOTest_isUnsignedLong
1022 return [[self class] WOTest_typeIsUnsignedLong:[self WOTest_objCTypeString]];
1025 - (BOOL)WOTest_isUnsignedLongLong
1027 return [[self class] WOTest_typeIsUnsignedLongLong:[self WOTest_objCTypeString]];
1030 - (BOOL)WOTest_isFloat
1032 return [[self class] WOTest_typeIsFloat:[self WOTest_objCTypeString]];
1035 - (BOOL)WOTest_isDouble
1037 return [[self class] WOTest_typeIsDouble:[self WOTest_objCTypeString]];
1040 - (BOOL)WOTest_isC99Bool
1042 return [[self class] WOTest_typeIsC99Bool:[self WOTest_objCTypeString]];
1045 - (BOOL)WOTest_isVoid
1047 return [[self class] WOTest_typeIsVoid:[self WOTest_objCTypeString]];
1050 - (BOOL)WOTest_isConstantCharacterString
1052 return [[self class] WOTest_typeIsConstantCharacterString:[self WOTest_objCTypeString]];
1055 - (BOOL)WOTest_isCharacterString
1057 return [[self class] WOTest_typeIsCharacterString:[self WOTest_objCTypeString]];
1060 - (BOOL)WOTest_isObject
1062 return [[self class] WOTest_typeIsObject:[self WOTest_objCTypeString]];
1065 - (BOOL)WOTest_isClass
1067 return [[self class] WOTest_typeIsClass:[self WOTest_objCTypeString]];
1070 - (BOOL)WOTest_isSelector
1072 return [[self class] WOTest_typeIsSelector:[self WOTest_objCTypeString]];
1075 - (BOOL)WOTest_isPointerToVoid
1077 return [[self class] WOTest_typeIsPointerToVoid:[self WOTest_objCTypeString]];
1080 - (char)WOTest_charValue
1083 [self getValue:&value];
1087 - (int)WOTest_intValue
1090 [self getValue:&value];
1094 - (short)WOTest_shortValue
1097 [self getValue:&value];
1101 - (long)WOTest_longValue
1104 [self getValue:&value];
1108 - (long long)WOTest_longLongValue
1111 [self getValue:&value];
1115 - (unsigned char)WOTest_unsignedCharValue
1117 unsigned char value;
1118 [self getValue:&value];
1122 - (unsigned int)WOTest_unsignedIntValue
1125 [self getValue:&value];
1129 - (unsigned short)WOTest_unsignedShortValue
1131 unsigned short value;
1132 [self getValue:&value];
1136 - (unsigned long)WOTest_unsignedLongValue
1138 unsigned long value;
1139 [self getValue:&value];
1143 - (unsigned long long)WOTest_unsignedLongLongValue
1145 unsigned long long value;
1146 [self getValue:&value];
1150 - (float)WOTest_floatValue
1153 [self getValue:&value];
1157 - (double)WOTest_doubleValue
1160 [self getValue:&value];
1164 - (_Bool)WOTest_C99BoolValue
1167 [self getValue:&value];
1171 - (const char *)WOTest_constantCharacterStringValue
1174 [self getValue:&value];
1178 - (char *)WOTest_characterStringValue
1181 [self getValue:&value];
1185 - (id)WOTest_objectValue
1188 [self getValue:&value];
1192 - (Class)WOTest_classValue
1195 [self getValue:&value];
1199 - (SEL)WOTest_selectorValue
1202 [self getValue:&value];
1206 - (void *)WOTest_pointerToVoidValue
1209 [self getValue:&value];
1213 - (BOOL)WOTest_isCharArray
1215 // look for string of form "[4c]"
1216 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
1217 unichar startMarker, flag, endMarker;
1219 return ([scanner WOTest_scanCharacter:&startMarker] && (startMarker == _C_ARY_B) &&
1220 [scanner scanInt:&count] &&
1221 [scanner WOTest_scanCharacter:&flag] && (flag == _C_CHR) &&
1222 [scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_ARY_E) &&
1226 - (NSString *)WOTest_stringValue
1229 if ([self WOTest_isCharacterString] || [self WOTest_isConstantCharacterString])
1230 return [NSString stringWithUTF8String:(const char *)[self pointerValue]];
1231 else // see if this is a char array
1233 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
1234 unichar startMarker, flag, endMarker;
1236 if ([scanner WOTest_scanCharacter:&startMarker] &&
1237 (startMarker == _C_ARY_B) && [scanner scanInt:&count] &&
1238 [scanner WOTest_scanCharacter:&flag] && (flag == _C_CHR) &&
1239 [scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_ARY_E) &&
1245 char *buffer = malloc(count * sizeof(char));
1246 NSAssert1(buffer != NULL, @"malloc() failed (size %d)",
1247 (count * sizeof(char)));
1248 [self getValue:buffer];
1250 // confirm that this is a null-terminated string
1251 for (int i = 0; i < count; i++)
1254 return [NSString stringWithUTF8String:buffer];
1268 #pragma mark Low-level test methods
1270 /* Unfortunately there is a lot of very similar code repeated across these methods but it seems to be a necessary evil (600 lines of necessary evil). Firstly, it's necessary to explicitly declare the type of the right-hand value of the comparison. There are lots of permuations for implicit casts, explicit casts (and warnings), and GCC seems to warn about signed to unsigned comparisons differently depending on the types. */
1271 - (NSComparisonResult)WOTest_compareWithChar:(char)other
1273 if ([self WOTest_isChar]) // (also BOOL)
1274 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // no cast
1275 else if ([self WOTest_isInt])
1276 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1277 else if ([self WOTest_isShort])
1278 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1279 else if ([self WOTest_isLong])
1280 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1281 else if ([self WOTest_isLongLong])
1282 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1283 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1285 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1286 else if ([self WOTest_isUnsignedInt])
1288 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1289 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned char)other); // explicit cast
1291 else if ([self WOTest_isUnsignedShort])
1292 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1293 else if ([self WOTest_isUnsignedLong])
1295 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1296 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned char)other); // explicit cast
1298 else if ([self WOTest_isUnsignedLongLong])
1300 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1302 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned char)other);
1304 else if ([self WOTest_isFloat])
1305 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1306 else if ([self WOTest_isDouble])
1307 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1308 else if ([self WOTest_isC99Bool])
1309 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1312 [NSException raise:NSInvalidArgumentException
1313 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1315 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1318 - (NSComparisonResult)WOTest_compareWithInt:(int)other
1320 if ([self WOTest_isChar]) // (also BOOL)
1321 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1322 else if ([self WOTest_isInt])
1323 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // no cast
1324 else if ([self WOTest_isShort])
1325 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1326 else if ([self WOTest_isLong])
1327 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1328 else if ([self WOTest_isLongLong])
1329 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1330 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1332 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1333 else if ([self WOTest_isUnsignedInt])
1335 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1336 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned int)other); // explicit cast
1338 else if ([self WOTest_isUnsignedShort])
1339 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1340 else if ([self WOTest_isUnsignedLong])
1342 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1343 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned int)other); // explicit cast
1345 else if ([self WOTest_isUnsignedLongLong])
1347 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1348 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned int)other); // explicit cast
1350 else if ([self WOTest_isFloat])
1351 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1352 else if ([self WOTest_isDouble])
1353 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1354 else if ([self WOTest_isC99Bool])
1355 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1358 [NSException raise:NSInvalidArgumentException
1359 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1361 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1364 - (NSComparisonResult)WOTest_compareWithShort:(short)other
1366 if ([self WOTest_isChar]) // (also BOOL)
1367 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1368 else if ([self WOTest_isInt])
1369 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1370 else if ([self WOTest_isShort])
1371 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // no cast
1372 else if ([self WOTest_isLong])
1373 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1374 else if ([self WOTest_isLongLong])
1375 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1376 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1378 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1379 else if ([self WOTest_isUnsignedInt])
1381 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1382 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned short)other); // explicit cast
1384 else if ([self WOTest_isUnsignedShort])
1385 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1386 else if ([self WOTest_isUnsignedLong])
1388 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1389 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned short)other); // explicit cast
1391 else if ([self WOTest_isUnsignedLongLong])
1393 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1394 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned short)other); // explicit cast
1396 else if ([self WOTest_isFloat])
1397 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1398 else if ([self WOTest_isDouble])
1399 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1400 else if ([self WOTest_isC99Bool])
1401 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1404 [NSException raise:NSInvalidArgumentException
1405 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1407 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1410 - (NSComparisonResult)WOTest_compareWithLong:(long)other
1412 if ([self WOTest_isChar]) // (also BOOL)
1413 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1414 else if ([self WOTest_isInt])
1415 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1416 else if ([self WOTest_isShort])
1417 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1418 else if ([self WOTest_isLong])
1419 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // no cast
1420 else if ([self WOTest_isLongLong])
1421 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1422 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1424 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1425 else if ([self WOTest_isUnsignedInt])
1427 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1428 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned long)other); // explicit cast
1430 else if ([self WOTest_isUnsignedShort])
1431 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1432 else if ([self WOTest_isUnsignedLong])
1434 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1435 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned long)other); // explicit cast
1437 else if ([self WOTest_isUnsignedLongLong])
1439 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1441 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned long)other);
1443 else if ([self WOTest_isFloat])
1444 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1445 else if ([self WOTest_isDouble])
1446 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1447 else if ([self WOTest_isC99Bool])
1448 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1451 [NSException raise:NSInvalidArgumentException
1452 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1454 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1457 - (NSComparisonResult)WOTest_compareWithLongLong:(long long)other
1459 if ([self WOTest_isChar]) // (also BOOL)
1460 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1461 else if ([self WOTest_isInt])
1462 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1463 else if ([self WOTest_isShort])
1464 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1465 else if ([self WOTest_isLong])
1466 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1467 else if ([self WOTest_isLongLong])
1468 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // no cast
1469 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1470 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1471 else if ([self WOTest_isUnsignedInt])
1472 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1473 else if ([self WOTest_isUnsignedShort])
1474 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1475 else if ([self WOTest_isUnsignedLong])
1476 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1477 else if ([self WOTest_isUnsignedLongLong])
1479 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1480 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned long long)other); // explicit cast
1482 else if ([self WOTest_isFloat])
1483 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1484 else if ([self WOTest_isDouble])
1485 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1486 else if ([self WOTest_isC99Bool])
1487 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1490 [NSException raise:NSInvalidArgumentException
1491 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1493 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1496 - (NSComparisonResult)WOTest_compareWithUnsignedChar:(unsigned char)other
1498 if ([self WOTest_isChar]) // (also BOOL)
1499 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1500 else if ([self WOTest_isInt])
1501 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1502 else if ([self WOTest_isShort])
1503 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1504 else if ([self WOTest_isLong])
1505 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1506 else if ([self WOTest_isLongLong])
1507 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1508 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1509 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // no cast
1510 else if ([self WOTest_isUnsignedInt])
1511 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1512 else if ([self WOTest_isUnsignedShort])
1513 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1514 else if ([self WOTest_isUnsignedLong])
1515 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1516 else if ([self WOTest_isUnsignedLongLong])
1517 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1518 else if ([self WOTest_isFloat])
1519 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1520 else if ([self WOTest_isDouble])
1521 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1522 else if ([self WOTest_isC99Bool])
1523 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1526 [NSException raise:NSInvalidArgumentException
1527 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1529 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1532 - (NSComparisonResult)WOTest_compareWithUnsignedInt:(unsigned int)other
1534 if ([self WOTest_isChar]) // (also BOOL)
1536 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1537 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // explicit cast
1539 else if ([self WOTest_isInt])
1541 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1542 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1544 else if ([self WOTest_isShort])
1546 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1547 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1549 else if ([self WOTest_isLong])
1551 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1552 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1554 else if ([self WOTest_isLongLong])
1555 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1556 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1557 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1558 else if ([self WOTest_isUnsignedInt])
1559 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // no cast
1560 else if ([self WOTest_isUnsignedShort])
1561 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1562 else if ([self WOTest_isUnsignedLong])
1563 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1564 else if ([self WOTest_isUnsignedLongLong])
1565 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1566 else if ([self WOTest_isFloat])
1567 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1568 else if ([self WOTest_isDouble])
1569 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1570 else if ([self WOTest_isC99Bool])
1571 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1574 [NSException raise:NSInvalidArgumentException
1575 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1577 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1580 - (NSComparisonResult)WOTest_compareWithUnsignedShort:(unsigned short)other
1582 if ([self WOTest_isChar]) // (also BOOL)
1583 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1584 else if ([self WOTest_isInt])
1585 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1586 else if ([self WOTest_isShort])
1587 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1588 else if ([self WOTest_isLong])
1589 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1590 else if ([self WOTest_isLongLong])
1591 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1592 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1593 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1594 else if ([self WOTest_isUnsignedInt])
1595 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1596 else if ([self WOTest_isUnsignedShort])
1597 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // no cast
1598 else if ([self WOTest_isUnsignedLong])
1599 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1600 else if ([self WOTest_isUnsignedLongLong])
1601 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1602 else if ([self WOTest_isFloat])
1603 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1604 else if ([self WOTest_isDouble])
1605 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1606 else if ([self WOTest_isC99Bool])
1607 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1610 [NSException raise:NSInvalidArgumentException
1611 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1613 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1616 - (NSComparisonResult)WOTest_compareWithUnsignedLong:(unsigned long)other
1618 if ([self WOTest_isChar]) // char (also BOOL)
1620 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1621 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // expicit cast
1623 else if ([self WOTest_isInt]) // int
1625 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1626 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1628 else if ([self WOTest_isShort]) // short
1630 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1631 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1633 else if ([self WOTest_isLong]) // long
1635 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1636 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1638 else if ([self WOTest_isLongLong]) // long long
1639 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1640 else if ([self WOTest_isUnsignedChar]) // unsigned char (also Boolean)
1641 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1642 else if ([self WOTest_isUnsignedInt]) // unsigned int
1643 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // implicit cast
1644 else if ([self WOTest_isUnsignedShort]) // unsigned short
1645 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1646 else if ([self WOTest_isUnsignedLong]) // unsigned long
1647 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // no cast
1648 else if ([self WOTest_isUnsignedLongLong]) // unsigned long long
1649 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1650 else if ([self WOTest_isFloat]) // float
1651 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1652 else if ([self WOTest_isDouble]) // double
1653 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1654 else if ([self WOTest_isC99Bool]) // C99 _Bool
1655 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1658 [NSException raise:NSInvalidArgumentException
1659 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1661 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1664 - (NSComparisonResult)WOTest_compareWithUnsignedLongLong:(unsigned long long)other
1666 if ([self WOTest_isChar]) // (also BOOL)
1668 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1669 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // explicit cast
1671 else if ([self WOTest_isInt])
1673 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1674 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1676 else if ([self WOTest_isShort])
1678 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1679 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1681 else if ([self WOTest_isLong])
1683 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1684 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1686 else if ([self WOTest_isLongLong])
1688 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1689 return WO_COMPARE_SCALARS((unsigned long long)[self WOTest_longLongValue], other); // explicit cast
1691 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1692 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1693 else if ([self WOTest_isUnsignedInt])
1694 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // implicit cast
1695 else if ([self WOTest_isUnsignedShort])
1696 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1697 else if ([self WOTest_isUnsignedLong])
1698 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1699 else if ([self WOTest_isUnsignedLongLong])
1700 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // no cast
1701 else if ([self WOTest_isFloat])
1702 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1703 else if ([self WOTest_isDouble])
1704 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1705 else if ([self WOTest_isC99Bool])
1706 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1709 [NSException raise:NSInvalidArgumentException
1710 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1712 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1715 - (NSComparisonResult)WOTest_compareWithFloat:(float)other
1717 if ([self WOTest_isChar]) // (also BOOL)
1718 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1719 else if ([self WOTest_isInt])
1720 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1721 else if ([self WOTest_isShort])
1722 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1723 else if ([self WOTest_isLong])
1724 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1725 else if ([self WOTest_isLongLong])
1726 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1727 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1728 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1729 else if ([self WOTest_isUnsignedInt])
1730 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1731 else if ([self WOTest_isUnsignedShort])
1732 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1733 else if ([self WOTest_isUnsignedLong])
1734 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1735 else if ([self WOTest_isUnsignedLongLong])
1736 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1737 else if ([self WOTest_isFloat])
1738 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // no cast
1739 else if ([self WOTest_isDouble])
1740 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1741 else if ([self WOTest_isC99Bool])
1742 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1745 [NSException raise:NSInvalidArgumentException
1746 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1748 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1751 - (NSComparisonResult)WOTest_compareWithDouble:(double)other
1753 if ([self WOTest_isChar]) // (also BOOL)
1754 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1755 else if ([self WOTest_isInt])
1756 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1757 else if ([self WOTest_isShort])
1758 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1759 else if ([self WOTest_isLong])
1760 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1761 else if ([self WOTest_isLongLong])
1762 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1763 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1764 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1765 else if ([self WOTest_isUnsignedInt])
1766 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1767 else if ([self WOTest_isUnsignedShort])
1768 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1769 else if ([self WOTest_isUnsignedLong])
1770 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1771 else if ([self WOTest_isUnsignedLongLong])
1772 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1773 else if ([self WOTest_isFloat])
1774 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1775 else if ([self WOTest_isDouble])
1776 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // no cast
1777 else if ([self WOTest_isC99Bool])
1778 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1781 [NSException raise:NSInvalidArgumentException
1782 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1784 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1787 - (NSComparisonResult)WOTest_compareWithC99Bool:(_Bool)other
1789 if ([self WOTest_isChar]) // (also BOOL)
1790 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1791 else if ([self WOTest_isInt])
1792 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1793 else if ([self WOTest_isShort])
1794 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1795 else if ([self WOTest_isLong])
1796 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1797 else if ([self WOTest_isLongLong])
1798 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1799 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1800 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1801 else if ([self WOTest_isUnsignedInt])
1802 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1803 else if ([self WOTest_isUnsignedShort])
1804 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1805 else if ([self WOTest_isUnsignedLong])
1806 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1807 else if ([self WOTest_isUnsignedLongLong])
1808 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1809 else if ([self WOTest_isFloat])
1810 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1811 else if ([self WOTest_isDouble])
1812 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1813 else if ([self WOTest_isC99Bool])
1814 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // no cast
1817 [NSException raise:NSInvalidArgumentException
1818 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1820 return NSOrderedSame; // never reached, but necessary to suppress compiler warning