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 // pointer-to-void case
759 if ([self WOTest_isPointerToVoid] && [aValue WOTest_isPointerToVoid])
761 // test conservatively here: equal pointers are considered equal;
762 // all others fall through and an exception is raised
763 if ([self pointerValue] == [aValue pointerValue])
764 return NSOrderedSame;
767 // numeric scalar case
768 if ([self WOTest_isNumericScalar] && [aValue WOTest_isNumericScalar])
770 if ([aValue WOTest_isChar])
771 return [self WOTest_compareWithChar:[aValue WOTest_charValue]];
772 else if ([aValue WOTest_isInt])
773 return [self WOTest_compareWithInt:[aValue WOTest_intValue]];
774 else if ([aValue WOTest_isShort])
775 return [self WOTest_compareWithShort:[aValue WOTest_shortValue]];
776 else if ([aValue WOTest_isLong])
777 return [self WOTest_compareWithLong:[aValue WOTest_longValue]];
778 else if ([aValue WOTest_isLongLong])
779 return [self WOTest_compareWithLongLong:[aValue WOTest_longLongValue]];
780 else if ([aValue WOTest_isUnsignedChar])
781 return [self WOTest_compareWithUnsignedChar:[aValue WOTest_unsignedCharValue]];
782 else if ([aValue WOTest_isUnsignedInt])
783 return [self WOTest_compareWithUnsignedInt:[aValue WOTest_unsignedIntValue]];
784 else if ([aValue WOTest_isUnsignedShort])
785 return [self WOTest_compareWithUnsignedShort:[aValue WOTest_unsignedShortValue]];
786 else if ([aValue WOTest_isUnsignedLong])
787 return [self WOTest_compareWithUnsignedLong:[aValue WOTest_unsignedLongValue]];
788 else if ([aValue WOTest_isUnsignedLongLong])
789 return [self WOTest_compareWithUnsignedLongLong:
790 [aValue WOTest_unsignedLongLongValue]];
791 else if ([aValue WOTest_isFloat])
792 return [self WOTest_compareWithFloat:[aValue WOTest_floatValue]];
793 else if ([aValue WOTest_isDouble])
794 return [self WOTest_compareWithDouble:[aValue WOTest_doubleValue]];
795 else if ([aValue WOTest_isC99Bool])
796 return [self WOTest_compareWithC99Bool:[aValue WOTest_C99BoolValue]];
799 [NSException raise:NSInvalidArgumentException format:@"non-numeric value(s) passed"];
801 // never reached, but necessary to suppress compiler warning
802 return NSOrderedSame;
806 #pragma mark Utility methods
808 - (size_t)WOTest_bufferSize
810 return [[self class] WOTest_sizeForType:[self WOTest_objCTypeString]];
813 - (void)WOTest_printSignCompareWarning:(NSString *)warning
815 NSParameterAssert(warning != nil);
817 // this conditional in here so that the warnings can be turned off in WOTest self-testing
818 if ([[WOTest sharedInstance] warnsAboutSignComparisons])
820 [[WOTest sharedInstance] writeWarning:warning];
821 [[WOTest sharedInstance] writeLastKnownLocation];
826 #pragma mark Convenience methods
828 /*! Returns the Objective-C type of the receiver as an NSString. */
829 - (NSString *)WOTest_objCTypeString
831 return [NSString stringWithUTF8String:[self objCType]];
834 - (NSString *)WOTest_description
836 // these special handlings exist because NSValue's description is not very human-friendly
837 // it gets even worse when running on Intel: for example, an integer like 500,000 (0x0007a120 hex) is displayed as "<20a10700>"
838 if ([self WOTest_isObject])
840 // look for objects that are either (NSString objects) or objects that respond to "description"
841 id valueContents = [self WOTest_objectValue];
844 // for NSString objects: just return content
845 if ([NSObject WOTest_object:valueContents isKindOfClass:[NSString class]])
846 return valueContents;
847 else if ([NSObject WOTest_object:valueContents respondsToSelector:@selector(description)] &&
848 [NSObject WOTest_isIdReturnType:[NSObject WOTest_returnTypeForObject:valueContents
849 selector:@selector(description)]])
851 NSString *description = objc_msgSend(valueContents, @selector(description));
852 if (description && [NSObject WOTest_object:description isKindOfClass:[NSString class]])
857 // TODO: write unit tests to confirm that NSString supports all of these printf format markers and modifiers
858 else if ([self WOTest_isChar])
860 char character = [self WOTest_charValue];
861 if (character == 32) // the space character
863 else if ((character >= 33) && (character <= 126)) // other printable characters printed as an ASCII char
864 return [NSString stringWithFormat:@"'%C'", (unichar)character];
866 return [NSString stringWithFormat:@"(char)%hhd", character]; // all others printed as signed numbers
868 else if ([self WOTest_isInt])
869 return [NSString stringWithFormat:@"(int)%d", [self WOTest_intValue]];
870 else if ([self WOTest_isShort])
871 return [NSString stringWithFormat:@"(short)%hi", [self WOTest_shortValue]];
872 else if ([self WOTest_isLong])
873 return [NSString stringWithFormat:@"(long)%ld", [self WOTest_longValue]];
874 else if ([self WOTest_isLongLong])
875 return [NSString stringWithFormat:@"(long long)%lld", [self WOTest_longLongValue]];
876 else if ([self WOTest_isUnsignedChar])
878 unsigned char character = [self WOTest_unsignedCharValue];
879 if (character == 32) // the space character
881 else if ((character >= 33) && (character <= 126)) // other printable characters printed as an ASCII char
882 return [NSString stringWithFormat:@"%C", (unichar)character];
884 // all others printed as unsigned numbers
885 return [NSString stringWithFormat:@"(unsigned char)%hhu", [self WOTest_unsignedCharValue]];
887 else if ([self WOTest_isUnsignedInt])
888 return [NSString stringWithFormat:@"(unsigned int)%u", [self WOTest_unsignedIntValue]];
889 else if ([self WOTest_isUnsignedShort])
890 return [NSString stringWithFormat:@"(unsigned short)%hu", [self WOTest_unsignedShortValue]];
891 else if ([self WOTest_isUnsignedLong])
892 return [NSString stringWithFormat:@"(unsigned long)%lu", [self WOTest_unsignedLongValue]];
893 else if ([self WOTest_isUnsignedLongLong])
894 return [NSString stringWithFormat:@"(unsigned long long)%llu", [self WOTest_unsignedLongLongValue]];
895 else if ([self WOTest_isFloat])
896 return [NSString stringWithFormat:@"(float)%f", [self WOTest_floatValue]];
897 else if ([self WOTest_isDouble])
898 return [NSString stringWithFormat:@"(double)%f", [self WOTest_doubleValue]];
899 else if ([self WOTest_isC99Bool])
900 return [NSString stringWithFormat:@"(_Bool)%@", [self WOTest_C99BoolValue] ? @"true" : @"false"];
901 else if ([self WOTest_isVoid])
903 else if ([self WOTest_isConstantCharacterString])
904 return [NSString stringWithFormat:@"\"%s\"", [self WOTest_constantCharacterStringValue]];
905 else if ([self WOTest_isCharacterString])
906 return [NSString stringWithFormat:@"\"%s\"", [self WOTest_characterStringValue]];
907 else if ([self WOTest_isClass])
908 return [NSString stringWithFormat:@"(Class)%@", NSStringFromClass([self WOTest_classValue])];
909 else if ([self WOTest_isSelector])
910 return [NSString stringWithFormat:@"(SEL)%@", NSStringFromSelector([self WOTest_selectorValue])];
911 else if ([self WOTest_isPointerToVoid])
912 return [NSString stringWithFormat:@"(void *)%#08x", [self WOTest_pointerToVoidValue]];
913 return [self description]; // fallback case
917 #pragma mark Identifying generic types
919 - (BOOL)WOTest_isNumericScalar
921 return ([self WOTest_isChar] || [self WOTest_isInt] ||
922 [self WOTest_isShort] || [self WOTest_isLong] ||
923 [self WOTest_isLongLong] || [self WOTest_isUnsignedChar] ||
924 [self WOTest_isUnsignedInt] || [self WOTest_isUnsignedShort] ||
925 [self WOTest_isUnsignedLong] || [self WOTest_isUnsignedLongLong] ||
926 [self WOTest_isFloat] || [self WOTest_isDouble] ||
927 [self WOTest_isC99Bool]);
930 - (BOOL)WOTest_isPointer
932 return [[self class] WOTest_typeIsPointer:[self WOTest_objCTypeString]];
935 - (BOOL)WOTest_isArray
937 return [[self class] WOTest_typeIsArray:[self WOTest_objCTypeString]];
940 - (unsigned)WOTest_arrayCount
942 NSAssert([self WOTest_isArray],
943 @"WOTest_arrayCount sent but receiver does not contain an array");
944 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
948 // attempt the scan: it should work
949 if (!([scanner WOTest_scanCharacter:&startMarker] && (startMarker == _C_ARY_B) && [scanner scanInt:&count]))
950 [NSException raise:NSInternalInconsistencyException format:@"scanner error in WOTest_arrayCount"];
952 return (unsigned)count;
955 - (NSString *)WOTest_arrayType
957 NSAssert([self WOTest_isArray], @"WOTest_arrayType sent but receiver does not contain an array");
958 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
959 [scanner setScanLocation:1];
960 NSString *typeString;
961 if (!([scanner scanInt:nil] && [scanner WOTest_scanTypeIntoString:&typeString]))
962 [NSException raise:NSInternalInconsistencyException format:@"scanner error in WOTest_arrayType"];
966 - (BOOL)WOTest_isStruct
968 return [[self class] WOTest_typeIsStruct:[self WOTest_objCTypeString]];
971 - (BOOL)WOTest_isUnion
973 return [[self class] WOTest_typeIsUnion:[self WOTest_objCTypeString]];
976 - (BOOL)WOTest_isBitfield
978 return [[self class] WOTest_typeIsBitfield:[self WOTest_objCTypeString]];
981 - (BOOL)WOTest_isUnknown
983 return [[self class] WOTest_typeIsUnknown:[self WOTest_objCTypeString]];
987 #pragma mark Identifying and retrieving specific types
989 - (BOOL)WOTest_isChar
991 return [[self class] WOTest_typeIsChar:[self WOTest_objCTypeString]];
996 return [[self class] WOTest_typeIsInt:[self WOTest_objCTypeString]];
999 - (BOOL)WOTest_isShort
1001 return [[self class] WOTest_typeIsShort:[self WOTest_objCTypeString]];
1004 - (BOOL)WOTest_isLong
1006 return [[self class] WOTest_typeIsLong:[self WOTest_objCTypeString]];
1009 - (BOOL)WOTest_isLongLong
1011 return [[self class] WOTest_typeIsLongLong:[self WOTest_objCTypeString]];
1014 - (BOOL)WOTest_isUnsignedChar
1016 return [[self class] WOTest_typeIsUnsignedChar:[self WOTest_objCTypeString]];
1019 - (BOOL)WOTest_isUnsignedInt
1021 return [[self class] WOTest_typeIsUnsignedInt:[self WOTest_objCTypeString]];
1024 - (BOOL)WOTest_isUnsignedShort
1026 return [[self class] WOTest_typeIsUnsignedShort:[self WOTest_objCTypeString]];
1029 - (BOOL)WOTest_isUnsignedLong
1031 return [[self class] WOTest_typeIsUnsignedLong:[self WOTest_objCTypeString]];
1034 - (BOOL)WOTest_isUnsignedLongLong
1036 return [[self class] WOTest_typeIsUnsignedLongLong:[self WOTest_objCTypeString]];
1039 - (BOOL)WOTest_isFloat
1041 return [[self class] WOTest_typeIsFloat:[self WOTest_objCTypeString]];
1044 - (BOOL)WOTest_isDouble
1046 return [[self class] WOTest_typeIsDouble:[self WOTest_objCTypeString]];
1049 - (BOOL)WOTest_isC99Bool
1051 return [[self class] WOTest_typeIsC99Bool:[self WOTest_objCTypeString]];
1054 - (BOOL)WOTest_isVoid
1056 return [[self class] WOTest_typeIsVoid:[self WOTest_objCTypeString]];
1059 - (BOOL)WOTest_isConstantCharacterString
1061 return [[self class] WOTest_typeIsConstantCharacterString:[self WOTest_objCTypeString]];
1064 - (BOOL)WOTest_isCharacterString
1066 return [[self class] WOTest_typeIsCharacterString:[self WOTest_objCTypeString]];
1069 - (BOOL)WOTest_isObject
1071 return [[self class] WOTest_typeIsObject:[self WOTest_objCTypeString]];
1074 - (BOOL)WOTest_isClass
1076 return [[self class] WOTest_typeIsClass:[self WOTest_objCTypeString]];
1079 - (BOOL)WOTest_isSelector
1081 return [[self class] WOTest_typeIsSelector:[self WOTest_objCTypeString]];
1084 - (BOOL)WOTest_isPointerToVoid
1086 return [[self class] WOTest_typeIsPointerToVoid:[self WOTest_objCTypeString]];
1089 - (char)WOTest_charValue
1092 [self getValue:&value];
1096 - (int)WOTest_intValue
1099 [self getValue:&value];
1103 - (short)WOTest_shortValue
1106 [self getValue:&value];
1110 - (long)WOTest_longValue
1113 [self getValue:&value];
1117 - (long long)WOTest_longLongValue
1120 [self getValue:&value];
1124 - (unsigned char)WOTest_unsignedCharValue
1126 unsigned char value;
1127 [self getValue:&value];
1131 - (unsigned int)WOTest_unsignedIntValue
1134 [self getValue:&value];
1138 - (unsigned short)WOTest_unsignedShortValue
1140 unsigned short value;
1141 [self getValue:&value];
1145 - (unsigned long)WOTest_unsignedLongValue
1147 unsigned long value;
1148 [self getValue:&value];
1152 - (unsigned long long)WOTest_unsignedLongLongValue
1154 unsigned long long value;
1155 [self getValue:&value];
1159 - (float)WOTest_floatValue
1162 [self getValue:&value];
1166 - (double)WOTest_doubleValue
1169 [self getValue:&value];
1173 - (_Bool)WOTest_C99BoolValue
1176 [self getValue:&value];
1180 - (const char *)WOTest_constantCharacterStringValue
1183 [self getValue:&value];
1187 - (char *)WOTest_characterStringValue
1190 [self getValue:&value];
1194 - (id)WOTest_objectValue
1197 [self getValue:&value];
1201 - (Class)WOTest_classValue
1204 [self getValue:&value];
1208 - (SEL)WOTest_selectorValue
1211 [self getValue:&value];
1215 - (void *)WOTest_pointerToVoidValue
1218 [self getValue:&value];
1222 - (BOOL)WOTest_isCharArray
1224 // look for string of form "[4c]"
1225 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
1226 unichar startMarker, flag, endMarker;
1228 return ([scanner WOTest_scanCharacter:&startMarker] && (startMarker == _C_ARY_B) &&
1229 [scanner scanInt:&count] &&
1230 [scanner WOTest_scanCharacter:&flag] && (flag == _C_CHR) &&
1231 [scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_ARY_E) &&
1235 - (NSString *)WOTest_stringValue
1238 if ([self WOTest_isCharacterString] || [self WOTest_isConstantCharacterString])
1239 return [NSString stringWithUTF8String:(const char *)[self pointerValue]];
1240 else // see if this is a char array
1242 NSScanner *scanner = [NSScanner scannerWithString:[self WOTest_objCTypeString]];
1243 unichar startMarker, flag, endMarker;
1245 if ([scanner WOTest_scanCharacter:&startMarker] &&
1246 (startMarker == _C_ARY_B) && [scanner scanInt:&count] &&
1247 [scanner WOTest_scanCharacter:&flag] && (flag == _C_CHR) &&
1248 [scanner WOTest_scanCharacter:&endMarker] && (endMarker == _C_ARY_E) &&
1254 char *buffer = malloc(count * sizeof(char));
1255 NSAssert1(buffer != NULL, @"malloc() failed (size %d)",
1256 (count * sizeof(char)));
1257 [self getValue:buffer];
1259 // confirm that this is a null-terminated string
1260 for (int i = 0; i < count; i++)
1263 return [NSString stringWithUTF8String:buffer];
1277 #pragma mark Low-level test methods
1279 /* 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. */
1280 - (NSComparisonResult)WOTest_compareWithChar:(char)other
1282 if ([self WOTest_isChar]) // (also BOOL)
1283 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // no cast
1284 else if ([self WOTest_isInt])
1285 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1286 else if ([self WOTest_isShort])
1287 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1288 else if ([self WOTest_isLong])
1289 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1290 else if ([self WOTest_isLongLong])
1291 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1292 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1294 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1295 else if ([self WOTest_isUnsignedInt])
1297 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1298 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned char)other); // explicit cast
1300 else if ([self WOTest_isUnsignedShort])
1301 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1302 else if ([self WOTest_isUnsignedLong])
1304 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1305 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned char)other); // explicit cast
1307 else if ([self WOTest_isUnsignedLongLong])
1309 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1311 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned char)other);
1313 else if ([self WOTest_isFloat])
1314 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1315 else if ([self WOTest_isDouble])
1316 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1317 else if ([self WOTest_isC99Bool])
1318 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1321 [NSException raise:NSInvalidArgumentException
1322 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1324 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1327 - (NSComparisonResult)WOTest_compareWithInt:(int)other
1329 if ([self WOTest_isChar]) // (also BOOL)
1330 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1331 else if ([self WOTest_isInt])
1332 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // no cast
1333 else if ([self WOTest_isShort])
1334 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1335 else if ([self WOTest_isLong])
1336 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1337 else if ([self WOTest_isLongLong])
1338 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1339 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1341 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1342 else if ([self WOTest_isUnsignedInt])
1344 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1345 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned int)other); // explicit cast
1347 else if ([self WOTest_isUnsignedShort])
1348 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1349 else if ([self WOTest_isUnsignedLong])
1351 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1352 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned int)other); // explicit cast
1354 else if ([self WOTest_isUnsignedLongLong])
1356 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1357 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned int)other); // explicit cast
1359 else if ([self WOTest_isFloat])
1360 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1361 else if ([self WOTest_isDouble])
1362 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1363 else if ([self WOTest_isC99Bool])
1364 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1367 [NSException raise:NSInvalidArgumentException
1368 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1370 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1373 - (NSComparisonResult)WOTest_compareWithShort:(short)other
1375 if ([self WOTest_isChar]) // (also BOOL)
1376 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1377 else if ([self WOTest_isInt])
1378 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1379 else if ([self WOTest_isShort])
1380 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // no cast
1381 else if ([self WOTest_isLong])
1382 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1383 else if ([self WOTest_isLongLong])
1384 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1385 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1387 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1388 else if ([self WOTest_isUnsignedInt])
1390 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1391 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned short)other); // explicit cast
1393 else if ([self WOTest_isUnsignedShort])
1394 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1395 else if ([self WOTest_isUnsignedLong])
1397 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1398 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned short)other); // explicit cast
1400 else if ([self WOTest_isUnsignedLongLong])
1402 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1403 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned short)other); // explicit cast
1405 else if ([self WOTest_isFloat])
1406 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1407 else if ([self WOTest_isDouble])
1408 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1409 else if ([self WOTest_isC99Bool])
1410 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1413 [NSException raise:NSInvalidArgumentException
1414 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1416 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1419 - (NSComparisonResult)WOTest_compareWithLong:(long)other
1421 if ([self WOTest_isChar]) // (also BOOL)
1422 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1423 else if ([self WOTest_isInt])
1424 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1425 else if ([self WOTest_isShort])
1426 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1427 else if ([self WOTest_isLong])
1428 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // no cast
1429 else if ([self WOTest_isLongLong])
1430 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1431 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1433 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other);
1434 else if ([self WOTest_isUnsignedInt])
1436 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1437 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], (unsigned long)other); // explicit cast
1439 else if ([self WOTest_isUnsignedShort])
1440 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1441 else if ([self WOTest_isUnsignedLong])
1443 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1444 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], (unsigned long)other); // explicit cast
1446 else if ([self WOTest_isUnsignedLongLong])
1448 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1450 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned long)other);
1452 else if ([self WOTest_isFloat])
1453 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1454 else if ([self WOTest_isDouble])
1455 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1456 else if ([self WOTest_isC99Bool])
1457 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1460 [NSException raise:NSInvalidArgumentException
1461 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1463 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1466 - (NSComparisonResult)WOTest_compareWithLongLong:(long long)other
1468 if ([self WOTest_isChar]) // (also BOOL)
1469 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1470 else if ([self WOTest_isInt])
1471 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1472 else if ([self WOTest_isShort])
1473 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1474 else if ([self WOTest_isLong])
1475 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1476 else if ([self WOTest_isLongLong])
1477 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // no cast
1478 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1479 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1480 else if ([self WOTest_isUnsignedInt])
1481 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1482 else if ([self WOTest_isUnsignedShort])
1483 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1484 else if ([self WOTest_isUnsignedLong])
1485 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1486 else if ([self WOTest_isUnsignedLongLong])
1488 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1489 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], (unsigned long long)other); // explicit cast
1491 else if ([self WOTest_isFloat])
1492 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1493 else if ([self WOTest_isDouble])
1494 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1495 else if ([self WOTest_isC99Bool])
1496 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1499 [NSException raise:NSInvalidArgumentException
1500 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1502 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1505 - (NSComparisonResult)WOTest_compareWithUnsignedChar:(unsigned char)other
1507 if ([self WOTest_isChar]) // (also BOOL)
1508 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1509 else if ([self WOTest_isInt])
1510 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1511 else if ([self WOTest_isShort])
1512 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1513 else if ([self WOTest_isLong])
1514 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1515 else if ([self WOTest_isLongLong])
1516 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1517 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1518 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // no cast
1519 else if ([self WOTest_isUnsignedInt])
1520 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1521 else if ([self WOTest_isUnsignedShort])
1522 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1523 else if ([self WOTest_isUnsignedLong])
1524 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1525 else if ([self WOTest_isUnsignedLongLong])
1526 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1527 else if ([self WOTest_isFloat])
1528 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1529 else if ([self WOTest_isDouble])
1530 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1531 else if ([self WOTest_isC99Bool])
1532 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1535 [NSException raise:NSInvalidArgumentException
1536 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1538 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1541 - (NSComparisonResult)WOTest_compareWithUnsignedInt:(unsigned int)other
1543 if ([self WOTest_isChar]) // (also BOOL)
1545 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1546 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // explicit cast
1548 else if ([self WOTest_isInt])
1550 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1551 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1553 else if ([self WOTest_isShort])
1555 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1556 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1558 else if ([self WOTest_isLong])
1560 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1561 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1563 else if ([self WOTest_isLongLong])
1564 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1565 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1566 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1567 else if ([self WOTest_isUnsignedInt])
1568 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // no cast
1569 else if ([self WOTest_isUnsignedShort])
1570 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1571 else if ([self WOTest_isUnsignedLong])
1572 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1573 else if ([self WOTest_isUnsignedLongLong])
1574 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1575 else if ([self WOTest_isFloat])
1576 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1577 else if ([self WOTest_isDouble])
1578 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1579 else if ([self WOTest_isC99Bool])
1580 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1583 [NSException raise:NSInvalidArgumentException
1584 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1586 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1589 - (NSComparisonResult)WOTest_compareWithUnsignedShort:(unsigned short)other
1591 if ([self WOTest_isChar]) // (also BOOL)
1592 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1593 else if ([self WOTest_isInt])
1594 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1595 else if ([self WOTest_isShort])
1596 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1597 else if ([self WOTest_isLong])
1598 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1599 else if ([self WOTest_isLongLong])
1600 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1601 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1602 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1603 else if ([self WOTest_isUnsignedInt])
1604 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1605 else if ([self WOTest_isUnsignedShort])
1606 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // no cast
1607 else if ([self WOTest_isUnsignedLong])
1608 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1609 else if ([self WOTest_isUnsignedLongLong])
1610 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1611 else if ([self WOTest_isFloat])
1612 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1613 else if ([self WOTest_isDouble])
1614 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1615 else if ([self WOTest_isC99Bool])
1616 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1619 [NSException raise:NSInvalidArgumentException
1620 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1622 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1625 - (NSComparisonResult)WOTest_compareWithUnsignedLong:(unsigned long)other
1627 if ([self WOTest_isChar]) // char (also BOOL)
1629 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1630 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // expicit cast
1632 else if ([self WOTest_isInt]) // int
1634 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1635 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1637 else if ([self WOTest_isShort]) // short
1639 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1640 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1642 else if ([self WOTest_isLong]) // long
1644 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1645 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1647 else if ([self WOTest_isLongLong]) // long long
1648 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1649 else if ([self WOTest_isUnsignedChar]) // unsigned char (also Boolean)
1650 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1651 else if ([self WOTest_isUnsignedInt]) // unsigned int
1652 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // implicit cast
1653 else if ([self WOTest_isUnsignedShort]) // unsigned short
1654 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1655 else if ([self WOTest_isUnsignedLong]) // unsigned long
1656 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // no cast
1657 else if ([self WOTest_isUnsignedLongLong]) // unsigned long long
1658 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1659 else if ([self WOTest_isFloat]) // float
1660 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1661 else if ([self WOTest_isDouble]) // double
1662 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1663 else if ([self WOTest_isC99Bool]) // C99 _Bool
1664 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1667 [NSException raise:NSInvalidArgumentException
1668 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1670 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1673 - (NSComparisonResult)WOTest_compareWithUnsignedLongLong:(unsigned long long)other
1675 if ([self WOTest_isChar]) // (also BOOL)
1677 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1678 return WO_COMPARE_SCALARS((unsigned char)[self WOTest_charValue], other); // explicit cast
1680 else if ([self WOTest_isInt])
1682 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1683 return WO_COMPARE_SCALARS((unsigned int)[self WOTest_intValue], other); // explicit cast
1685 else if ([self WOTest_isShort])
1687 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1688 return WO_COMPARE_SCALARS((unsigned short)[self WOTest_shortValue], other); // explicit cast
1690 else if ([self WOTest_isLong])
1692 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1693 return WO_COMPARE_SCALARS((unsigned long)[self WOTest_longValue], other); // explicit cast
1695 else if ([self WOTest_isLongLong])
1697 [self WOTest_printSignCompareWarning:@"comparison between signed and unsigned, to avoid this warning use an explicit cast"];
1698 return WO_COMPARE_SCALARS((unsigned long long)[self WOTest_longLongValue], other); // explicit cast
1700 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1701 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1702 else if ([self WOTest_isUnsignedInt])
1703 return WO_COMPARE_SCALARS([self WOTest_unsignedIntValue], other); // implicit cast
1704 else if ([self WOTest_isUnsignedShort])
1705 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1706 else if ([self WOTest_isUnsignedLong])
1707 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1708 else if ([self WOTest_isUnsignedLongLong])
1709 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // no cast
1710 else if ([self WOTest_isFloat])
1711 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1712 else if ([self WOTest_isDouble])
1713 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1714 else if ([self WOTest_isC99Bool])
1715 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1718 [NSException raise:NSInvalidArgumentException
1719 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1721 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1724 - (NSComparisonResult)WOTest_compareWithFloat:(float)other
1726 if ([self WOTest_isChar]) // (also BOOL)
1727 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1728 else if ([self WOTest_isInt])
1729 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1730 else if ([self WOTest_isShort])
1731 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1732 else if ([self WOTest_isLong])
1733 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1734 else if ([self WOTest_isLongLong])
1735 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1736 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1737 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1738 else if ([self WOTest_isUnsignedInt])
1739 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1740 else if ([self WOTest_isUnsignedShort])
1741 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1742 else if ([self WOTest_isUnsignedLong])
1743 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1744 else if ([self WOTest_isUnsignedLongLong])
1745 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1746 else if ([self WOTest_isFloat])
1747 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // no cast
1748 else if ([self WOTest_isDouble])
1749 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1750 else if ([self WOTest_isC99Bool])
1751 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1754 [NSException raise:NSInvalidArgumentException
1755 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1757 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1760 - (NSComparisonResult)WOTest_compareWithDouble:(double)other
1762 if ([self WOTest_isChar]) // (also BOOL)
1763 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1764 else if ([self WOTest_isInt])
1765 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1766 else if ([self WOTest_isShort])
1767 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1768 else if ([self WOTest_isLong])
1769 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1770 else if ([self WOTest_isLongLong])
1771 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1772 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1773 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1774 else if ([self WOTest_isUnsignedInt])
1775 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1776 else if ([self WOTest_isUnsignedShort])
1777 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1778 else if ([self WOTest_isUnsignedLong])
1779 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1780 else if ([self WOTest_isUnsignedLongLong])
1781 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1782 else if ([self WOTest_isFloat])
1783 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1784 else if ([self WOTest_isDouble])
1785 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // no cast
1786 else if ([self WOTest_isC99Bool])
1787 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // implicit cast
1790 [NSException raise:NSInvalidArgumentException
1791 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1793 return NSOrderedSame; // never reached, but necessary to suppress compiler warning
1796 - (NSComparisonResult)WOTest_compareWithC99Bool:(_Bool)other
1798 if ([self WOTest_isChar]) // (also BOOL)
1799 return WO_COMPARE_SCALARS([self WOTest_charValue], other); // implicit cast
1800 else if ([self WOTest_isInt])
1801 return WO_COMPARE_SCALARS([self WOTest_intValue], other); // implicit cast
1802 else if ([self WOTest_isShort])
1803 return WO_COMPARE_SCALARS([self WOTest_shortValue], other); // implicit cast
1804 else if ([self WOTest_isLong])
1805 return WO_COMPARE_SCALARS([self WOTest_longValue], other); // implicit cast
1806 else if ([self WOTest_isLongLong])
1807 return WO_COMPARE_SCALARS([self WOTest_longLongValue], other); // implicit cast
1808 else if ([self WOTest_isUnsignedChar]) // (also Boolean)
1809 return WO_COMPARE_SCALARS([self WOTest_unsignedCharValue], other); // implicit cast
1810 else if ([self WOTest_isUnsignedInt])
1811 return WO_COMPARE_SCALARS ([self WOTest_unsignedIntValue], other); // implicit cast
1812 else if ([self WOTest_isUnsignedShort])
1813 return WO_COMPARE_SCALARS([self WOTest_unsignedShortValue], other); // implicit cast
1814 else if ([self WOTest_isUnsignedLong])
1815 return WO_COMPARE_SCALARS([self WOTest_unsignedLongValue], other); // implicit cast
1816 else if ([self WOTest_isUnsignedLongLong])
1817 return WO_COMPARE_SCALARS([self WOTest_unsignedLongLongValue], other); // implicit cast
1818 else if ([self WOTest_isFloat])
1819 return WO_COMPARE_SCALARS([self WOTest_floatValue], other); // implicit cast
1820 else if ([self WOTest_isDouble])
1821 return WO_COMPARE_SCALARS([self WOTest_doubleValue], other); // implicit cast
1822 else if ([self WOTest_isC99Bool])
1823 return WO_COMPARE_SCALARS([self WOTest_C99BoolValue], other); // no cast
1826 [NSException raise:NSInvalidArgumentException
1827 format:@"cannot compare type \"%s\" with type \"%s\"", [self objCType], @encode(typeof(other))];
1829 return NSOrderedSame; // never reached, but necessary to suppress compiler warning