2010-02-15 10:58:34 +00:00
|
|
|
/** Implementation of NSNumber for GNUStep
|
|
|
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
Written by: David Chisnall
|
|
|
|
Partial rewrite: Richard Frith-Macdonld <rfm@gnu.org>
|
2010-08-18 12:34:56 +00:00
|
|
|
(to compile on gnu/linux and mswindows,
|
|
|
|
to meet coding/style standards,
|
|
|
|
to restore lost functionality)
|
2012-04-01 07:33:38 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
Date: February 2010
|
1995-04-03 20:49:14 +00:00
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
1995-04-03 20:49:14 +00:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1995-04-03 20:49:14 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1995-04-03 20:49:14 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1995-04-03 20:49:14 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-06-04 06:42:10 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
*/
|
|
|
|
|
2000-03-18 07:56:43 +00:00
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
#import "common.h"
|
Rewritten NSNumber implementation. This fixes several OS X-compatibility issues:
The -pointerValue method now returns the value cast to a pointer, not some random value, as the documentation says it should. This is a change from OpenStep, which said:
> It's an error to send this message to an NSValue that doesn't store a pointer.
The OS X docs now say:
> The receiver's value as a pointer to void. If the receiver was not created to hold a pointer-sized data item, the result is undefined.
This means that any NSNumber created with a word-sized integer should return the same value.
Fixed a number of corner-cases in the compare: implementation caused by incorrect type promotion. The OS X docs say:
> The compare: method follows the standard C rules for type conversion.
The OS X implementation does not do this. We now match Apple's conversion rules bug-for-bug: Every value is stored in the smallest signed type that will hold it, unless there is no unsigned type that can hold it, in which case it is stored in an `unsigned long long`, comparisons between integer and floating point values cast both to a double, comparisons between integer types perform a real comparison (so an unsigned long long is always greater than any negative number, at any precision). The Apple implementation is actually quite sane, it is just completely unrelated to the documentation in any way.
We now use the same range of reusable objects. Note that there is an error in Cocoa Design Patterns in the description of how Apple's implementation works. Do not use this as a reference.
We now return `nil` when an NSNumber is sent an -init message. This is consistent with Apple's implementation but breaks some things in the GNUstep test suite (which RFM said he will fix).
There is a small change in NSValue.h so that the locale parameter is now an `id` not an `NSString*`. This is because, under recent OS X, it may also be an `NSLocale` instance. I am not sure how much GNUstep supports `NSLocale`, but this change shouldn't affect anything.
The new (private) GSNumberTypes.h file lets you define macros that are instantiated with each of the names of primitive C types. These might be useful for simplifying other classes that have -intValue, -floatValue, and so on methods, such as the `NSCell` family.
The old NSConcreteNumberTemplate and NSConcreteNumber stuff has been removed. The code is now a bit more than 10% of the size of the old NSNumber code, and is hopefully maintainable now, so the next change won't require a complete rewrite.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29618 72102866-910b-0410-8b05-ffd578937521
2010-02-14 12:57:44 +00:00
|
|
|
|
2010-02-18 07:06:42 +00:00
|
|
|
#if !defined(LLONG_MAX)
|
|
|
|
# if defined(__LONG_LONG_MAX__)
|
|
|
|
# define LLONG_MAX __LONG_LONG_MAX__
|
|
|
|
# define LLONG_MIN (-LLONG_MAX-1)
|
|
|
|
# define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
|
|
|
|
# else
|
|
|
|
# error Neither LLONG_MAX nor __LONG_LONG_MAX__ found
|
|
|
|
# endif
|
2010-02-17 12:07:48 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2013-08-22 15:44:54 +00:00
|
|
|
#import "common.h"
|
2010-02-15 10:58:34 +00:00
|
|
|
#import "Foundation/NSCoder.h"
|
|
|
|
#import "Foundation/NSDecimalNumber.h"
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
#import "Foundation/NSValue.h"
|
2011-08-05 17:34:47 +00:00
|
|
|
#if __has_include(<objc/runtime.h>)
|
|
|
|
# include <objc/runtime.h>
|
|
|
|
#endif
|
Rewritten NSNumber implementation. This fixes several OS X-compatibility issues:
The -pointerValue method now returns the value cast to a pointer, not some random value, as the documentation says it should. This is a change from OpenStep, which said:
> It's an error to send this message to an NSValue that doesn't store a pointer.
The OS X docs now say:
> The receiver's value as a pointer to void. If the receiver was not created to hold a pointer-sized data item, the result is undefined.
This means that any NSNumber created with a word-sized integer should return the same value.
Fixed a number of corner-cases in the compare: implementation caused by incorrect type promotion. The OS X docs say:
> The compare: method follows the standard C rules for type conversion.
The OS X implementation does not do this. We now match Apple's conversion rules bug-for-bug: Every value is stored in the smallest signed type that will hold it, unless there is no unsigned type that can hold it, in which case it is stored in an `unsigned long long`, comparisons between integer and floating point values cast both to a double, comparisons between integer types perform a real comparison (so an unsigned long long is always greater than any negative number, at any precision). The Apple implementation is actually quite sane, it is just completely unrelated to the documentation in any way.
We now use the same range of reusable objects. Note that there is an error in Cocoa Design Patterns in the description of how Apple's implementation works. Do not use this as a reference.
We now return `nil` when an NSNumber is sent an -init message. This is consistent with Apple's implementation but breaks some things in the GNUstep test suite (which RFM said he will fix).
There is a small change in NSValue.h so that the locale parameter is now an `id` not an `NSString*`. This is because, under recent OS X, it may also be an `NSLocale` instance. I am not sure how much GNUstep supports `NSLocale`, but this change shouldn't affect anything.
The new (private) GSNumberTypes.h file lets you define macros that are instantiated with each of the names of primitive C types. These might be useful for simplifying other classes that have -intValue, -floatValue, and so on methods, such as the `NSCell` family.
The old NSConcreteNumberTemplate and NSConcreteNumber stuff has been removed. The code is now a bit more than 10% of the size of the old NSNumber code, and is hopefully maintainable now, so the next change won't require a complete rewrite.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29618 72102866-910b-0410-8b05-ffd578937521
2010-02-14 12:57:44 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/*
|
|
|
|
* NSNumber implementation. This matches the behaviour of Apple's
|
|
|
|
* implementation. Values in the range -1 to 12 inclusive are mapped to
|
|
|
|
* singletons. All other values are mapped to the smallest signed value that
|
2010-02-17 12:07:48 +00:00
|
|
|
* will store them, unless they are greater than LLONG_MAX, in which case
|
2010-02-15 10:58:34 +00:00
|
|
|
* they are stored in an unsigned long long.
|
2010-08-18 12:34:56 +00:00
|
|
|
* Booleans are handled as a special case since some stuff (notably interface
|
|
|
|
* builder (nib) archives) needs to differentiate between booleans and integers.
|
2010-02-15 10:58:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
@interface NSSignedIntegerNumber : NSNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
@end
|
2010-02-15 10:58:34 +00:00
|
|
|
|
|
|
|
@interface NSIntNumber : NSSignedIntegerNumber
|
2003-11-30 09:05:31 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
@public
|
|
|
|
int value;
|
2003-11-30 09:05:31 +00:00
|
|
|
}
|
Rewritten NSNumber implementation. This fixes several OS X-compatibility issues:
The -pointerValue method now returns the value cast to a pointer, not some random value, as the documentation says it should. This is a change from OpenStep, which said:
> It's an error to send this message to an NSValue that doesn't store a pointer.
The OS X docs now say:
> The receiver's value as a pointer to void. If the receiver was not created to hold a pointer-sized data item, the result is undefined.
This means that any NSNumber created with a word-sized integer should return the same value.
Fixed a number of corner-cases in the compare: implementation caused by incorrect type promotion. The OS X docs say:
> The compare: method follows the standard C rules for type conversion.
The OS X implementation does not do this. We now match Apple's conversion rules bug-for-bug: Every value is stored in the smallest signed type that will hold it, unless there is no unsigned type that can hold it, in which case it is stored in an `unsigned long long`, comparisons between integer and floating point values cast both to a double, comparisons between integer types perform a real comparison (so an unsigned long long is always greater than any negative number, at any precision). The Apple implementation is actually quite sane, it is just completely unrelated to the documentation in any way.
We now use the same range of reusable objects. Note that there is an error in Cocoa Design Patterns in the description of how Apple's implementation works. Do not use this as a reference.
We now return `nil` when an NSNumber is sent an -init message. This is consistent with Apple's implementation but breaks some things in the GNUstep test suite (which RFM said he will fix).
There is a small change in NSValue.h so that the locale parameter is now an `id` not an `NSString*`. This is because, under recent OS X, it may also be an `NSLocale` instance. I am not sure how much GNUstep supports `NSLocale`, but this change shouldn't affect anything.
The new (private) GSNumberTypes.h file lets you define macros that are instantiated with each of the names of primitive C types. These might be useful for simplifying other classes that have -intValue, -floatValue, and so on methods, such as the `NSCell` family.
The old NSConcreteNumberTemplate and NSConcreteNumber stuff has been removed. The code is now a bit more than 10% of the size of the old NSNumber code, and is hopefully maintainable now, so the next change won't require a complete rewrite.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29618 72102866-910b-0410-8b05-ffd578937521
2010-02-14 12:57:44 +00:00
|
|
|
@end
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2010-08-18 12:34:56 +00:00
|
|
|
/* Some code needs to differentiate between booleans and other NSNumber
|
|
|
|
* instances, so we need a special subclass to permit that.
|
|
|
|
*/
|
|
|
|
@interface NSBoolNumber : NSIntNumber
|
|
|
|
@end
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@interface NSLongLongNumber : NSSignedIntegerNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
@public
|
|
|
|
long long int value;
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@interface NSUnsignedLongLongNumber : NSNumber
|
2003-11-30 09:05:31 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
@public
|
|
|
|
unsigned long long int value;
|
2003-11-30 09:05:31 +00:00
|
|
|
}
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
// The value ivar in all of the concrete classes contains the real value.
|
|
|
|
#define VALUE value
|
|
|
|
#define COMPARE(value, other) \
|
|
|
|
if (value < other)\
|
|
|
|
{\
|
|
|
|
return NSOrderedAscending;\
|
|
|
|
}\
|
|
|
|
if (value > other)\
|
|
|
|
{\
|
|
|
|
return NSOrderedDescending;\
|
|
|
|
}\
|
|
|
|
return NSOrderedSame;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2011-02-26 06:29:57 +00:00
|
|
|
#define DCOMPARE(value, other) \
|
|
|
|
if (isnan(value)) \
|
|
|
|
{ \
|
|
|
|
if (isnan(other)) \
|
|
|
|
{ \
|
|
|
|
return NSOrderedSame; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
return NSOrderedAscending; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
if (isnan(other)) \
|
|
|
|
{ \
|
|
|
|
if (value < 0.0) \
|
|
|
|
{ \
|
|
|
|
return NSOrderedAscending; \
|
|
|
|
} \
|
|
|
|
return NSOrderedDescending; \
|
|
|
|
} \
|
|
|
|
else if (value < other) \
|
|
|
|
{ \
|
|
|
|
return NSOrderedAscending; \
|
|
|
|
} \
|
|
|
|
else if (value > other) \
|
|
|
|
{ \
|
|
|
|
return NSOrderedDescending; \
|
|
|
|
} \
|
|
|
|
return NSOrderedSame; \
|
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSSignedIntegerNumber
|
|
|
|
- (NSComparisonResult) compare: (NSNumber*)aNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aNumber == self)
|
|
|
|
{
|
|
|
|
return NSOrderedSame;
|
|
|
|
}
|
|
|
|
if (aNumber == nil)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"nil argument for compare:"];
|
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
switch ([aNumber objCType][0])
|
|
|
|
{
|
|
|
|
/* For cases smaller than or equal to an int, we could get the int
|
|
|
|
* value and compare.
|
|
|
|
*/
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
case 'q':
|
2000-03-23 18:57:43 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
long long value = [self longLongValue];
|
|
|
|
long long other = [aNumber longLongValue];
|
|
|
|
|
|
|
|
COMPARE (value, other);
|
2000-03-23 18:57:43 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'Q':
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
unsigned long long other;
|
|
|
|
unsigned long long value;
|
|
|
|
long long v;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/* According to the C type promotion rules, we should cast this to
|
|
|
|
* an unsigned long long, however Apple's code does not do this.
|
|
|
|
* Instead, it performs a real comparison.
|
|
|
|
*/
|
|
|
|
v = [self longLongValue];
|
2000-03-19 20:57:09 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/* If this value is less than 0, then it is less than any value
|
|
|
|
* that can possibly be stored in an unsigned value.
|
2010-02-14 16:32:02 +00:00
|
|
|
*/
|
2010-02-15 10:58:34 +00:00
|
|
|
if (v < 0)
|
|
|
|
{
|
|
|
|
return NSOrderedAscending;
|
|
|
|
}
|
|
|
|
|
|
|
|
other = [aNumber unsignedLongLongValue];
|
|
|
|
value = (unsigned long long) v;
|
|
|
|
COMPARE (value, other);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'f':
|
|
|
|
case 'd':
|
2000-03-19 20:57:09 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
double other = [aNumber doubleValue];
|
|
|
|
double value = [self doubleValue];
|
|
|
|
|
2011-02-26 06:29:57 +00:00
|
|
|
DCOMPARE(value, other)
|
2000-03-19 20:57:09 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
default:
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"unrecognised type for compare:"];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return 0; // Not reached.
|
2000-03-19 20:57:09 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSIntNumber
|
|
|
|
#define FORMAT @"%i"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-08-18 12:34:56 +00:00
|
|
|
@implementation NSBoolNumber
|
2016-04-08 08:17:00 +00:00
|
|
|
- (void) getValue: (void*)buffer
|
|
|
|
{
|
|
|
|
BOOL *ptr = (BOOL*)buffer;
|
|
|
|
*ptr = VALUE;
|
|
|
|
}
|
2010-08-18 12:34:56 +00:00
|
|
|
- (const char *) objCType
|
|
|
|
{
|
|
|
|
return @encode(BOOL);
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSLongLongNumber
|
|
|
|
#define FORMAT @"%lli"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSUnsignedLongLongNumber
|
|
|
|
#define FORMAT @"%llu"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
- (NSComparisonResult) compare: (NSNumber*)aNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aNumber == self)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return NSOrderedSame;
|
|
|
|
}
|
|
|
|
if (aNumber == nil)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"nil argument for compare:"];
|
|
|
|
}
|
2009-02-23 20:42:32 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
switch ([aNumber objCType][0])
|
|
|
|
{
|
|
|
|
/* For cases smaller than or equal to an int, we could get the int
|
|
|
|
* value and compare.
|
2010-02-14 16:32:02 +00:00
|
|
|
*/
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
case 'q':
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
long long other = [aNumber longLongValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
if (other < 0)
|
|
|
|
{
|
|
|
|
return NSOrderedDescending;
|
|
|
|
}
|
|
|
|
COMPARE (value, ((unsigned long long) other));
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'Q':
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
unsigned long long other = [aNumber unsignedLongLongValue];
|
|
|
|
|
|
|
|
COMPARE (value, other);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'f':
|
|
|
|
case 'd':
|
2000-03-19 20:57:09 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
double other = [aNumber doubleValue];
|
2011-02-25 00:25:43 +00:00
|
|
|
double selfv = [self doubleValue];
|
1995-04-03 20:49:14 +00:00
|
|
|
|
2011-02-26 06:29:57 +00:00
|
|
|
DCOMPARE(selfv, other)
|
2010-02-15 10:58:34 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
default:
|
2010-02-15 10:58:34 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"unrecognised type for compare:"];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return 0; // Not reached.
|
2009-02-23 20:42:32 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/*
|
|
|
|
* Abstract superclass for floating point numbers.
|
|
|
|
*/
|
|
|
|
@interface NSFloatingPointNumber : NSNumber
|
|
|
|
@end
|
2012-04-01 07:33:38 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSFloatingPointNumber
|
|
|
|
/* For floats, the type promotion rules say that we always promote to a
|
|
|
|
* floating point type, even if the other value is really an integer.
|
|
|
|
*/
|
|
|
|
- (BOOL) isEqualToNumber: (NSNumber*)aNumber
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2010-02-26 11:20:21 +00:00
|
|
|
return ([self doubleValue] == [aNumber doubleValue]) ? YES : NO;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSComparisonResult) compare: (NSNumber*)aNumber
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
double other;
|
|
|
|
double value;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aNumber == self)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return NSOrderedSame;
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aNumber == nil)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"nil argument for compare:"];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2011-02-25 00:25:43 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
other = [aNumber doubleValue];
|
|
|
|
value = [self doubleValue];
|
2011-02-25 00:25:43 +00:00
|
|
|
|
2011-02-26 06:29:57 +00:00
|
|
|
DCOMPARE(value, other)
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@interface NSFloatNumber : NSFloatingPointNumber
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
@public
|
|
|
|
float value;
|
|
|
|
}
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSFloatNumber
|
|
|
|
#define FORMAT @"%0.7g"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@interface NSDoubleNumber : NSFloatingPointNumber
|
|
|
|
{
|
|
|
|
@public
|
|
|
|
double value;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
@end
|
1995-04-03 20:49:14 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSDoubleNumber
|
|
|
|
#define FORMAT @"%0.16g"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
@end
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2011-07-26 19:05:43 +00:00
|
|
|
#ifdef OBJC_SMALL_OBJECT_SHIFT
|
|
|
|
static BOOL useSmallInt;
|
2016-04-19 08:07:53 +00:00
|
|
|
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
2011-11-16 17:29:15 +00:00
|
|
|
static BOOL useSmallExtendedDouble;
|
|
|
|
static BOOL useSmallRepeatingDouble;
|
2012-04-01 07:33:38 +00:00
|
|
|
static BOOL useSmallFloat;
|
2016-04-19 08:07:53 +00:00
|
|
|
#endif
|
2011-11-16 17:29:15 +00:00
|
|
|
#define SMALL_INT_MASK 1
|
|
|
|
#define SMALL_EXTENDED_DOUBLE_MASK 2
|
|
|
|
#define SMALL_REPEATING_DOUBLE_MASK 3
|
2012-04-01 07:33:38 +00:00
|
|
|
// 4 is GSTinyString
|
|
|
|
#define SMALL_FLOAT_MASK 5
|
2011-07-26 19:05:43 +00:00
|
|
|
|
2011-11-17 06:11:36 +00:00
|
|
|
@interface NSSmallInt : NSSignedIntegerNumber
|
|
|
|
@end
|
|
|
|
|
2011-07-26 19:05:43 +00:00
|
|
|
@implementation NSSmallInt
|
|
|
|
#undef VALUE
|
2011-07-27 08:46:31 +00:00
|
|
|
#define VALUE (((intptr_t)self) >> OBJC_SMALL_OBJECT_SHIFT)
|
2013-07-03 06:46:41 +00:00
|
|
|
#define FORMAT @"%"PRIdPTR
|
2011-07-26 19:05:43 +00:00
|
|
|
#include "NSNumberMethods.h"
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (void) load
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
2011-11-16 17:29:15 +00:00
|
|
|
useSmallInt = objc_registerSmallObjectClass_np(self, SMALL_INT_MASK);
|
2011-07-26 19:05:43 +00:00
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) alloc
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
|
|
|
return (id)1;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
|
|
|
return (id)1;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (id) copy
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone*)aZone
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) retain
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2013-01-29 18:42:23 +00:00
|
|
|
- (NSUInteger) retainCount
|
|
|
|
{
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
2011-11-17 06:11:36 +00:00
|
|
|
- (id) autorelease
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (oneway void) release
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2011-07-26 19:05:43 +00:00
|
|
|
@end
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
union BoxedDouble
|
|
|
|
{
|
2011-11-17 06:11:36 +00:00
|
|
|
id obj;
|
|
|
|
uintptr_t bits;
|
|
|
|
double d;
|
|
|
|
};
|
|
|
|
|
|
|
|
@interface NSSmallExtendedDouble : NSFloatingPointNumber
|
|
|
|
@end
|
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
@implementation NSSmallExtendedDouble
|
2011-11-17 06:11:36 +00:00
|
|
|
static double
|
|
|
|
unboxSmallExtendedDouble(uintptr_t boxed)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
// The low bit of the mantissa
|
|
|
|
uintptr_t mask = boxed & 8;
|
|
|
|
union BoxedDouble ret;
|
|
|
|
// Clear the class pointer
|
|
|
|
boxed &= ~7;
|
|
|
|
ret.bits = boxed | (mask >> 1) | (mask >> 2) | (mask >> 3);
|
|
|
|
return ret.d;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
static BOOL
|
|
|
|
isSmallExtendedDouble(double d)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
union BoxedDouble b = {.d=d};
|
|
|
|
return unboxSmallExtendedDouble(b.bits) == d;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
static double
|
|
|
|
unboxSmallRepeatingDouble(uintptr_t boxed)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
// The low bit of the mantissa
|
|
|
|
uintptr_t mask = boxed & 56;
|
|
|
|
union BoxedDouble ret;
|
|
|
|
// Clear the class pointer
|
|
|
|
boxed &= ~7;
|
|
|
|
ret.bits = boxed | (mask >> 3);
|
|
|
|
return ret.d;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
static BOOL
|
|
|
|
isSmallRepeatingDouble(double d)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
union BoxedDouble b = {.d=d};
|
|
|
|
return unboxSmallRepeatingDouble(b.bits) == d;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
static id
|
|
|
|
boxDouble(double d, uintptr_t mask)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
union BoxedDouble b = {.d=d};
|
|
|
|
b.bits &= ~OBJC_SMALL_OBJECT_MASK;
|
|
|
|
b.bits |= mask;
|
|
|
|
return b.obj;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
#undef VALUE
|
|
|
|
#define VALUE (unboxSmallExtendedDouble((uintptr_t)self))
|
|
|
|
#define FORMAT @"%0.16g"
|
|
|
|
#include "NSNumberMethods.h"
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2016-04-19 08:07:53 +00:00
|
|
|
+ (void) load
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
2011-11-17 06:11:36 +00:00
|
|
|
useSmallExtendedDouble = objc_registerSmallObjectClass_np
|
|
|
|
(self, SMALL_EXTENDED_DOUBLE_MASK);
|
2011-11-16 17:29:15 +00:00
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) alloc
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (id) copy
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone*)aZone
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) retain
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2013-01-29 18:42:23 +00:00
|
|
|
- (NSUInteger) retainCount
|
|
|
|
{
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
2011-11-17 06:11:36 +00:00
|
|
|
- (id) autorelease
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (oneway void) release
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2011-11-16 17:29:15 +00:00
|
|
|
@end
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
@interface NSSmallRepeatingDouble : NSFloatingPointNumber
|
|
|
|
@end
|
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
@implementation NSSmallRepeatingDouble
|
|
|
|
#undef VALUE
|
|
|
|
#define VALUE (unboxSmallRepeatingDouble((uintptr_t)self))
|
|
|
|
#define FORMAT @"%0.16g"
|
|
|
|
#include "NSNumberMethods.h"
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (void) load
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
2011-11-17 06:11:36 +00:00
|
|
|
useSmallRepeatingDouble = objc_registerSmallObjectClass_np
|
|
|
|
(self, SMALL_REPEATING_DOUBLE_MASK);
|
2011-11-16 17:29:15 +00:00
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) alloc
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (id) copy
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone*)aZone
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
|
|
|
- (id) retain
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2011-11-17 06:11:36 +00:00
|
|
|
|
2013-01-29 18:42:23 +00:00
|
|
|
- (NSUInteger) retainCount
|
|
|
|
{
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
2011-11-17 06:11:36 +00:00
|
|
|
- (id) autorelease
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (oneway void) release
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2011-11-16 17:29:15 +00:00
|
|
|
@end
|
2012-04-01 07:33:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Technically, all floats are small on 64bit and fit into a NSRepeatingDouble,
|
|
|
|
* but we want to get the description FORMAT right for floats (i.e. "%0.7g" and
|
|
|
|
* not "%0.16g".
|
|
|
|
*/
|
|
|
|
@interface NSSmallFloat : NSSmallRepeatingDouble
|
|
|
|
@end
|
|
|
|
@implementation NSSmallFloat
|
|
|
|
#undef VALUE
|
|
|
|
#define VALUE (unboxSmallRepeatingDouble((uintptr_t)self))
|
|
|
|
#define FORMAT @"%0.7g"
|
|
|
|
#include "NSNumberMethods.h"
|
|
|
|
|
|
|
|
+ (void) load
|
|
|
|
{
|
|
|
|
useSmallFloat = objc_registerSmallObjectClass_np
|
|
|
|
(self, SMALL_FLOAT_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (id) alloc
|
|
|
|
{
|
|
|
|
return (id)SMALL_FLOAT_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
|
|
|
{
|
|
|
|
return (id)SMALL_FLOAT_MASK;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
2011-11-16 17:29:15 +00:00
|
|
|
#endif
|
2011-07-26 19:05:43 +00:00
|
|
|
#endif
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
@implementation NSNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
static Class NSNumberClass;
|
2010-08-18 12:34:56 +00:00
|
|
|
static Class NSBoolNumberClass;
|
2010-02-15 10:58:34 +00:00
|
|
|
static Class NSIntNumberClass;
|
|
|
|
static Class NSLongLongNumberClass;
|
|
|
|
static Class NSUnsignedLongLongNumberClass;
|
|
|
|
static Class NSFloatNumberClass;
|
|
|
|
static Class NSDoubleNumberClass;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-08-18 12:34:56 +00:00
|
|
|
/*
|
|
|
|
* Numbers from -1 to 12 inclusive that are reused.
|
|
|
|
*/
|
|
|
|
static NSNumber *ReusedInstances[14];
|
|
|
|
static NSBoolNumber *boolY; // Boolean YES (integer 1)
|
|
|
|
static NSBoolNumber *boolN; // Boolean NO (integer 0)
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (void) initialize
|
2010-01-24 17:54:31 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
int i;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
if ([NSNumber class] != self)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return;
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
NSNumberClass = self;
|
2010-08-18 12:34:56 +00:00
|
|
|
NSBoolNumberClass = [NSBoolNumber class];
|
2010-02-15 10:58:34 +00:00
|
|
|
NSIntNumberClass = [NSIntNumber class];
|
|
|
|
NSLongLongNumberClass = [NSLongLongNumber class];
|
|
|
|
NSUnsignedLongLongNumberClass = [NSUnsignedLongLongNumber class];
|
|
|
|
NSFloatNumberClass = [NSFloatNumber class];
|
|
|
|
NSDoubleNumberClass = [NSDoubleNumber class];
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2018-12-04 11:09:18 +00:00
|
|
|
boolY = NSAllocateObject(NSBoolNumberClass, 0, 0);
|
2013-08-22 15:44:54 +00:00
|
|
|
[[NSObject leakAt: &boolY] release];
|
2010-08-18 12:34:56 +00:00
|
|
|
boolY->value = 1;
|
2018-12-04 11:09:18 +00:00
|
|
|
boolN = NSAllocateObject(NSBoolNumberClass, 0, 0);
|
2010-08-18 12:34:56 +00:00
|
|
|
boolN->value = 0;
|
2013-08-22 15:44:54 +00:00
|
|
|
[[NSObject leakAt: &boolN] release];
|
2010-08-18 12:34:56 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
for (i = 0; i < 14; i++)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2018-12-04 11:09:18 +00:00
|
|
|
NSIntNumber *n = NSAllocateObject(NSIntNumberClass, 0, 0);
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = i - 1;
|
|
|
|
ReusedInstances[i] = n;
|
2013-08-22 15:44:54 +00:00
|
|
|
[[NSObject leakAt: &ReusedInstances[i]] release];
|
2010-02-15 10:58:34 +00:00
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (const char *) objCType
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-08-18 12:34:56 +00:00
|
|
|
/* All concrete NSNumber types must implement this so we know which one
|
2010-02-15 10:58:34 +00:00
|
|
|
* they are.
|
|
|
|
*/
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return NULL; // Not reached
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (BOOL) isEqualToNumber: (NSNumber*)aNumber
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-26 11:20:21 +00:00
|
|
|
return ([self compare: aNumber] == NSOrderedSame) ? YES : NO;
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (BOOL) isEqual: (id)anObject
|
2009-02-23 20:42:32 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
if ([anObject isKindOfClass: NSNumberClass])
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self isEqualToNumber: anObject];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [super isEqual: anObject];
|
2009-02-23 20:42:32 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (BOOL) isEqualToValue: (NSValue*)aValue
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
if ([aValue isKindOfClass: NSNumberClass])
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self isEqualToNumber: (NSNumber*)aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return NO;
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-09-12 17:05:30 +00:00
|
|
|
- (NSUInteger) hash
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return (unsigned)[self doubleValue];
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSString*) stringValue
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self descriptionWithLocale: nil];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSString*) descriptionWithLocale: (id)aLocale
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return nil; // Not reached
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSComparisonResult) compare: (NSNumber*)aNumber
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return 0; // Not reached
|
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-09-24 19:20:16 +00:00
|
|
|
#define INTEGER_MACRO(encoding,type, ignored, name) \
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) initWith ## name: (type)aValue \
|
|
|
|
{\
|
2010-02-25 18:49:31 +00:00
|
|
|
DESTROY(self);\
|
2010-02-15 10:58:34 +00:00
|
|
|
return [[NSNumberClass numberWith ## name: aValue] retain];\
|
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
#include "GSNumberTypes.h"
|
|
|
|
|
2010-02-19 19:23:03 +00:00
|
|
|
- (id) initWithBool: (BOOL)aValue
|
|
|
|
{
|
2010-02-25 18:49:31 +00:00
|
|
|
DESTROY(self);
|
2010-08-18 12:34:56 +00:00
|
|
|
return [(aValue == 0 ? boolN : boolY) retain];\
|
2010-02-19 19:23:03 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/*
|
|
|
|
* Macro for checking whether this value is the same as one of the singleton
|
2012-04-01 07:33:38 +00:00
|
|
|
* instances.
|
2010-02-15 10:58:34 +00:00
|
|
|
*/
|
|
|
|
#define CHECK_SINGLETON(aValue) \
|
|
|
|
if (aValue >= -1 && aValue <= 12)\
|
|
|
|
{\
|
|
|
|
return ReusedInstances[aValue+1];\
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithBool: (BOOL)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(BOOL)] autorelease];
|
|
|
|
}
|
2010-08-18 12:34:56 +00:00
|
|
|
if (0 == aValue)
|
|
|
|
{
|
|
|
|
return boolN;
|
|
|
|
}
|
|
|
|
return boolY;
|
2010-02-15 10:58:34 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithChar: (signed char)aValue
|
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
2011-04-04 16:35:20 +00:00
|
|
|
objCType: @encode(signed char)] autorelease];
|
2010-06-12 19:13:23 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: aValue];
|
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedChar: (unsigned char)aValue
|
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(unsigned char)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: aValue];
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithShort: (short)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(short)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedShort: (unsigned short)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(unsigned short)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithInt: (int)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
NSIntNumber *n;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(int)] autorelease];
|
|
|
|
}
|
|
|
|
|
2018-12-04 11:09:18 +00:00
|
|
|
CHECK_SINGLETON(aValue);
|
2011-07-26 19:05:43 +00:00
|
|
|
#ifdef OBJC_SMALL_OBJECT_SHIFT
|
2016-04-19 08:07:53 +00:00
|
|
|
if (useSmallInt
|
|
|
|
&& (aValue < (INT_MAX>>OBJC_SMALL_OBJECT_SHIFT))
|
|
|
|
&& (aValue > -(INT_MAX>>OBJC_SMALL_OBJECT_SHIFT)))
|
2011-07-26 19:05:43 +00:00
|
|
|
{
|
2016-04-19 08:07:53 +00:00
|
|
|
return (id)((((NSInteger)aValue) << OBJC_SMALL_OBJECT_SHIFT)
|
|
|
|
| SMALL_INT_MASK);
|
2011-07-26 19:05:43 +00:00
|
|
|
}
|
|
|
|
#endif
|
2018-12-04 11:09:18 +00:00
|
|
|
n = NSAllocateObject(NSIntNumberClass, 0, 0);
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = aValue;
|
2010-02-22 23:49:33 +00:00
|
|
|
return AUTORELEASE(n);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedInt: (unsigned int)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(unsigned int)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2018-12-04 11:09:18 +00:00
|
|
|
CHECK_SINGLETON(aValue);
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aValue < (unsigned int) INT_MAX)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: (int)aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithLongLong: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithLong: (long)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(long)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithLongLong: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedLong: (unsigned long)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(unsigned long)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithUnsignedLongLong: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithLongLong: (long long)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
NSLongLongNumber *n;
|
|
|
|
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(long long)] autorelease];
|
|
|
|
}
|
2018-12-04 11:09:18 +00:00
|
|
|
CHECK_SINGLETON(aValue);
|
2010-02-15 10:58:34 +00:00
|
|
|
if (aValue < (long long)INT_MAX && aValue > (long long)INT_MIN)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: (int) aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2018-12-04 11:09:18 +00:00
|
|
|
n = NSAllocateObject(NSLongLongNumberClass, 0, 0);
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = aValue;
|
2010-02-22 23:49:33 +00:00
|
|
|
return AUTORELEASE(n);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedLongLong: (unsigned long long)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
NSUnsignedLongLongNumber *n;
|
|
|
|
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(unsigned long long)] autorelease];
|
|
|
|
}
|
2010-02-17 12:07:48 +00:00
|
|
|
if (aValue < (unsigned long long) LLONG_MAX)
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithLongLong: (long long) aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2018-12-04 11:09:18 +00:00
|
|
|
n = NSAllocateObject(NSUnsignedLongLongNumberClass, 0, 0);
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = aValue;
|
2010-02-22 23:49:33 +00:00
|
|
|
return AUTORELEASE(n);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithFloat: (float)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
NSFloatNumber *n;
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(float)] autorelease];
|
|
|
|
}
|
2011-11-16 17:29:15 +00:00
|
|
|
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
2012-04-01 07:33:38 +00:00
|
|
|
if (useSmallFloat)
|
2011-11-16 17:29:15 +00:00
|
|
|
{
|
2012-04-01 07:33:38 +00:00
|
|
|
return boxDouble(aValue, SMALL_FLOAT_MASK);
|
2011-11-16 17:29:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
2018-12-04 11:09:18 +00:00
|
|
|
n = NSAllocateObject(NSFloatNumberClass, 0, 0);
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = aValue;
|
2010-02-22 23:49:33 +00:00
|
|
|
return AUTORELEASE(n);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithDouble: (double)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
NSDoubleNumber *n;
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(double)] autorelease];
|
|
|
|
}
|
2011-11-16 17:29:15 +00:00
|
|
|
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
|
|
|
if (useSmallRepeatingDouble && isSmallRepeatingDouble(aValue))
|
|
|
|
{
|
|
|
|
return boxDouble(aValue, SMALL_REPEATING_DOUBLE_MASK);
|
|
|
|
}
|
|
|
|
if (useSmallExtendedDouble && isSmallExtendedDouble(aValue))
|
|
|
|
{
|
|
|
|
return boxDouble(aValue, SMALL_EXTENDED_DOUBLE_MASK);
|
|
|
|
}
|
|
|
|
#endif
|
2018-12-04 11:09:18 +00:00
|
|
|
n = NSAllocateObject(NSDoubleNumberClass, 0, 0);
|
2010-02-15 10:58:34 +00:00
|
|
|
n->value = aValue;
|
2010-02-22 23:49:33 +00:00
|
|
|
return AUTORELEASE(n);
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithInteger: (NSInteger)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(NSInteger)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
// Compile time constant; the compiler will remove this conditional
|
|
|
|
if (sizeof (NSInteger) == sizeof (int))
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithInt: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithLongLong: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
+ (NSNumber *) numberWithUnsignedInteger: (NSUInteger)aValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-06-12 19:13:23 +00:00
|
|
|
if (self != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithBytes: (const void *)&aValue
|
|
|
|
objCType: @encode(NSUInteger)] autorelease];
|
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
// Compile time constant; the compiler will remove this conditional
|
|
|
|
if (sizeof (NSUInteger) == sizeof (unsigned int))
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithUnsignedInt: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self numberWithUnsignedLongLong: aValue];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) initWithBytes: (const void *)
|
|
|
|
value objCType: (const char *)type
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
switch (type[0])
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'c':
|
2011-04-04 16:35:20 +00:00
|
|
|
return [self initWithInteger: *(signed char *) value];
|
2010-02-15 10:58:34 +00:00
|
|
|
case 'C':
|
|
|
|
return [self initWithInteger: *(unsigned char *) value];
|
|
|
|
case 's':
|
|
|
|
return [self initWithInteger: *(short *) value];
|
|
|
|
case 'S':
|
|
|
|
return [self initWithInteger: *(unsigned short *) value];
|
|
|
|
case 'i':
|
|
|
|
return [self initWithInteger: *(int *) value];
|
|
|
|
case 'I':
|
|
|
|
return [self initWithInteger: *(unsigned int *) value];
|
|
|
|
case 'l':
|
|
|
|
return [self initWithLong: *(long *) value];
|
|
|
|
case 'L':
|
|
|
|
return [self initWithUnsignedLong: *(unsigned long *) value];
|
|
|
|
case 'q':
|
|
|
|
return [self initWithLongLong: *(long long *) value];
|
|
|
|
case 'Q':
|
|
|
|
return [self initWithUnsignedLongLong: *(unsigned long long *) value];
|
|
|
|
case 'f':
|
|
|
|
return [self initWithFloat: *(float *) value];
|
|
|
|
case 'd':
|
|
|
|
return [self initWithDouble: *(double *) value];
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
return [super initWithBytes: value objCType: type];
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (void *) pointerValue
|
2009-02-23 20:42:32 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return (void *)[self unsignedIntegerValue];
|
2009-02-23 20:42:32 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) replacementObjectForPortCoder: (NSPortCoder *) encoder
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-14 16:32:02 +00:00
|
|
|
return self;
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (Class) classForCoder
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return NSNumberClass;
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (void) encodeWithCoder: (NSCoder *) coder
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
const char *type = [self objCType];
|
2016-03-25 08:37:36 +00:00
|
|
|
unsigned char charbuf;
|
|
|
|
unsigned short shortbuf;
|
|
|
|
unsigned int intbuf;
|
|
|
|
unsigned long longbuf;
|
|
|
|
unsigned long long llongbuf;
|
|
|
|
float floatbuf;
|
|
|
|
double doublebuf;
|
|
|
|
void *buffer;
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2016-03-25 11:42:23 +00:00
|
|
|
[coder encodeValueOfObjCType: @encode(char) at: type];
|
2016-03-25 08:37:36 +00:00
|
|
|
|
|
|
|
switch (type[0])
|
|
|
|
{
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
buffer = &charbuf; break;
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
buffer = &shortbuf; break;
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
buffer = &intbuf; break;
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
buffer = &longbuf; break;
|
|
|
|
case 'q':
|
|
|
|
case 'Q':
|
|
|
|
buffer = &llongbuf; break;
|
|
|
|
case 'f':
|
|
|
|
buffer = &floatbuf; break;
|
|
|
|
case 'd':
|
|
|
|
buffer = &doublebuf; break;
|
2016-03-25 11:42:23 +00:00
|
|
|
default:
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"unknown NSNumber type '%s'", type];
|
2016-04-17 15:14:34 +00:00
|
|
|
return; // Avoid spurious compiler warning.
|
2016-03-25 08:37:36 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
[self getValue: buffer];
|
|
|
|
[coder encodeValueOfObjCType: type at: buffer];
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) copyWithZone: (NSZone *) aZone
|
1998-03-12 14:21:20 +00:00
|
|
|
{
|
2010-02-19 19:23:03 +00:00
|
|
|
// OSX just returns the receive with no copy.
|
|
|
|
return RETAIN (self);
|
1998-03-12 14:21:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) initWithCoder: (NSCoder *) coder
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
char type[2] = { 0 };
|
2016-03-25 08:37:36 +00:00
|
|
|
unsigned char charbuf;
|
|
|
|
unsigned short shortbuf;
|
|
|
|
unsigned int intbuf;
|
|
|
|
unsigned long longbuf;
|
|
|
|
unsigned long long llongbuf;
|
|
|
|
float floatbuf;
|
|
|
|
double doublebuf;
|
|
|
|
void *buffer;
|
2010-02-15 10:58:34 +00:00
|
|
|
|
2016-03-25 11:42:23 +00:00
|
|
|
[coder decodeValueOfObjCType: @encode(char) at: type];
|
2016-03-25 08:37:36 +00:00
|
|
|
switch (type[0])
|
|
|
|
{
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
buffer = &charbuf; break;
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
buffer = &shortbuf; break;
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
buffer = &intbuf; break;
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
buffer = &longbuf; break;
|
|
|
|
case 'q':
|
|
|
|
case 'Q':
|
|
|
|
buffer = &llongbuf; break;
|
|
|
|
case 'f':
|
|
|
|
buffer = &floatbuf; break;
|
|
|
|
case 'd':
|
|
|
|
buffer = &doublebuf; break;
|
2016-03-25 11:42:23 +00:00
|
|
|
default:
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"unknown NSNumber type '%c'", type[0]];
|
2016-04-17 15:14:34 +00:00
|
|
|
return nil; // Avoid spurious compiler warning.
|
2016-03-25 11:42:23 +00:00
|
|
|
}
|
2010-02-15 10:58:34 +00:00
|
|
|
[coder decodeValueOfObjCType: type at: buffer];
|
|
|
|
return [self initWithBytes: buffer objCType: type];
|
1998-02-05 22:06:20 +00:00
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSString *) description
|
1998-02-05 22:06:20 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
return [self stringValue];
|
|
|
|
}
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2011-07-12 11:40:15 +00:00
|
|
|
/* Return nil for an NSNumber that is allocated and initialized without
|
2010-02-15 10:58:34 +00:00
|
|
|
* providing a real value. Yes, this seems weird, but it is actually what
|
|
|
|
* happens on OS X.
|
2010-02-14 16:32:02 +00:00
|
|
|
*/
|
2010-02-15 10:58:34 +00:00
|
|
|
- (id) init
|
2007-06-14 05:03:35 +00:00
|
|
|
{
|
2011-07-11 12:36:04 +00:00
|
|
|
if (object_getClass(self) != NSNumberClass)
|
|
|
|
{
|
|
|
|
return [super init];
|
|
|
|
}
|
2010-02-25 18:49:31 +00:00
|
|
|
DESTROY(self);
|
2010-02-15 10:58:34 +00:00
|
|
|
return nil;
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
/* Stop the compiler complaining about unimplemented methods. Throwing an
|
|
|
|
* exception here matches OS X behaviour, although they throw an invalid
|
|
|
|
* argument exception.
|
2010-02-14 16:32:02 +00:00
|
|
|
*/
|
2010-09-24 19:20:16 +00:00
|
|
|
#define INTEGER_MACRO(encoding, type, name, ignored) \
|
2010-02-15 10:58:34 +00:00
|
|
|
- (type) name ## Value\
|
|
|
|
{\
|
|
|
|
[self subclassResponsibility: _cmd];\
|
|
|
|
return (type)0;\
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
#include "GSNumberTypes.h"
|
2010-02-19 19:23:03 +00:00
|
|
|
|
|
|
|
- (BOOL) boolValue
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
- (NSDecimal) decimalValue
|
2010-02-14 16:32:02 +00:00
|
|
|
{
|
2010-02-15 10:58:34 +00:00
|
|
|
NSDecimalNumber *dn;
|
|
|
|
NSDecimal decimal;
|
2010-02-14 16:32:02 +00:00
|
|
|
|
2010-02-15 10:58:34 +00:00
|
|
|
dn = [[NSDecimalNumber alloc] initWithString: [self stringValue]];
|
|
|
|
decimal = [dn decimalValue];
|
|
|
|
[dn release];
|
|
|
|
return decimal;
|
2010-02-14 16:32:02 +00:00
|
|
|
}
|
|
|
|
|
1996-02-22 16:02:02 +00:00
|
|
|
@end
|