mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +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
This commit is contained in:
parent
79ce6ac700
commit
99cb20ae16
9 changed files with 472 additions and 3534 deletions
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
27
Source/GSNumberTypes.h
Normal 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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
3147
Source/NSNumber.m
3147
Source/NSNumber.m
File diff suppressed because it is too large
Load diff
21
Source/NSNumberMethods.h
Normal file
21
Source/NSNumberMethods.h
Normal 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
|
Loading…
Reference in a new issue