mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Changes for optimisation of storage of numbers in sets/maps/dictionaries and
for small numbers in particular. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6335 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a3243a910e
commit
16ea7d5057
4 changed files with 560 additions and 310 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2000-03-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
NSNumber optimisation ...
|
||||
* Headers/gnustep/base/NSValue.h: Added a couple of GNUstep specific
|
||||
functions for obtaining cached information about methods of NSNumber
|
||||
subclasses and hashes of small integer values.
|
||||
* Source/NSNumber.m: Added caches for small integer numbers and for
|
||||
booleans. Also added caching mechamism for methods and order info
|
||||
for NSNumber concrete subclasses.
|
||||
* Source/NSConcreteNumber.m: Added support for much more efficient
|
||||
compare and fast hash for small integers.
|
||||
|
||||
2000-03-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSUserDefaults.m: ([-description]) implemented.
|
||||
|
|
|
@ -78,19 +78,19 @@
|
|||
+ (NSNumber*) numberWithUnsignedLongLong: (unsigned long long)value;
|
||||
+ (NSNumber*) numberWithUnsignedShort: (unsigned short)value;
|
||||
|
||||
- (id)initWithBool: (BOOL)value;
|
||||
- (id)initWithChar: (char)value;
|
||||
- (id)initWithDouble: (double)value;
|
||||
- (id)initWithFloat: (float)value;
|
||||
- (id)initWithInt: (int)value;
|
||||
- (id)initWithLong: (long)value;
|
||||
- (id)initWithLongLong: (long long)value;
|
||||
- (id)initWithShort: (short)value;
|
||||
- (id)initWithUnsignedChar: (unsigned char)value;
|
||||
- (id)initWithUnsignedInt: (unsigned int)value;
|
||||
- (id)initWithUnsignedLong: (unsigned long)value;
|
||||
- (id)initWithUnsignedLongLong: (unsigned long long)value;
|
||||
- (id)initWithUnsignedShort: (unsigned short)value;
|
||||
- (id) initWithBool: (BOOL)value;
|
||||
- (id) initWithChar: (char)value;
|
||||
- (id) initWithDouble: (double)value;
|
||||
- (id) initWithFloat: (float)value;
|
||||
- (id) initWithInt: (int)value;
|
||||
- (id) initWithLong: (long)value;
|
||||
- (id) initWithLongLong: (long long)value;
|
||||
- (id) initWithShort: (short)value;
|
||||
- (id) initWithUnsignedChar: (unsigned char)value;
|
||||
- (id) initWithUnsignedInt: (unsigned int)value;
|
||||
- (id) initWithUnsignedLong: (unsigned long)value;
|
||||
- (id) initWithUnsignedLongLong: (unsigned long long)value;
|
||||
- (id) initWithUnsignedShort: (unsigned short)value;
|
||||
|
||||
// Accessing Data
|
||||
|
||||
|
@ -123,9 +123,37 @@
|
|||
@interface NSValue (Subclassing)
|
||||
|
||||
/* Used by value: withObjCType: to determine the concrete subclass to alloc */
|
||||
+ (Class)valueClassWithObjCType: (const char *)type;
|
||||
+ (Class) valueClassWithObjCType: (const char*)type;
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* Cache info for internal use by NSNumber concrete subclasses.
|
||||
*/
|
||||
typedef struct {
|
||||
int typeOrder;
|
||||
NSComparisonResult (*compValue)(NSNumber*, SEL, NSNumber*);
|
||||
BOOL (*boolValue)(NSNumber*, SEL);
|
||||
char (*charValue)(NSNumber*, SEL);
|
||||
unsigned char (*unsignedCharValue)(NSNumber*, SEL);
|
||||
short (*shortValue)(NSNumber*, SEL);
|
||||
unsigned short (*unsignedShortValue)(NSNumber*, SEL);
|
||||
int (*intValue)(NSNumber*, SEL);
|
||||
unsigned int (*unsignedIntValue)(NSNumber*, SEL);
|
||||
long (*longValue)(NSNumber*, SEL);
|
||||
unsigned long (*unsignedLongValue)(NSNumber*, SEL);
|
||||
long long (*longLongValue)(NSNumber*, SEL);
|
||||
unsigned long long (*unsignedLongLongValue)(NSNumber*, SEL);
|
||||
float (*floatValue)(NSNumber*, SEL);
|
||||
double (*doubleValue)(NSNumber*, SEL);
|
||||
} GSNumberInfo;
|
||||
|
||||
GSNumberInfo *GSNumberInfoFromObject(NSNumber *o);
|
||||
#define GS_SMALL 16
|
||||
/*
|
||||
* Get cached values for integers in the range -GS_SMALL to +GS_SMALL
|
||||
*/
|
||||
unsigned GSSmallHash(int n);
|
||||
#endif
|
||||
|
||||
#endif /* __NSValue_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
|
@ -37,119 +37,62 @@
|
|||
# define NumberTemplate NSBoolNumber
|
||||
# define TYPE_METHOD boolValue
|
||||
# define TYPE_FORMAT @"%u"
|
||||
# define NEXT_ORDER 4
|
||||
# define NEXT_METHOD shortValue
|
||||
# define NEXT_CTYPE short
|
||||
#elif TYPE_ORDER == 1
|
||||
# define NumberTemplate NSUCharNumber
|
||||
# define TYPE_METHOD unsignedCharValue
|
||||
# define TYPE_FORMAT @"%c"
|
||||
# define NEXT_ORDER 4
|
||||
# define NEXT_METHOD shortValue
|
||||
# define NEXT_CTYPE short
|
||||
#elif TYPE_ORDER == 2
|
||||
# define NumberTemplate NSCharNumber
|
||||
# define TYPE_METHOD charValue
|
||||
# define TYPE_FORMAT @"%c"
|
||||
# define NEXT_ORDER 4
|
||||
# define NEXT_METHOD shortValue
|
||||
# define NEXT_CTYPE short
|
||||
#elif TYPE_ORDER == 2
|
||||
# define NumberTemplate NSUCharNumber
|
||||
# define TYPE_METHOD unsignedCharValue
|
||||
# define TYPE_FORMAT @"%c"
|
||||
#elif TYPE_ORDER == 3
|
||||
# define NumberTemplate NSUShortNumber
|
||||
# define TYPE_METHOD unsignedShortValue
|
||||
# define TYPE_FORMAT @"%hu"
|
||||
# define NEXT_ORDER 6
|
||||
# define NEXT_METHOD intValue
|
||||
# define NEXT_CTYPE int
|
||||
#elif TYPE_ORDER == 4
|
||||
# define NumberTemplate NSShortNumber
|
||||
# define TYPE_METHOD shortValue
|
||||
# define TYPE_FORMAT @"%hd"
|
||||
# define NEXT_ORDER 6
|
||||
# define NEXT_METHOD intValue
|
||||
# define NEXT_CTYPE int
|
||||
#elif TYPE_ORDER == 4
|
||||
# define NumberTemplate NSUShortNumber
|
||||
# define TYPE_METHOD unsignedShortValue
|
||||
# define TYPE_FORMAT @"%hu"
|
||||
#elif TYPE_ORDER == 5
|
||||
# define NumberTemplate NSUIntNumber
|
||||
# define TYPE_METHOD unsignedIntValue
|
||||
# define TYPE_FORMAT @"%u"
|
||||
# define NEXT_ORDER 8
|
||||
# define NEXT_METHOD longValue
|
||||
# define NEXT_CTYPE long
|
||||
#elif TYPE_ORDER == 6
|
||||
# define NumberTemplate NSIntNumber
|
||||
# define TYPE_METHOD intValue
|
||||
# define TYPE_FORMAT @"%d"
|
||||
# define NEXT_ORDER 8
|
||||
# define NEXT_METHOD longValue
|
||||
# define NEXT_CTYPE long
|
||||
#elif TYPE_ORDER == 6
|
||||
# define NumberTemplate NSUIntNumber
|
||||
# define TYPE_METHOD unsignedIntValue
|
||||
# define TYPE_FORMAT @"%u"
|
||||
#elif TYPE_ORDER == 7
|
||||
# define NumberTemplate NSULongNumber
|
||||
# define TYPE_METHOD unsignedLongValue
|
||||
# define TYPE_FORMAT @"%lu"
|
||||
# define NEXT_ORDER 10
|
||||
# define NEXT_METHOD longLongValue
|
||||
# define NEXT_CTYPE long long
|
||||
#elif TYPE_ORDER == 8
|
||||
# define NumberTemplate NSLongNumber
|
||||
# define TYPE_METHOD longValue
|
||||
# define TYPE_FORMAT @"%ld"
|
||||
# define NEXT_ORDER 10
|
||||
# define NEXT_METHOD longLongValue
|
||||
# define NEXT_CTYPE long long
|
||||
#elif TYPE_ORDER == 8
|
||||
# define NumberTemplate NSULongNumber
|
||||
# define TYPE_METHOD unsignedLongValue
|
||||
# define TYPE_FORMAT @"%lu"
|
||||
#elif TYPE_ORDER == 9
|
||||
# define NumberTemplate NSULongLongNumber
|
||||
# define TYPE_METHOD unsignedLongLongValue
|
||||
# define TYPE_FORMAT @"%llu"
|
||||
# define NEXT_ORDER 12
|
||||
# define NEXT_METHOD doubleValue
|
||||
# define NEXT_CTYPE double
|
||||
#elif TYPE_ORDER == 10
|
||||
# define NumberTemplate NSLongLongNumber
|
||||
# define TYPE_METHOD longLongValue
|
||||
# define TYPE_FORMAT @"%lld"
|
||||
# define NEXT_ORDER 12
|
||||
# define NEXT_METHOD doubleValue
|
||||
# define NEXT_CTYPE double
|
||||
#elif TYPE_ORDER == 10
|
||||
# define NumberTemplate NSULongLongNumber
|
||||
# define TYPE_METHOD unsignedLongLongValue
|
||||
# define TYPE_FORMAT @"%llu"
|
||||
#elif TYPE_ORDER == 11
|
||||
# define NumberTemplate NSFloatNumber
|
||||
# define TYPE_METHOD floatValue
|
||||
# define TYPE_FORMAT @"%f"
|
||||
# define NEXT_ORDER 12
|
||||
# define NEXT_METHOD doubleValue
|
||||
# define NEXT_CTYPE double
|
||||
#elif TYPE_ORDER == 12
|
||||
# define NumberTemplate NSDoubleNumber
|
||||
# define TYPE_METHOD doubleValue
|
||||
# define TYPE_FORMAT @"%g"
|
||||
# define NEXT_ORDER 12
|
||||
# define NEXT_METHOD doubleValue
|
||||
# define NEXT_CTYPE double
|
||||
#endif
|
||||
|
||||
@interface NSNumber (Private)
|
||||
- (int)_nextOrder;
|
||||
- (NSComparisonResult) _promotedCompare: (NSNumber*)other;
|
||||
- (int)_typeOrder;
|
||||
- (int) _typeOrder;
|
||||
@end
|
||||
|
||||
@implementation NumberTemplate (Private)
|
||||
- (int)_nextOrder
|
||||
{
|
||||
return NEXT_ORDER;
|
||||
}
|
||||
- (NSComparisonResult) _promotedCompare: (NSNumber*)other
|
||||
{
|
||||
NEXT_CTYPE v0, v1;
|
||||
|
||||
v0 = [self NEXT_METHOD];
|
||||
v1 = [other NEXT_METHOD];
|
||||
|
||||
if (v0 == v1)
|
||||
return NSOrderedSame;
|
||||
else
|
||||
return (v0 < v1) ? NSOrderedAscending : NSOrderedDescending;
|
||||
}
|
||||
- (int)_typeOrder
|
||||
- (int) _typeOrder
|
||||
{
|
||||
return TYPE_ORDER;
|
||||
}
|
||||
|
@ -157,130 +100,19 @@
|
|||
|
||||
@implementation NumberTemplate
|
||||
|
||||
- (id)initWithBytes: (const void *)value objCType: (const char *)type
|
||||
- (id) initWithBytes: (const void*)value objCType: (const char*)type
|
||||
{
|
||||
typedef __typeof__(data) _dt;
|
||||
data = *(_dt *)value;
|
||||
data = *(_dt*)value;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)boolValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (char)charValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (double)doubleValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (float)floatValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (int)intValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (long long)longLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (long)longValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (short)shortValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned char)unsignedCharValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned int)unsignedIntValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned long long)unsignedLongLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned long)unsignedLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned short)unsignedShortValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compare: (NSNumber *)other
|
||||
{
|
||||
int o = [self _typeOrder];
|
||||
|
||||
if (o == [other _typeOrder] || o >= [other _nextOrder])
|
||||
{
|
||||
typedef __typeof__(data) _dt;
|
||||
_dt other_data = [other TYPE_METHOD];
|
||||
|
||||
if (data == other_data)
|
||||
return NSOrderedSame;
|
||||
else
|
||||
return (data < other_data) ? NSOrderedAscending : NSOrderedDescending;
|
||||
}
|
||||
o = [self _nextOrder];
|
||||
if (o <= [other _typeOrder])
|
||||
{
|
||||
NSComparisonResult r = [other compare: self];
|
||||
|
||||
if (r == NSOrderedAscending)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (r == NSOrderedDescending)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
if (o >= [other _nextOrder])
|
||||
{
|
||||
return [self _promotedCompare: other];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSComparisonResult r = [other _promotedCompare: self];
|
||||
|
||||
if (r == NSOrderedAscending)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (r == NSOrderedDescending)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Because of the rule that two numbers which are the same according to
|
||||
/*
|
||||
* Because of the rule that two numbers which are the same according to
|
||||
* [-isEqual: ] must generate the same hash, we must generate the hash
|
||||
* from the most general representation of the number.
|
||||
* NB. Don't change this without changing the matching function in
|
||||
* NSNumber.m
|
||||
*/
|
||||
- (unsigned) hash
|
||||
{
|
||||
|
@ -289,23 +121,141 @@
|
|||
unsigned char c[sizeof(double)];
|
||||
} val;
|
||||
unsigned hash = 0;
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
* If possible use a cached hash value for small integers.
|
||||
*/
|
||||
#if TYPE_ORDER < 11
|
||||
#if (TYPE_ORDER & 1)
|
||||
if (data <= GS_SMALL && data >= -GS_SMALL)
|
||||
#else
|
||||
if (data <= GS_SMALL)
|
||||
#endif
|
||||
{
|
||||
return GSSmallHash((int)data);
|
||||
}
|
||||
#endif
|
||||
|
||||
val.d = [self doubleValue];
|
||||
for (i = 0; i < sizeof(double); i++) {
|
||||
hash += val.c[i];
|
||||
}
|
||||
for (i = 0; i < sizeof(double); i++)
|
||||
{
|
||||
hash += val.c[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (BOOL) isEqualToNumber: (NSNumber*)o
|
||||
- (BOOL) boolValue
|
||||
{
|
||||
if ([self compare: o] == NSOrderedSame)
|
||||
return YES;
|
||||
return NO;
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSString *)descriptionWithLocale: (NSDictionary*)locale
|
||||
- (char) charValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (double) doubleValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (float) floatValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (int) intValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (long long) longLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (long) longValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (short) shortValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned char) unsignedCharValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned int) unsignedIntValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned long long) unsignedLongLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned long) unsignedLongValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (unsigned short) unsignedShortValue
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSComparisonResult) compare: (NSNumber*)other
|
||||
{
|
||||
GSNumberInfo *info;
|
||||
|
||||
if (other == self)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
info = GSNumberInfoFromObject(other);
|
||||
if (TYPE_ORDER >= info->typeOrder)
|
||||
{
|
||||
typedef __typeof__(data) _dt;
|
||||
_dt other_data = (*(info->TYPE_METHOD))(other, @selector(TYPE_METHOD));
|
||||
|
||||
if (data == other_data)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else if (data < other_data)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSComparisonResult r;
|
||||
|
||||
r = (*(info->compValue))(other, @selector(compare:), self);
|
||||
|
||||
if (r == NSOrderedAscending)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (r == NSOrderedDescending)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
|
||||
{
|
||||
#if TYPE_ORDER == 0
|
||||
return (data) ? @"YES" : @"NO";
|
||||
|
@ -315,9 +265,9 @@
|
|||
}
|
||||
|
||||
// Override these from NSValue
|
||||
- (void)getValue: (void *)value
|
||||
- (void) getValue: (void*)value
|
||||
{
|
||||
if (!value)
|
||||
if (value == 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Cannot copy value into NULL pointer"];
|
||||
|
@ -326,14 +276,14 @@
|
|||
memcpy( value, &data, objc_sizeof_type([self objCType]) );
|
||||
}
|
||||
|
||||
- (const char *)objCType
|
||||
- (const char*) objCType
|
||||
{
|
||||
typedef __typeof__(data) _dt;
|
||||
return @encode(_dt);
|
||||
}
|
||||
|
||||
// NSCoding
|
||||
- (Class)classForCoder
|
||||
- (Class) classForCoder
|
||||
{
|
||||
return [self class];
|
||||
}
|
||||
|
|
|
@ -28,17 +28,98 @@
|
|||
#include <base/fast.x>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSConcreteNumber.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSThread.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
|
||||
@interface NSNumber (Private)
|
||||
- (int)_nextOrder;
|
||||
- (NSComparisonResult) _promotedCompare: (NSNumber*)other;
|
||||
- (int)_typeOrder;
|
||||
- (int) _typeOrder;
|
||||
@end
|
||||
|
||||
@implementation NSNumber
|
||||
|
||||
static NSMapTable *numberMap;
|
||||
static BOOL multiThreaded = NO;
|
||||
static NSNumber *boolN;
|
||||
static NSNumber *boolY;
|
||||
static NSNumber *smallIntegers[GS_SMALL * 2 + 1];
|
||||
static unsigned int smallHashes[GS_SMALL * 2 + 1];
|
||||
|
||||
/*
|
||||
* Cache info for each number class. The caches for all the standard types
|
||||
* of number are built in the NSNumber +initialize method - which is protected
|
||||
* by locks. Therafter, in a multi-threaded system we may waste some memory
|
||||
* in order to get speed.
|
||||
*/
|
||||
GSNumberInfo*
|
||||
GSNumberInfoFromObject(NSNumber *o)
|
||||
{
|
||||
Class c;
|
||||
GSNumberInfo *info;
|
||||
|
||||
c = fastClass(o);
|
||||
info = (GSNumberInfo*)NSMapGet (numberMap, (void*)c);
|
||||
if (info == 0)
|
||||
{
|
||||
info = (GSNumberInfo*)objc_malloc(sizeof(GSNumberInfo));
|
||||
info->typeOrder = [o _typeOrder];
|
||||
info->compValue = (NSComparisonResult (*)(NSNumber*, SEL, NSNumber*))
|
||||
[o methodForSelector: @selector(compare:)];
|
||||
info->boolValue = (BOOL (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(boolValue)];
|
||||
info->charValue = (char (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(charValue)];
|
||||
info->unsignedCharValue = (unsigned char (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(unsignedCharValue)];
|
||||
info->shortValue = (short (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(shortValue)];
|
||||
info->unsignedShortValue = (unsigned short (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(unsignedShortValue)];
|
||||
info->intValue = (int (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(intValue)];
|
||||
info->unsignedIntValue = (unsigned int (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(unsignedIntValue)];
|
||||
info->longValue = (long (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(longValue)];
|
||||
info->unsignedLongValue = (unsigned long (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(unsignedLongValue)];
|
||||
info->longLongValue = (long long (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(longLongValue)];
|
||||
info->unsignedLongLongValue = (unsigned long long (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(unsignedLongLongValue)];
|
||||
info->floatValue = (float (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(floatValue)];
|
||||
info->doubleValue = (double (*)(NSNumber*, SEL))
|
||||
[o methodForSelector: @selector(doubleValue)];
|
||||
|
||||
if (multiThreaded == YES)
|
||||
{
|
||||
NSMapTable *table;
|
||||
|
||||
/*
|
||||
* Memory leak for efficiency - the old map table is never
|
||||
* deallocated, so we don't have to do any locking.
|
||||
*/
|
||||
table = NSCopyMapTableWithZone(numberMap, NSDefaultMallocZone());
|
||||
NSMapInsert(table, (void*)c, (void*)info);
|
||||
numberMap = table;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSMapInsert(numberMap, (void*)c, (void*)info);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
GSSmallHash(int n)
|
||||
{
|
||||
return smallHashes[n + GS_SMALL];
|
||||
}
|
||||
|
||||
static Class abstractClass;
|
||||
static Class boolNumberClass;
|
||||
static Class charNumberClass;
|
||||
|
@ -54,12 +135,32 @@ static Class uLongLongNumberClass;
|
|||
static Class floatNumberClass;
|
||||
static Class doubleNumberClass;
|
||||
|
||||
+ (void) _becomeThreaded: (NSNotification*)notification
|
||||
{
|
||||
multiThreaded = YES;
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSNumber class])
|
||||
{
|
||||
abstractClass = self;
|
||||
BOOL boolean;
|
||||
int integer;
|
||||
unsigned (*hasher)(NSNumber*, SEL);
|
||||
|
||||
abstractClass = self;
|
||||
hasher = (unsigned (*)(NSNumber*, SEL))
|
||||
[self instanceMethodForSelector: @selector(hash)];
|
||||
|
||||
/*
|
||||
* Create cache for per-subclass method implementations etc.
|
||||
*/
|
||||
numberMap = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSOwnedPointerMapValueCallBacks, 0);
|
||||
|
||||
/*
|
||||
* cache standard subclass info.
|
||||
*/
|
||||
boolNumberClass = [NSBoolNumber class];
|
||||
charNumberClass = [NSCharNumber class];
|
||||
uCharNumberClass = [NSUCharNumber class];
|
||||
|
@ -73,13 +174,58 @@ static Class doubleNumberClass;
|
|||
uLongLongNumberClass = [NSULongLongNumber class];
|
||||
floatNumberClass = [NSFloatNumber class];
|
||||
doubleNumberClass = [NSDoubleNumber class];
|
||||
|
||||
/*
|
||||
* cache bool values.
|
||||
*/
|
||||
boolN = (NSNumber*)NSAllocateObject(boolNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
boolean = NO;
|
||||
boolN = [boolN initWithBytes: &boolean objCType: NULL];
|
||||
|
||||
boolY = (NSNumber*)NSAllocateObject(boolNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
boolean = YES;
|
||||
boolY = [boolY initWithBytes: &boolean objCType: NULL];
|
||||
|
||||
/*
|
||||
* cache small integer values.
|
||||
*/
|
||||
for (integer = -GS_SMALL; integer <= GS_SMALL; integer++)
|
||||
{
|
||||
NSNumber *num;
|
||||
|
||||
num = (NSNumber*)NSAllocateObject(intNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
num = [num initWithBytes: &integer objCType: NULL];
|
||||
smallIntegers[integer + GS_SMALL] = num;
|
||||
smallHashes[integer + GS_SMALL] = (*hasher)(num, @selector(hash));
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we know if we are multi-threaded so that if the caches
|
||||
* need to grow, we do it by copying and replacing without deleting
|
||||
* an old cache that may be in use by another thread.
|
||||
*/
|
||||
if ([NSThread isMultiThreaded])
|
||||
{
|
||||
[self _becomeThreaded: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(_becomeThreaded:)
|
||||
name: NSWillBecomeMultiThreadedNotification
|
||||
object: nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the concrete class associated with the type encoding. Note
|
||||
that we don't allow NSNumber to instantiate any class but its own
|
||||
concrete subclasses (see check at end of method) */
|
||||
+ (Class)valueClassWithObjCType: (const char *)type
|
||||
+ (Class) valueClassWithObjCType: (const char*)type
|
||||
{
|
||||
Class theClass = Nil;
|
||||
|
||||
|
@ -118,32 +264,39 @@ static Class doubleNumberClass;
|
|||
/* NOT REACHED */
|
||||
}
|
||||
else if (theClass == Nil)
|
||||
theClass = [super valueClassWithObjCType: type];
|
||||
|
||||
{
|
||||
theClass = [super valueClassWithObjCType: type];
|
||||
}
|
||||
return theClass;
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithBool: (BOOL)value
|
||||
+ (NSNumber*) numberWithBool: (BOOL)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
theObj = (NSNumber*)NSAllocateObject(boolNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
if (value == YES)
|
||||
{
|
||||
return boolY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return boolN;
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithChar: (char)value
|
||||
+ (NSNumber*) numberWithChar: (char)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(charNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithDouble: (double)value
|
||||
+ (NSNumber*) numberWithDouble: (double)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
|
@ -153,7 +306,7 @@ static Class doubleNumberClass;
|
|||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithFloat: (float)value
|
||||
+ (NSNumber*) numberWithFloat: (float)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
|
@ -163,97 +316,133 @@ static Class doubleNumberClass;
|
|||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithInt: (int)value
|
||||
+ (NSNumber*) numberWithInt: (int)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(intNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithLong: (long)value
|
||||
+ (NSNumber*) numberWithLong: (long)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(longNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithLongLong: (long long)value
|
||||
+ (NSNumber*) numberWithLongLong: (long long)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(longLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithShort: (short)value
|
||||
+ (NSNumber*) numberWithShort: (short)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(shortNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithUnsignedChar: (unsigned char)value
|
||||
+ (NSNumber*) numberWithUnsignedChar: (unsigned char)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(uCharNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithUnsignedInt: (unsigned int)value
|
||||
+ (NSNumber*) numberWithUnsignedInt: (unsigned int)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(uIntNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithUnsignedLong: (unsigned long)value
|
||||
+ (NSNumber*) numberWithUnsignedLong: (unsigned long)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(uLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithUnsignedLongLong: (unsigned long long)value
|
||||
+ (NSNumber*) numberWithUnsignedLongLong: (unsigned long long)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(uLongLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSNumber *)numberWithUnsignedShort: (unsigned short)value
|
||||
+ (NSNumber*) numberWithUnsignedShort: (unsigned short)value
|
||||
{
|
||||
NSNumber *theObj;
|
||||
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return smallIntegers[value + GS_SMALL];
|
||||
}
|
||||
theObj = (NSNumber*)NSAllocateObject(uShortNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
theObj = [theObj initWithBytes: &value objCType: NULL];
|
||||
return AUTORELEASE(theObj);
|
||||
}
|
||||
|
||||
+ (NSValue*)valueFromString: (NSString *)string
|
||||
+ (NSValue*) valueFromString: (NSString*)string
|
||||
{
|
||||
/* FIXME: implement this better */
|
||||
const char *str;
|
||||
|
@ -269,25 +458,34 @@ static Class doubleNumberClass;
|
|||
return [NSNumber numberWithInt: 0];
|
||||
}
|
||||
|
||||
- (id)initWithBool: (BOOL)value
|
||||
- (id) initWithBool: (BOOL)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
self = (NSNumber*)NSAllocateObject(boolNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
if (value == YES)
|
||||
{
|
||||
self = boolY;
|
||||
}
|
||||
else
|
||||
{
|
||||
self = boolN;
|
||||
}
|
||||
return RETAIN(self);
|
||||
}
|
||||
|
||||
- (id)initWithChar: (char)value
|
||||
- (id) initWithChar: (char)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(charNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithDouble: (double)value
|
||||
- (id) initWithDouble: (double)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
self = (NSNumber*)NSAllocateObject(doubleNumberClass, 0,
|
||||
|
@ -296,7 +494,7 @@ static Class doubleNumberClass;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFloat: (float)value
|
||||
- (id) initWithFloat: (float)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
self = (NSNumber*)NSAllocateObject(floatNumberClass, 0,
|
||||
|
@ -305,81 +503,117 @@ static Class doubleNumberClass;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithInt: (int)value
|
||||
- (id) initWithInt: (int)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(intNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithLong: (long)value
|
||||
- (id) initWithLong: (long)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(longNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithLongLong: (long long)value
|
||||
- (id) initWithLongLong: (long long)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(longLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithShort: (short)value
|
||||
- (id) initWithShort: (short)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL && value >= -GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(shortNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithUnsignedChar: (unsigned char)value
|
||||
- (id) initWithUnsignedChar: (unsigned char)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(uCharNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithUnsignedInt: (unsigned int)value
|
||||
- (id) initWithUnsignedInt: (unsigned int)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(uIntNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithUnsignedLong: (unsigned long)value
|
||||
- (id) initWithUnsignedLong: (unsigned long)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(uLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithUnsignedLongLong: (unsigned long long)value
|
||||
- (id) initWithUnsignedLongLong: (unsigned long long)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(uLongLongNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithUnsignedShort: (unsigned short)value
|
||||
- (id) initWithUnsignedShort: (unsigned short)value
|
||||
{
|
||||
NSDeallocateObject(self);
|
||||
if (value <= GS_SMALL)
|
||||
{
|
||||
return RETAIN(smallIntegers[value + GS_SMALL]);
|
||||
}
|
||||
self = (NSNumber*)NSAllocateObject(uShortNumberClass, 0,
|
||||
NSDefaultMallocZone());
|
||||
self = [self initWithBytes: &value objCType: NULL];
|
||||
|
@ -408,145 +642,171 @@ static Class doubleNumberClass;
|
|||
}
|
||||
|
||||
/* All the rest of these methods must be implemented by a subclass */
|
||||
- (BOOL)boolValue
|
||||
- (BOOL) boolValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (char)charValue
|
||||
- (char) charValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (double)doubleValue
|
||||
- (double) doubleValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (float)floatValue
|
||||
- (float) floatValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int)intValue
|
||||
- (int) intValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (long long)longLongValue
|
||||
- (long long) longLongValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (long)longValue
|
||||
- (long) longValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (short)shortValue
|
||||
- (short) shortValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSString *)stringValue
|
||||
- (NSString*) stringValue
|
||||
{
|
||||
return [self descriptionWithLocale: nil];
|
||||
}
|
||||
|
||||
- (unsigned char)unsignedCharValue
|
||||
- (unsigned char) unsignedCharValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (unsigned int)unsignedIntValue
|
||||
- (unsigned int) unsignedIntValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (unsigned long long)unsignedLongLongValue
|
||||
- (unsigned long long) unsignedLongLongValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (unsigned long)unsignedLongValue
|
||||
- (unsigned long) unsignedLongValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (unsigned short)unsignedShortValue
|
||||
- (unsigned short) unsignedShortValue
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compare: (NSNumber *)otherNumber
|
||||
- (NSComparisonResult) compare: (NSNumber*)other
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
GSNumberInfo *otherInfo;
|
||||
GSNumberInfo *myInfo;
|
||||
double otherValue;
|
||||
double myValue;
|
||||
|
||||
myInfo = GSNumberInfoFromObject(self);
|
||||
otherInfo = GSNumberInfoFromObject(other);
|
||||
myValue = (*(myInfo->doubleValue))(self, @selector(doubleValue));
|
||||
otherValue = (*(otherInfo->doubleValue))(other, @selector(doubleValue));
|
||||
|
||||
if (myValue == otherValue)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else if (myValue < otherValue)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Because of the rule that two numbers which are the same according to
|
||||
* [-isEqual: ] must generate the same hash, we must generate the hash
|
||||
* from the most general representation of the number.
|
||||
* NB. Don't change this without changing the matching function in
|
||||
* NSConcreteNumber.m
|
||||
*/
|
||||
- (unsigned) hash
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
union {
|
||||
double d;
|
||||
unsigned char c[sizeof(double)];
|
||||
} val;
|
||||
unsigned hash = 0;
|
||||
unsigned i;
|
||||
|
||||
val.d = [self doubleValue];
|
||||
for (i = 0; i < sizeof(double); i++)
|
||||
{
|
||||
hash += val.c[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (BOOL) isEqual: o
|
||||
{
|
||||
if (o != nil && fastIsInstance(o)
|
||||
&& fastInstanceIsKindOfClass(o, abstractClass))
|
||||
return [self isEqualToNumber: (NSNumber*)o];
|
||||
else
|
||||
return [super isEqual: o];
|
||||
{
|
||||
return [self isEqualToNumber: (NSNumber*)o];
|
||||
}
|
||||
return [super isEqual: o];
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToNumber: (NSNumber *)otherNumber
|
||||
- (BOOL) isEqualToNumber: (NSNumber*)o
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
if ([self compare: o] == NSOrderedSame)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
// NSCoding (done by subclasses)
|
||||
- (void)encodeWithCoder: (NSCoder *)coder
|
||||
- (void) encodeWithCoder: (NSCoder*)coder
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (id)initWithCoder: (NSCoder *)coder
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (int)_nextOrder
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
- (NSComparisonResult) _promotedCompare: (NSNumber*)other
|
||||
{
|
||||
double v0, v1;
|
||||
|
||||
v0 = [self doubleValue];
|
||||
v1 = [other doubleValue];
|
||||
|
||||
if (v0 == v1)
|
||||
return NSOrderedSame;
|
||||
else
|
||||
return (v0 < v1) ? NSOrderedAscending : NSOrderedDescending;
|
||||
}
|
||||
- (int)_typeOrder
|
||||
- (int) _typeOrder
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue