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
This commit is contained in:
David Chisnall 2010-02-14 12:57:44 +00:00
parent 79ce6ac700
commit 99cb20ae16
9 changed files with 472 additions and 3534 deletions

View file

@ -1,3 +1,7 @@
2010-02-14 David Chisnall <theraven@sucs.org>
Rewrote NSNumber implementation.
2010-02-14 Richard Frith-Macdonald <rfm@gnu.org>
Major change merge back of 'reorg' branch into trunk.

View file

@ -308,7 +308,7 @@ extern "C" {
* <desc>%0.16g</desc>
* </deflist>
*/
- (NSString*) descriptionWithLocale: (NSDictionary*)locale;
- (NSString*) descriptionWithLocale: (id)locale;
/**
* Compares receiver with otherNumber, using C type conversion if necessary,

View file

@ -185,7 +185,6 @@ NSCopyObject.m \
NSCountedSet.m \
NSConcreteHashTable.m \
NSConcreteMapTable.m \
NSConcreteNumber.m \
NSConnection.m \
NSData.m \
NSDate.m \
@ -312,7 +311,6 @@ BASE_MFILES += GSFFCallInvocation.m
endif
BASE_OTHER_SRCFILES = \
NSConcreteNumberTemplate.m \
GSConcreteValueTemplate.m \
GSTemplateValue.m \
dld-load.h \

27
Source/GSNumberTypes.h Normal file
View file

@ -0,0 +1,27 @@
/**
* GSNumberTypes expects the INTEGER_MACRO macro to be defined. This macro is
* invoked once for every type and its Objective-C name. Use this file when
* implementing things like the -unsignedIntValue family of methods. For this
* case, the macro will be invoked with unsigned int as the type and
* unsignedInt as the name.
*
*/
#ifndef INTEGER_MACRO
#error Define INTEGER_MACRO(type, name, capitalizedName) before including GSNumberTypes.h
#endif
INTEGER_MACRO(double, double, Double)
INTEGER_MACRO(float, float, Float)
INTEGER_MACRO(signed char, char, Char)
INTEGER_MACRO(int, int, Int)
INTEGER_MACRO(short, short, Short)
INTEGER_MACRO(long, long, Long)
INTEGER_MACRO(BOOL, bool, Bool)
INTEGER_MACRO(NSInteger, integer, Integer)
INTEGER_MACRO(NSUInteger, unsignedInteger, UnsignedInteger)
INTEGER_MACRO(long long, longLong, LongLong)
INTEGER_MACRO(unsigned char, unsignedChar, UnsignedChar)
INTEGER_MACRO(unsigned short, unsignedShort, UnsignedShort)
INTEGER_MACRO(unsigned int, unsignedInt, UnsignedInt)
INTEGER_MACRO(unsigned long, unsignedLong, UnsignedLong)
INTEGER_MACRO(unsigned long long, unsignedLongLong, UnsignedLongLong)
#undef INTEGER_MACRO

View file

@ -1,105 +0,0 @@
/* NSConcreteNumber - Interface for Concrete NSNumber classes
Copyright (C) 1993,1994 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@boulder.colorado.edu>
Date: Mar 1995
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "Foundation/NSValue.h"
@interface NSBoolNumber : NSNumber
{
BOOL data;
}
@end
@interface NSUCharNumber : NSNumber
{
unsigned char data;
}
@end
@interface NSCharNumber : NSNumber
{
signed char data;
}
@end
@interface NSUShortNumber : NSNumber
{
unsigned short data;
}
@end
@interface NSShortNumber : NSNumber
{
signed short data;
}
@end
@interface NSUIntNumber : NSNumber
{
unsigned int data;
}
@end
@interface NSIntNumber : NSNumber
{
signed int data;
}
@end
@interface NSULongNumber : NSNumber
{
unsigned long data;
}
@end
@interface NSLongNumber : NSNumber
{
signed long data;
}
@end
@interface NSULongLongNumber : NSNumber
{
unsigned long long data;
}
@end
@interface NSLongLongNumber : NSNumber
{
signed long long data;
}
@end
@interface NSFloatNumber : NSNumber
{
float data;
}
@end
@interface NSDoubleNumber : NSNumber
{
double data;
}
@end

View file

@ -1,85 +0,0 @@
/* NSConcreteNumber - Handle preprocessor magic for NSConcreteNumberTemplate
Copyright (C) 1993,1994 Free Software Foundation, Inc.
Written by: Andrew Ruder <andy@aeruder.net>
Date: May 2006
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "config.h"
#import "GNUstepBase/preface.h"
#import "GNUstepBase/GSConfig.h"
#import "Foundation/NSObjCRuntime.h"
#import "Foundation/NSString.h"
#import "Foundation/NSException.h"
#import "Foundation/NSCoder.h"
#import "NSConcreteNumber.h"
#import "GSPrivate.h"
#define TYPE_ORDER 0
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 1
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 2
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 3
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 4
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 5
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 6
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 7
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 8
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 9
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 10
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 11
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER
#define TYPE_ORDER 12
#include "NSConcreteNumberTemplate.m"
#undef TYPE_ORDER

View file

@ -1,613 +0,0 @@
# line 1 "NSConcreteNumberTemplate.m" /* So gdb knows which file we are in */
/* NSConcreteNumberTemplate - Object encapsulation of numbers
Copyright (C) 1993, 1994, 1996, 2000 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@boulder.colorado.edu>
Date: Mar 1995
Rewrite: Richard Frith-Macdonald <rfm@gnu.org>
Date: Mar 2000
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
/* This file should be run through a preprocessor with the macro TYPE_ORDER
defined to a number from 0 to 12 corresponding to each number type */
#if TYPE_ORDER == 0
# define NumberTemplate NSBoolNumber
# define TYPE_TYPE BOOL
#elif TYPE_ORDER == 1
# define NumberTemplate NSCharNumber
# define TYPE_TYPE signed char
#elif TYPE_ORDER == 2
# define NumberTemplate NSUCharNumber
# define TYPE_TYPE unsigned char
#elif TYPE_ORDER == 3
# define NumberTemplate NSShortNumber
# define TYPE_TYPE signed short
#elif TYPE_ORDER == 4
# define NumberTemplate NSUShortNumber
# define TYPE_TYPE unsigned short
#elif TYPE_ORDER == 5
# define NumberTemplate NSIntNumber
# define TYPE_TYPE signed int
#elif TYPE_ORDER == 6
# define NumberTemplate NSUIntNumber
# define TYPE_TYPE unsigned int
#elif TYPE_ORDER == 7
# define NumberTemplate NSLongNumber
# define TYPE_TYPE signed long
#elif TYPE_ORDER == 8
# define NumberTemplate NSULongNumber
# define TYPE_TYPE unsigned long
#elif TYPE_ORDER == 9
# define NumberTemplate NSLongLongNumber
# define TYPE_TYPE signed long long
#elif TYPE_ORDER == 10
# define NumberTemplate NSULongLongNumber
# define TYPE_TYPE unsigned long long
#elif TYPE_ORDER == 11
# define NumberTemplate NSFloatNumber
# define TYPE_TYPE float
#elif TYPE_ORDER == 12
# define NumberTemplate NSDoubleNumber
# define TYPE_TYPE double
#endif
@implementation NumberTemplate
- (id) initWithBytes: (const void*)value objCType: (const char*)type
{
typedef __typeof__(data) _dt;
data = *(const _dt*)value;
return self;
}
/*
* 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
{
union {
double d;
unsigned char c[sizeof(double)];
} val;
unsigned hash = 0;
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 GSPrivateSmallHash((int)data);
}
#endif
val.d = [self doubleValue];
for (i = 0; i < sizeof(double); i++)
{
hash = (hash << 5) + hash + val.c[i];
}
return hash;
}
- (BOOL) boolValue
{
return (BOOL)data;
}
- (signed char) charValue
{
return (signed char)data;
}
- (double) doubleValue
{
return (double)data;
}
- (float) floatValue
{
return (float)data;
}
- (signed int) intValue
{
return (signed int)data;
}
- (signed long long) longLongValue
{
return (signed long long)data;
}
- (signed long) longValue
{
return (signed long)data;
}
- (signed short) shortValue
{
return (signed short)data;
}
- (unsigned char) unsignedCharValue
{
return (unsigned char)data;
}
- (unsigned int) unsignedIntValue
{
return (unsigned int)data;
}
- (unsigned long long) unsignedLongLongValue
{
return (unsigned long long)data;
}
- (unsigned long) unsignedLongValue
{
return (unsigned long)data;
}
- (unsigned short) unsignedShortValue
{
return (unsigned short)data;
}
- (NSComparisonResult) compare: (NSNumber*)other
{
if (other == self)
{
return NSOrderedSame;
}
else if (other == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"nil argument for compare:"];
}
else
{
GSNumberInfo *info = GSNumberInfoFromObject(other);
switch (info->typeLevel)
{
case 0:
{
BOOL oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#if GS_SIZEOF_CHAR < GS_SIZEOF_SHORT && TYPE_ORDER < 3
#define PT (short)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_INT && TYPE_ORDER < 5
#define PT (int)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 1:
{
signed char oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 0
#if GS_SIZEOF_CHAR < GS_SIZEOF_SHORT && TYPE_ORDER < 3
#define PT (short)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_INT && TYPE_ORDER < 5
#define PT (int)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 2:
{
unsigned char oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#if GS_SIZEOF_CHAR < GS_SIZEOF_SHORT && TYPE_ORDER < 3
#define PT (short)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_INT && TYPE_ORDER < 5
#define PT (int)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_CHAR < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 3:
{
signed short oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 0
#if GS_SIZEOF_SHORT < GS_SIZEOF_INT && TYPE_ORDER < 5
#define PT (int)
#elif GS_SIZEOF_SHORT < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_SHORT < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 4:
{
unsigned short oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#if GS_SIZEOF_SHORT < GS_SIZEOF_INT && TYPE_ORDER < 5
#define PT (int)
#elif GS_SIZEOF_SHORT < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_SHORT < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 5:
{
signed int oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 0
#if GS_SIZEOF_INT < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_INT < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 6:
{
unsigned int oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#if GS_SIZEOF_INT < GS_SIZEOF_LONG && TYPE_ORDER < 7
#define PT (long)
#elif GS_SIZEOF_INT < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 7:
{
signed long oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 0
#if GS_SIZEOF_LONG < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 8:
{
unsigned long oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#if GS_SIZEOF_LONG < GS_SIZEOF_LONG_LONG && TYPE_ORDER < 9
#define PT (long long)
#else
#define PT (double)
#endif
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 9:
{
signed long long oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 0
#define PT (double)
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 10:
{
unsigned long long oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if (TYPE_ORDER & 1) == 1
#define PT (double)
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 11:
{
float oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#if TYPE_ORDER != 11
#define PT (double)
#else
#define PT
#endif
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
case 12:
{
double oData;
(*(info->getValue))(other, @selector(getValue:), (void*)&oData);
#undef PT
#define PT (double)
if (PT data == PT oData)
return NSOrderedSame;
else if (PT data < PT oData)
return NSOrderedAscending;
else
return NSOrderedDescending;
}
default:
[NSException raise: NSInvalidArgumentException
format: @"number type value for comparison"];
return NSOrderedSame;
}
}
return 0; /* Quiet warnings */
}
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
{
#if TYPE_ORDER == 0
return (data) ? @"YES" : @"NO";
#else
NSString *result = [NSString alloc];
#if TYPE_ORDER == 1
result = [result initWithFormat: @"%i" locale: locale, (int)data];
#elif TYPE_ORDER == 2
result = [result initWithFormat: @"%u" locale: locale, (unsigned int)data];
#elif TYPE_ORDER == 3
result = [result initWithFormat: @"%hi" locale: locale, data];
#elif TYPE_ORDER == 4
result = [result initWithFormat: @"%hu" locale: locale, data];
#elif TYPE_ORDER == 5
result = [result initWithFormat: @"%i" locale: locale, data];
#elif TYPE_ORDER == 6
result = [result initWithFormat: @"%u" locale: locale, data];
#elif TYPE_ORDER == 7
result = [result initWithFormat: @"%li" locale: locale, data];
#elif TYPE_ORDER == 8
result = [result initWithFormat: @"%lu" locale: locale, data];
#elif TYPE_ORDER == 9
result = [result initWithFormat: @"%lli" locale: locale, data];
#elif TYPE_ORDER == 10
result = [result initWithFormat: @"%llu" locale: locale, data];
#elif TYPE_ORDER == 11
result = [result initWithFormat: @"%0.7g" locale: locale, (double)data];
#elif TYPE_ORDER == 12
result = [result initWithFormat: @"%0.16g" locale: locale, data];
#endif
return AUTORELEASE(result);
#endif
}
- (id) copy
{
if (NSShouldRetainWithZone(self, NSDefaultMallocZone()))
return RETAIN(self);
else
return NSCopyObject(self, 0, NSDefaultMallocZone());
}
- (id) copyWithZone: (NSZone*)zone
{
if (NSShouldRetainWithZone(self, zone))
return RETAIN(self);
else
return NSCopyObject(self, 0, zone);
}
// Override these from NSValue
- (void) getValue: (void*)value
{
if (value == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"Cannot copy value into NULL pointer"];
/* NOT REACHED */
}
memcpy(value, &data, objc_sizeof_type(@encode(TYPE_TYPE)));
}
- (const char*) objCType
{
return @encode(TYPE_TYPE);
}
- (id) nonretainedObjectValue
{
return (id)(void*)&data;
}
- (void*) pointerValue
{
return (void*)&data;
}
// NSCoding
/*
* Exact mirror of NSNumber abstract class coding method.
*/
- (void) encodeWithCoder: (NSCoder*)coder
{
const char *t = @encode(TYPE_TYPE);
[coder encodeValueOfObjCType: @encode(signed char) at: t];
[coder encodeValueOfObjCType: t at: &data];
}
/*
* NSNumber objects should have been encoded with their class set to the
* abstract class. If they haven't then we must be encoding from an old
* archive, so we must implement the old initWithCoder: method.
*/
- (id) initWithCoder: (NSCoder*)coder
{
[coder decodeValueOfObjCType: @encode(TYPE_TYPE) at: &data];
return self;
}
@end
#undef TYPE_TYPE
#undef NumberTemplate
#undef PT

File diff suppressed because it is too large Load diff

21
Source/NSNumberMethods.h Normal file
View file

@ -0,0 +1,21 @@
#define INTEGER_MACRO(type, name, ignored) \
- (type) name ## Value\
{\
return (type)VALUE;\
}
#include "GSNumberTypes.h"
- (const char *)objCType
{
return @encode(typeof(VALUE));
}
- (NSString*)descriptionWithLocale: (id)aLocale
{
return [[[NSString alloc] initWithFormat: FORMAT
locale: aLocale, VALUE] autorelease];
}
- (void)getValue: (void*)buffer
{
typeof(VALUE) *ptr = buffer;
*ptr = VALUE;
}
#undef FORMAT