#include <CoreFoundation/CFNumber.h>
#include "CFInternal.h"
#include <CoreFoundation/CFPriv.h>
#include <math.h>
#include <float.h>
#if DEPLOYMENT_TARGET_WINDOWS
#define isnan(A) _isnan(A)
#define isinf(A) !_finite(A)
#define copysign(A, B) _copysign(A, B)
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
#else
#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
#define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
struct __CFBoolean {
CFRuntimeBase _base;
};
static struct __CFBoolean __kCFBooleanTrue = {
INIT_CFRUNTIME_BASE()
};
const CFBooleanRef kCFBooleanTrue = &__kCFBooleanTrue;
static struct __CFBoolean __kCFBooleanFalse = {
INIT_CFRUNTIME_BASE()
};
const CFBooleanRef kCFBooleanFalse = &__kCFBooleanFalse;
static CFStringRef __CFBooleanCopyDescription(CFTypeRef cf) {
CFBooleanRef boolean = (CFBooleanRef)cf;
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf, CFGetAllocator(cf), (boolean == kCFBooleanTrue) ? "true" : "false");
}
static CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
CFBooleanRef boolean = (CFBooleanRef)cf;
return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false"));
}
static CFHashCode __CFBooleanHash(CFTypeRef cf) {
CFBooleanRef boolean = (CFBooleanRef)cf;
return (boolean == kCFBooleanTrue) ? _CFHashInt(1) : _CFHashInt(0);
}
static void __CFBooleanDeallocate(CFTypeRef cf) {
CFAssert(false, __kCFLogAssertion, "Deallocated CFBoolean!");
}
static CFTypeID __kCFBooleanTypeID = _kCFRuntimeNotATypeID;
static const CFRuntimeClass __CFBooleanClass = {
0,
"CFBoolean",
NULL, NULL, __CFBooleanDeallocate,
NULL,
__CFBooleanHash,
__CFBooleanCopyFormattingDescription,
__CFBooleanCopyDescription
};
__private_extern__ void __CFBooleanInitialize(void) {
__kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass);
_CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue, __kCFBooleanTypeID);
__kCFBooleanTrue._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID);
_CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse, __kCFBooleanTypeID);
__kCFBooleanFalse._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID);
}
CFTypeID CFBooleanGetTypeID(void) {
return __kCFBooleanTypeID;
}
Boolean CFBooleanGetValue(CFBooleanRef boolean) {
CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID, Boolean, boolean, "boolValue");
return (boolean == kCFBooleanTrue) ? true : false;
}
#define OLD_CRAP_TOO 0
#if OLD_CRAP_TOO
typedef union {
SInt32 valSInt32;
int64_t valSInt64;
Float32 valFloat32;
Float64 valFloat64;
} __CFNumberValue_old;
struct __CFNumber_old {
CFRuntimeBase _base;
__CFNumberValue_old value;
};
static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2);
static CFHashCode __CFNumberHash_old(CFTypeRef cf);
static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf);
__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf);
static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions);
static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr);
static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number);
static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number);
static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number);
static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr);
static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context);
#endif
#define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
#define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
#define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
#define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
#define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
#define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
#define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
#define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
#elif DEPLOYMENT_TARGET_WINDOWS
#define FLOAT_POSITIVE_2_TO_THE_64 18446744073709551616.0
#define FLOAT_NEGATIVE_2_TO_THE_127 -170141183460469231731687303715884105728.0
#define FLOAT_POSITIVE_2_TO_THE_127 170141183460469231731687303715884105728.0
#else
#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
typedef struct { int64_t high;
uint64_t low;
} CFSInt128Struct;
enum {
kCFNumberSInt128Type = 17
};
static uint8_t isNeg128(const CFSInt128Struct *in) {
return in->high < 0;
}
static CFComparisonResult cmp128(const CFSInt128Struct *in1, const CFSInt128Struct *in2) {
if (in1->high < in2->high) return kCFCompareLessThan;
if (in1->high > in2->high) return kCFCompareGreaterThan;
if (in1->low < in2->low) return kCFCompareLessThan;
if (in1->low > in2->low) return kCFCompareGreaterThan;
return kCFCompareEqualTo;
}
static void add128(CFSInt128Struct *out, CFSInt128Struct *in1, CFSInt128Struct *in2) {
CFSInt128Struct tmp;
tmp.low = in1->low + in2->low;
tmp.high = in1->high + in2->high;
if (UINT64_MAX - in1->low < in2->low) {
tmp.high++;
}
*out = tmp;
}
static void neg128(CFSInt128Struct *out, CFSInt128Struct *in) {
uint64_t tmplow = ~in->low;
out->low = tmplow + 1;
out->high = ~in->high;
if (UINT64_MAX == tmplow) {
out->high++;
}
}
static const CFSInt128Struct powersOf10[] = {
{ 0x4B3B4CA85A86C47ALL, 0x098A224000000000ULL },
{ 0x0785EE10D5DA46D9LL, 0x00F436A000000000ULL },
{ 0x00C097CE7BC90715LL, 0xB34B9F1000000000ULL },
{ 0x0013426172C74D82LL, 0x2B878FE800000000ULL },
{ 0x0001ED09BEAD87C0LL, 0x378D8E6400000000ULL },
{ 0x0000314DC6448D93LL, 0x38C15B0A00000000ULL },
{ 0x000004EE2D6D415BLL, 0x85ACEF8100000000ULL },
{ 0x0000007E37BE2022LL, 0xC0914B2680000000ULL },
{ 0x0000000C9F2C9CD0LL, 0x4674EDEA40000000ULL },
{ 0x00000001431E0FAELL, 0x6D7217CAA0000000ULL },
{ 0x00000000204FCE5ELL, 0x3E25026110000000ULL },
{ 0x00000000033B2E3CLL, 0x9FD0803CE8000000ULL },
{ 0x000000000052B7D2LL, 0xDCC80CD2E4000000ULL },
{ 0x0000000000084595LL, 0x161401484A000000ULL },
{ 0x000000000000D3C2LL, 0x1BCECCEDA1000000ULL },
{ 0x000000000000152DLL, 0x02C7E14AF6800000ULL },
{ 0x000000000000021ELL, 0x19E0C9BAB2400000ULL },
{ 0x0000000000000036LL, 0x35C9ADC5DEA00000ULL },
{ 0x0000000000000005LL, 0x6BC75E2D63100000ULL },
{ 0x0000000000000000LL, 0x8AC7230489E80000ULL },
{ 0x0000000000000000LL, 0x0DE0B6B3A7640000ULL },
{ 0x0000000000000000LL, 0x016345785D8A0000ULL },
{ 0x0000000000000000LL, 0x002386F26FC10000ULL },
{ 0x0000000000000000LL, 0x00038D7EA4C68000ULL },
{ 0x0000000000000000LL, 0x00005AF3107A4000ULL },
{ 0x0000000000000000LL, 0x000009184E72A000ULL },
{ 0x0000000000000000LL, 0x000000E8D4A51000ULL },
{ 0x0000000000000000LL, 0x000000174876E800ULL },
{ 0x0000000000000000LL, 0x00000002540BE400ULL },
{ 0x0000000000000000LL, 0x000000003B9ACA00ULL },
{ 0x0000000000000000LL, 0x0000000005F5E100ULL },
{ 0x0000000000000000LL, 0x0000000000989680ULL },
{ 0x0000000000000000LL, 0x00000000000F4240ULL },
{ 0x0000000000000000LL, 0x00000000000186A0ULL },
{ 0x0000000000000000LL, 0x0000000000002710ULL },
{ 0x0000000000000000LL, 0x00000000000003E8ULL },
{ 0x0000000000000000LL, 0x0000000000000064ULL },
{ 0x0000000000000000LL, 0x000000000000000AULL },
{ 0x0000000000000000LL, 0x0000000000000001ULL },
};
static const CFSInt128Struct neg_powersOf10[] = {
{ 0xB4C4B357A5793B85LL, 0xF675DDC000000000ULL },
{ 0xF87A11EF2A25B926LL, 0xFF0BC96000000000ULL },
{ 0xFF3F68318436F8EALL, 0x4CB460F000000000ULL },
{ 0xFFECBD9E8D38B27DLL, 0xD478701800000000ULL },
{ 0xFFFE12F64152783FLL, 0xC872719C00000000ULL },
{ 0xFFFFCEB239BB726CLL, 0xC73EA4F600000000ULL },
{ 0xFFFFFB11D292BEA4LL, 0x7A53107F00000000ULL },
{ 0xFFFFFF81C841DFDDLL, 0x3F6EB4D980000000ULL },
{ 0xFFFFFFF360D3632FLL, 0xB98B1215C0000000ULL },
{ 0xFFFFFFFEBCE1F051LL, 0x928DE83560000000ULL },
{ 0xFFFFFFFFDFB031A1LL, 0xC1DAFD9EF0000000ULL },
{ 0xFFFFFFFFFCC4D1C3LL, 0x602F7FC318000000ULL },
{ 0xFFFFFFFFFFAD482DLL, 0x2337F32D1C000000ULL },
{ 0xFFFFFFFFFFF7BA6ALL, 0xE9EBFEB7B6000000ULL },
{ 0xFFFFFFFFFFFF2C3DLL, 0xE43133125F000000ULL },
{ 0xFFFFFFFFFFFFEAD2LL, 0xFD381EB509800000ULL },
{ 0xFFFFFFFFFFFFFDE1LL, 0xE61F36454DC00000ULL },
{ 0xFFFFFFFFFFFFFFC9LL, 0xCA36523A21600000ULL },
{ 0xFFFFFFFFFFFFFFFALL, 0x9438A1D29CF00000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0x7538DCFB76180000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xF21F494C589C0000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFE9CBA87A2760000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFDC790D903F0000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFC72815B398000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFA50CEF85C000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFF6E7B18D6000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFF172B5AF000ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFE8B7891800ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFDABF41C00ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFC4653600ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFA0A1F00ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFF676980ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFF0BDC0ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFE7960ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFD8F0ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFC18ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFF9CULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFF6ULL },
{ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFULL },
};
static void emit128(char *buffer, const CFSInt128Struct *in, Boolean forcePlus) {
CFSInt128Struct tmp = *in;
if (isNeg128(&tmp)) {
neg128(&tmp, &tmp);
*buffer++ = '-';
} else if (forcePlus) {
*buffer++ = '+';
}
Boolean doneOne = false;
int idx;
for (idx = 0; idx < sizeof(powersOf10) / sizeof(powersOf10[0]); idx++) {
int count = 0;
while (cmp128(&powersOf10[idx], &tmp) <= 0) {
add128(&tmp, &tmp, (CFSInt128Struct *)&neg_powersOf10[idx]);
count++;
}
if (0 != count || doneOne) {
*buffer++ = '0' + count;
doneOne = true;
}
}
if (!doneOne) {
*buffer++ = '0';
}
*buffer = '\0';
}
static void cvtSInt128ToFloat64(Float64 *out, const CFSInt128Struct *in) {
Boolean wasNeg = false;
CFSInt128Struct tmp = *in;
if (isNeg128(&tmp)) {
neg128(&tmp, &tmp);
wasNeg = true;
}
Float64 d = (Float64)tmp.high * FLOAT_POSITIVE_2_TO_THE_64 + (Float64)tmp.low;
if (wasNeg) d = -d;
*out = d;
}
static void cvtFloat64ToSInt128(CFSInt128Struct *out, const Float64 *in) {
CFSInt128Struct i;
Float64 d = *in;
if (d < FLOAT_NEGATIVE_2_TO_THE_127) {
i.high = 0x8000000000000000LL;
i.low = 0x0000000000000000ULL;
*out = i;
return;
}
if (FLOAT_POSITIVE_2_TO_THE_127<= d) {
i.high = 0x7fffffffffffffffLL;
i.low = 0xffffffffffffffffULL;
*out = i;
return;
}
Float64 t = floor(d / FLOAT_POSITIVE_2_TO_THE_64);
i.high = (int64_t)t;
i.low = (uint64_t)(d - t * FLOAT_POSITIVE_2_TO_THE_64);
*out = i;
}
struct __CFNumber {
CFRuntimeBase _base;
#if OLD_CRAP_TOO
struct __CFNumber_old *__old__;
void * __dummy__;
#endif
uint64_t _pad;
};
static struct __CFNumber __kCFNumberNaN = {
INIT_CFRUNTIME_BASE(), 0ULL
};
const CFNumberRef kCFNumberNaN = &__kCFNumberNaN;
static struct __CFNumber __kCFNumberNegativeInfinity = {
INIT_CFRUNTIME_BASE(), 0ULL
};
const CFNumberRef kCFNumberNegativeInfinity = &__kCFNumberNegativeInfinity;
static struct __CFNumber __kCFNumberPositiveInfinity = {
INIT_CFRUNTIME_BASE(), 0ULL
};
const CFNumberRef kCFNumberPositiveInfinity = &__kCFNumberPositiveInfinity;
static const struct {
uint16_t canonicalType:5; uint16_t floatBit:1; uint16_t storageBit:1; uint16_t lgByteSize:3; uint16_t unused:6;
} __CFNumberTypeTable[] = {
{0, 0, 0, 0},
{kCFNumberSInt8Type, 0, 0, 0, 0},
{kCFNumberSInt16Type, 0, 0, 1, 0},
{kCFNumberSInt32Type, 0, 0, 2, 0},
{kCFNumberSInt64Type, 0, 0, 3, 0},
{kCFNumberFloat32Type, 1, 0, 2, 0},
{kCFNumberFloat64Type, 1, 1, 3, 0},
{kCFNumberSInt8Type, 0, 0, 0, 0},
{kCFNumberSInt16Type, 0, 0, 1, 0},
{kCFNumberSInt32Type, 0, 0, 2, 0},
#if __LP64__
{kCFNumberSInt64Type, 0, 0, 3, 0},
#else
{kCFNumberSInt32Type, 0, 0, 2, 0},
#endif
{kCFNumberSInt64Type, 0, 0, 3, 0},
{kCFNumberFloat32Type, 1, 0, 2, 0},
{kCFNumberFloat64Type, 1, 1, 3, 0},
#if __LP64__
{kCFNumberSInt64Type, 0, 0, 3, 0},
{kCFNumberSInt64Type, 0, 0, 3, 0},
{kCFNumberFloat64Type, 1, 1, 3, 0},
#else
{kCFNumberSInt32Type, 0, 0, 2, 0},
{kCFNumberSInt32Type, 0, 0, 2, 0},
{kCFNumberFloat32Type, 1, 0, 2, 0},
#endif
{kCFNumberSInt128Type, 0, 1, 4, 0},
};
CF_INLINE CFNumberType __CFNumberGetType(CFNumberRef num) {
return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
}
#define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
} while (0)
#define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
DST_TYPE dv; Boolean noLoss = false; \
if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
dv = DST_MAX; \
} else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
dv = DST_MIN; \
} else { \
dv = (DST_TYPE)sv.low; \
noLoss = true; \
} \
memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
return noLoss; \
} while (0)
static Boolean __CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
type = __CFNumberTypeTable[type].canonicalType;
CFNumberType ntype = __CFNumberGetType(number);
const void *data = &(number->_pad);
switch (type) {
case kCFNumberSInt8Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(Float32, int8_t, INT8_MIN, INT8_MAX);
} else {
CVT(Float64, int8_t, INT8_MIN, INT8_MAX);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(int64_t, int8_t, INT8_MIN, INT8_MAX);
} else {
CVT128ToInt(CFSInt128Struct, int8_t, INT8_MIN, INT8_MAX);
}
}
return true;
case kCFNumberSInt16Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(Float32, int16_t, INT16_MIN, INT16_MAX);
} else {
CVT(Float64, int16_t, INT16_MIN, INT16_MAX);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(int64_t, int16_t, INT16_MIN, INT16_MAX);
} else {
CVT128ToInt(CFSInt128Struct, int16_t, INT16_MIN, INT16_MAX);
}
}
return true;
case kCFNumberSInt32Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(Float32, int32_t, INT32_MIN, INT32_MAX);
} else {
CVT(Float64, int32_t, INT32_MIN, INT32_MAX);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(int64_t, int32_t, INT32_MIN, INT32_MAX);
} else {
CVT128ToInt(CFSInt128Struct, int32_t, INT32_MIN, INT32_MAX);
}
}
return true;
case kCFNumberSInt64Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(Float32, int64_t, INT64_MIN, INT64_MAX);
} else {
CVT(Float64, int64_t, INT64_MIN, INT64_MAX);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
memmove(valuePtr, data, 8);
} else {
CVT128ToInt(CFSInt128Struct, int64_t, INT64_MIN, INT64_MAX);
}
}
return true;
case kCFNumberSInt128Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
Float32 f;
memmove(&f, data, 4);
Float64 d = f;
CFSInt128Struct i;
cvtFloat64ToSInt128(&i, &d);
memmove(valuePtr, &i, 16);
Float64 d2;
cvtSInt128ToFloat64(&d2, &i);
Float32 f2 = (Float32)d2;
return (f2 == f);
} else {
Float64 d;
memmove(&d, data, 8);
CFSInt128Struct i;
cvtFloat64ToSInt128(&i, &d);
memmove(valuePtr, &i, 16);
Float64 d2;
cvtSInt128ToFloat64(&d2, &i);
return (d2 == d);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
int64_t j;
memmove(&j, data, 8);
CFSInt128Struct i;
i.low = j;
i.high = (j < 0) ? -1LL : 0LL;
memmove(valuePtr, &i, 16);
} else {
memmove(valuePtr, data, 16);
}
}
return true;
case kCFNumberFloat32Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
memmove(valuePtr, data, 4);
} else {
double d;
memmove(&d, data, 8);
if (isnan(d)) {
uint32_t l = 0x7fc00000;
memmove(valuePtr, &l, 4);
return true;
} else if (isinf(d)) {
uint32_t l = 0x7f800000;
if (d < 0.0) l += 0x80000000UL;
memmove(valuePtr, &l, 4);
return true;
}
CVT(Float64, Float32, -FLT_MAX, FLT_MAX);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(int64_t, Float32, -FLT_MAX, FLT_MAX);
} else {
CFSInt128Struct i;
memmove(&i, data, 16);
Float64 d;
cvtSInt128ToFloat64(&d, &i);
Float32 f = (Float32)d;
memmove(valuePtr, &f, 4);
d = f;
CFSInt128Struct i2;
cvtFloat64ToSInt128(&i2, &d);
return cmp128(&i2, &i) == kCFCompareEqualTo;
}
}
return true;
case kCFNumberFloat64Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
float f;
memmove(&f, data, 4);
if (isnan(f)) {
uint64_t l = BITSFORDOUBLENAN;
memmove(valuePtr, &l, 8);
return true;
} else if (isinf(f)) {
uint64_t l = BITSFORDOUBLEPOSINF;
if (f < 0.0) l += 0x8000000000000000ULL;
memmove(valuePtr, &l, 8);
return true;
}
CVT(Float32, Float64, -DBL_MAX, DBL_MAX);
} else {
memmove(valuePtr, data, 8);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT(int64_t, Float64, -DBL_MAX, DBL_MAX);
} else {
CFSInt128Struct i;
memmove(&i, data, 16);
Float64 d;
cvtSInt128ToFloat64(&d, &i);
memmove(valuePtr, &d, 8);
CFSInt128Struct i2;
cvtFloat64ToSInt128(&i2, &d);
return cmp128(&i2, &i) == kCFCompareEqualTo;
}
}
return true;
}
return false;
}
#define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
DST_TYPE dv = (DST_TYPE)(sv); \
memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
} while (0)
#define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
DST_TYPE dv; dv = (DST_TYPE)sv.low; \
memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
} while (0)
static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, void *valuePtr) {
type = __CFNumberTypeTable[type].canonicalType;
CFNumberType ntype = __CFNumberGetType(number);
const void *data = &(number->_pad);
switch (type) {
case kCFNumberSInt8Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(Float32, int8_t, 0);
} else {
CVT_COMPAT(Float64, int8_t, 0);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
int64_t sv; memmove(&sv, data, sizeof(int64_t));
int8_t dv = (int8_t)(sv);
memmove(valuePtr, &dv, sizeof(int8_t));
int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 8LL) == 0LL) || (vv == sv);
} else {
CVT128ToInt_COMPAT(CFSInt128Struct, int8_t);
}
}
return true;
case kCFNumberSInt16Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(Float32, int16_t, 0);
} else {
CVT_COMPAT(Float64, int16_t, 0);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
int64_t sv; memmove(&sv, data, sizeof(int64_t));
int16_t dv = (int16_t)(sv);
memmove(valuePtr, &dv, sizeof(int16_t));
int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 16LL) == 0LL) || (vv == sv);
} else {
CVT128ToInt_COMPAT(CFSInt128Struct, int16_t);
}
}
return true;
case kCFNumberSInt32Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(Float32, int32_t, 0);
} else {
CVT_COMPAT(Float64, int32_t, 0);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(int64_t, int32_t, 0);
} else {
CVT128ToInt_COMPAT(CFSInt128Struct, int32_t);
}
}
return true;
case kCFNumberSInt64Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(Float32, int64_t, 0);
} else {
CVT_COMPAT(Float64, int64_t, 0);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(int64_t, int64_t, 0);
} else {
CVT128ToInt_COMPAT(CFSInt128Struct, int64_t);
}
}
return true;
case kCFNumberSInt128Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
Float32 f;
memmove(&f, data, 4);
Float64 d = f;
CFSInt128Struct i;
cvtFloat64ToSInt128(&i, &d);
memmove(valuePtr, &i, 16);
Float64 d2;
cvtSInt128ToFloat64(&d2, &i);
Float32 f2 = (Float32)d2;
return (f2 == f);
} else {
Float64 d;
memmove(&d, data, 8);
CFSInt128Struct i;
cvtFloat64ToSInt128(&i, &d);
memmove(valuePtr, &i, 16);
Float64 d2;
cvtSInt128ToFloat64(&d2, &i);
return (d2 == d);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
int64_t j;
memmove(&j, data, 8);
CFSInt128Struct i;
i.low = j;
i.high = (j < 0) ? -1LL : 0LL;
memmove(valuePtr, &i, 16);
} else {
memmove(valuePtr, data, 16);
}
}
return true;
case kCFNumberFloat32Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
memmove(valuePtr, data, 4);
} else {
CVT_COMPAT(Float64, Float32, 0);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(int64_t, Float32, 0);
} else {
CFSInt128Struct i;
memmove(&i, data, 16);
Float64 d;
cvtSInt128ToFloat64(&d, &i);
Float32 f = (Float32)d;
memmove(valuePtr, &f, 4);
d = f;
CFSInt128Struct i2;
cvtFloat64ToSInt128(&i2, &d);
return cmp128(&i2, &i) == kCFCompareEqualTo;
}
}
return true;
case kCFNumberFloat64Type:
if (__CFNumberTypeTable[ntype].floatBit) {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(Float32, Float64, 0);
} else {
memmove(valuePtr, data, 8);
}
} else {
if (0 == __CFNumberTypeTable[ntype].storageBit) {
CVT_COMPAT(int64_t, Float64, 0);
} else {
CFSInt128Struct i;
memmove(&i, data, 16);
Float64 d;
cvtSInt128ToFloat64(&d, &i);
memmove(valuePtr, &d, 8);
CFSInt128Struct i2;
cvtFloat64ToSInt128(&i2, &d);
return cmp128(&i2, &i) == kCFCompareEqualTo;
}
}
return true;
}
return false;
}
#if OLD_CRAP_TOO
static void FAIL(void) {}
#endif
static CFStringRef __CFNumberCopyDescription(CFTypeRef cf) {
CFNumberRef number = (CFNumberRef)cf;
CFNumberType type = __CFNumberGetType(number);
CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
if (__CFNumberTypeTable[type].floatBit) {
Float64 d;
__CFNumberGetValue(number, kCFNumberFloat64Type, &d);
if (isnan(d)) {
CFStringAppend(mstr, CFSTR("nan"));
} else if (isinf(d)) {
CFStringAppend(mstr, (0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
} else if (0.0 == d) {
CFStringAppend(mstr, (copysign(1.0, d) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
} else {
CFStringAppendFormat(mstr, NULL, CFSTR("%+.*f"), (__CFNumberTypeTable[type].storageBit ? 20 : 10), d);
}
const char *typeName = "unknown float";
switch (type) {
case kCFNumberFloat32Type: typeName = "kCFNumberFloat32Type"; break;
case kCFNumberFloat64Type: typeName = "kCFNumberFloat64Type"; break;
}
CFStringAppendFormat(mstr, NULL, CFSTR(", type = %s}"), typeName);
} else {
CFSInt128Struct i;
__CFNumberGetValue(number, kCFNumberSInt128Type, &i);
char buffer[128];
emit128(buffer, &i, true);
const char *typeName = "unknown integer";
switch (type) {
case kCFNumberSInt8Type: typeName = "kCFNumberSInt8Type"; break;
case kCFNumberSInt16Type: typeName = "kCFNumberSInt16Type"; break;
case kCFNumberSInt32Type: typeName = "kCFNumberSInt32Type"; break;
case kCFNumberSInt64Type: typeName = "kCFNumberSInt64Type"; break;
case kCFNumberSInt128Type: typeName = "kCFNumberSInt128Type"; break;
}
CFStringAppendFormat(mstr, NULL, CFSTR("%s, type = %s}"), buffer, typeName);
}
#if OLD_CRAP_TOO
if (! number->__old__) {
printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf);
} else {
CFStringRef test = __CFNumberCopyDescription_old(number->__old__);
if (!CFEqual(test, mstr)) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test, mstr); FAIL();
}
}
#endif
return mstr;
}
static CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_new(CFTypeRef cf) {
Float64 d;
CFNumberGetValue((CFNumberRef)cf, kCFNumberFloat64Type, &d);
if (isnan(d)) {
return (CFStringRef)CFRetain(CFSTR("nan"));
}
if (isinf(d)) {
return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
}
if (0.0 == d) {
return (CFStringRef)CFRetain(CFSTR("0.0"));
}
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
}
__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) {
CFStringRef result = __CFNumberCopyFormattingDescriptionAsFloat64_new(cf);
#if OLD_CRAP_TOO
CFNumberRef number = (CFNumberRef)cf;
if (! number->__old__) {
printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf);
} else {
CFStringRef test = __CFNumberCopyFormattingDescriptionAsFloat64_old(number->__old__);
if (!CFEqual(test, result)) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test, result); FAIL();
}
}
#endif
return result;
}
static CFStringRef __CFNumberCopyFormattingDescription_new(CFTypeRef cf, CFDictionaryRef formatOptions) {
CFNumberRef number = (CFNumberRef)cf;
CFNumberType type = __CFNumberGetType(number);
if (__CFNumberTypeTable[type].floatBit) {
return __CFNumberCopyFormattingDescriptionAsFloat64(number);
}
CFSInt128Struct i;
__CFNumberGetValue(number, kCFNumberSInt128Type, &i);
char buffer[128];
emit128(buffer, &i, false);
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%s"), buffer);
}
static CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions);
#if OLD_CRAP_TOO
CFNumberRef number = (CFNumberRef)cf;
if (! number->__old__) {
printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf);
} else {
CFStringRef test = __CFNumberCopyFormattingDescription_old(number->__old__, formatOptions);
if (!CFEqual(test, result)) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test, result); FAIL();
}
}
#endif
return result;
}
static Boolean __CFNumberEqual(CFTypeRef cf1, CFTypeRef cf2) {
Boolean b = CFNumberCompare((CFNumberRef)cf1, (CFNumberRef)cf2, 0) == kCFCompareEqualTo;
#if OLD_CRAP_TOO
CFNumberRef number1 = (CFNumberRef)cf1;
CFNumberRef number2 = (CFNumberRef)cf2;
if (! number1->__old__ || !number2->__old__) {
printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1, cf2);
} else {
Boolean b2 = __CFNumberEqual_old(number1->__old__, number2->__old__);
if (b2 != b) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2, b); FAIL();
}
}
#endif
return b;
}
static CFHashCode __CFNumberHash(CFTypeRef cf) {
CFHashCode h;
CFNumberRef number = (CFNumberRef)cf;
switch (__CFNumberGetType(number)) {
case kCFNumberSInt8Type:
case kCFNumberSInt16Type:
case kCFNumberSInt32Type: {
SInt32 i;
__CFNumberGetValue(number, kCFNumberSInt32Type, &i);
h = _CFHashInt(i);
break;
}
default: {
Float64 d;
__CFNumberGetValue(number, kCFNumberFloat64Type, &d);
h = _CFHashDouble((double)d);
break;
}
}
#if OLD_CRAP_TOO
CFNumberRef number1 = (CFNumberRef)cf;
if (! number1->__old__) {
printf("*** Test skipped in __CFNumberHash for number %p\n", cf);
} else {
CFHashCode h2 = __CFNumberHash_old(number1->__old__);
if (h2 != h) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2, h); FAIL();
}
}
#endif
return h;
}
static CFTypeID __kCFNumberTypeID = _kCFRuntimeNotATypeID;
static const CFRuntimeClass __CFNumberClass = {
0,
"CFNumber",
NULL, NULL, NULL,
__CFNumberEqual,
__CFNumberHash,
__CFNumberCopyFormattingDescription,
__CFNumberCopyDescription
};
__private_extern__ void __CFNumberInitialize(void) {
__kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass);
_CFRuntimeSetInstanceTypeID(&__kCFNumberNaN, __kCFNumberTypeID);
__kCFNumberNaN._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNaN._pad = BITSFORDOUBLENAN;
_CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity, __kCFNumberTypeID);
__kCFNumberNegativeInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF;
_CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity, __kCFNumberTypeID);
__kCFNumberPositiveInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF;
}
CFTypeID CFNumberGetTypeID(void) {
return __kCFNumberTypeID;
}
#define MinCachedInt (-1)
#define MaxCachedInt (12)
#define NotToBeCached (MinCachedInt - 1)
static CFNumberRef __CFNumberCache[MaxCachedInt - MinCachedInt + 1] = {NULL};
CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
__CFAssertIsValidNumberType(type);
if (!allocator) allocator = __CFGetDefaultAllocator();
int64_t valToBeCached = NotToBeCached;
if (__CFNumberTypeTable[type].floatBit) {
CFNumberRef cached = NULL;
if (0 == __CFNumberTypeTable[type].storageBit) {
Float32 f = *(Float32 *)valuePtr;
if (isnan(f)) cached = kCFNumberNaN;
if (isinf(f)) cached = (f < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
} else {
Float64 d = *(Float64 *)valuePtr;
if (isnan(d)) cached = kCFNumberNaN;
if (isinf(d)) cached = (d < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
}
if (cached) return (CFNumberRef)CFRetain(cached);
} else if (kCFAllocatorSystemDefault == allocator) {
switch (__CFNumberTypeTable[type].canonicalType) {
case kCFNumberSInt8Type: {int8_t val = *(int8_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
case kCFNumberSInt16Type: {int16_t val = *(int16_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
case kCFNumberSInt32Type: {int32_t val = *(int32_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
case kCFNumberSInt64Type: {int64_t val = *(int64_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
}
if (NotToBeCached != valToBeCached) {
CFNumberRef cached = __CFNumberCache[valToBeCached - MinCachedInt]; if (NULL != cached) return (CFNumberRef)CFRetain(cached);
}
}
CFIndex size = 8 + ((!__CFNumberTypeTable[type].floatBit && __CFNumberTypeTable[type].storageBit) ? 8 : 0);
#if OLD_CRAP_TOO
size += 2 * sizeof(void *);
#endif
CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, size, NULL);
if (NULL == result) {
return NULL;
}
__CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)__CFNumberTypeTable[type].canonicalType);
#if OLD_CRAP_TOO
((struct __CFNumber *)result)->__old__ = CFNumberCreate_old(allocator, type, valuePtr);
CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result->__old__));
#endif
if (NotToBeCached != valToBeCached) {
memmove((void *)&result->_pad, &valToBeCached, 8);
CFNumberType origType = __CFNumberGetType(result);
__CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)kCFNumberSInt32Type);
if (OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)result, (void *volatile *)&__CFNumberCache[valToBeCached - MinCachedInt])) {
CFRetain(result);
} else {
__CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)origType);
}
return result;
}
uint64_t value;
switch (__CFNumberTypeTable[type].canonicalType) {
case kCFNumberSInt8Type: value = (uint64_t)(int64_t)*(int8_t *)valuePtr; goto smallVal;
case kCFNumberSInt16Type: value = (uint64_t)(int64_t)*(int16_t *)valuePtr; goto smallVal;
case kCFNumberSInt32Type: value = (uint64_t)(int64_t)*(int32_t *)valuePtr; goto smallVal;
smallVal: memmove((void *)&result->_pad, &value, 8); break;
case kCFNumberSInt64Type: memmove((void *)&result->_pad, valuePtr, 8); break;
case kCFNumberSInt128Type: memmove((void *)&result->_pad, valuePtr, 16); break;
case kCFNumberFloat32Type: memmove((void *)&result->_pad, valuePtr, 4); break;
case kCFNumberFloat64Type: memmove((void *)&result->_pad, valuePtr, 8); break;
}
return result;
}
CFNumberType CFNumberGetType(CFNumberRef number) {
CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID, CFNumberType, number, "_cfNumberType");
__CFAssertIsNumber(number);
CFNumberType type = __CFNumberGetType(number);
if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; #if OLD_CRAP_TOO
if (! number->__old__) {
printf("*** Test skipped in CFNumberGetType for number %p\n", number);
} else {
CFNumberType t2 = CFNumberGetType_old(number->__old__);
if (t2 != type) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2, type); FAIL();
}
}
#endif
return type;
}
CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) {
__CFAssertIsNumber(number);
return __CFNumberGetType(number);
}
CFIndex CFNumberGetByteSize(CFNumberRef number) {
__CFAssertIsNumber(number);
CFIndex r = 1 << __CFNumberTypeTable[CFNumberGetType(number)].lgByteSize;
#if OLD_CRAP_TOO
if (! number->__old__) {
printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number);
} else {
CFIndex r2 = CFNumberGetByteSize_old(number->__old__);
if (r2 != r) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2, r); FAIL();
}
}
#endif
return r;
}
Boolean CFNumberIsFloatType(CFNumberRef number) {
__CFAssertIsNumber(number);
Boolean r = __CFNumberTypeTable[CFNumberGetType(number)].floatBit;
#if OLD_CRAP_TOO
if (! number->__old__) {
printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number);
} else {
Boolean r2 = CFNumberIsFloatType_old(number->__old__);
if (r2 != r) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2, r); FAIL();
}
}
#endif
return r;
}
Boolean CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID, Boolean, number, "_getValue:forType:", valuePtr, __CFNumberTypeTable[type].canonicalType);
__CFAssertIsNumber(number);
__CFAssertIsValidNumberType(type);
uint8_t localMemory[128];
Boolean r = __CFNumberGetValueCompat(number, type, valuePtr ? valuePtr : localMemory);
#if OLD_CRAP_TOO
if (! number->__old__) {
printf("*** Test skipped in CFNumberGetValue for number %p\n", number);
} else {
uint8_t localMemory2[128];
Boolean r2 = CFNumberGetValue_old(number->__old__, type, localMemory2);
if (r2 != r) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2, r); FAIL();
}
if (0 != memcmp(localMemory2, valuePtr, CFNumberGetByteSize(number))) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME")); FAIL();
}
}
#endif
return r;
}
static CFComparisonResult CFNumberCompare_new(CFNumberRef number1, CFNumberRef number2, void *context) {
CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number1, "compare:", number2);
CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number2, "_reverseCompare:", number1);
__CFAssertIsNumber(number1);
__CFAssertIsNumber(number2);
CFNumberType type1 = __CFNumberGetType(number1);
CFNumberType type2 = __CFNumberGetType(number2);
if (!__CFNumberTypeTable[type1].floatBit && !__CFNumberTypeTable[type2].floatBit) {
CFSInt128Struct i1, i2;
__CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
__CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
return cmp128(&i1, &i2);
}
if (__CFNumberTypeTable[type1].floatBit && __CFNumberTypeTable[type2].floatBit) {
Float64 d1, d2;
__CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
__CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
double s1 = copysign(1.0, d1);
double s2 = copysign(1.0, d2);
if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
if (s1 < s2) return kCFCompareLessThan;
if (s2 < s1) return kCFCompareGreaterThan;
if (d1 < d2) return kCFCompareLessThan;
if (d2 < d1) return kCFCompareGreaterThan;
return kCFCompareEqualTo;
}
Boolean swapResult = false;
if (__CFNumberTypeTable[type2].floatBit) {
CFNumberRef tmp = number1;
number1 = number2;
number2 = tmp;
swapResult = true;
}
Float64 d1, d2;
__CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
if (d1 < FLOAT_NEGATIVE_2_TO_THE_127) {
return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
}
if (FLOAT_POSITIVE_2_TO_THE_127 <= d1) {
return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
}
CFSInt128Struct i1, i2;
__CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
__CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
CFComparisonResult res = cmp128(&i1, &i2);
if (kCFCompareEqualTo != res) {
return !swapResult ? res : -res;
}
if (isnan(d1)) {
if (isNeg128(&i2)) {
return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
}
return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
}
double s1 = copysign(1.0, d1);
double s2 = isNeg128(&i2) ? -1.0 : 1.0;
if (s1 < s2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
if (s2 < s1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
__CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
if (d1 < d2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
if (d2 < d1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
return kCFCompareEqualTo;
}
CFComparisonResult CFNumberCompare(CFNumberRef number1, CFNumberRef number2, void *context) {
CFComparisonResult r = CFNumberCompare_new(number1, number2, context);
#if OLD_CRAP_TOO
if (! number1->__old__ || !number2->__old__) {
printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1, number2);
} else {
CFComparisonResult r2 = CFNumberCompare_old(number1->__old__, number2->__old__, context);
if (r2 != r) {
CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2, r); FAIL();
}
}
#endif
return r;
}
#if OLD_CRAP_TOO
static const unsigned char __CFNumberCanonicalType[kCFNumberMaxType + 1] = {
0, kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
};
static const unsigned char __CFNumberStorageType[kCFNumberMaxType + 1] = {
0, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
};
static CFNumberType __CFNumberGetStorageTypeForType_old(CFNumberType type) {
return __CFNumberStorageType[type];
}
static CFNumberType __CFNumberGetCanonicalTypeForType_old(CFNumberType type) {
return __CFNumberCanonicalType[type];
}
static CFNumberType __CFNumberGetType_old(struct __CFNumber_old * num) {
return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
}
static Boolean __CFNumberTypeIsFloat_old(CFNumberType type) {
return (type == kCFNumberFloat64Type) || (type == kCFNumberFloat32Type) || (type == kCFNumberDoubleType) || (type == kCFNumberFloatType);
}
static CFIndex __CFNumberSizeOfType_old(CFNumberType type) {
switch (type) {
case kCFNumberSInt8Type: return sizeof(int8_t);
case kCFNumberSInt16Type: return sizeof(int16_t);
case kCFNumberSInt32Type: return sizeof(SInt32);
case kCFNumberSInt64Type: return sizeof(int64_t);
case kCFNumberFloat32Type: return sizeof(Float32);
case kCFNumberFloat64Type: return sizeof(Float64);
default: printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
}
}
#define SET_VALUE(valueUnion, type, valuePtr) \
switch (type) { \
case kCFNumberSInt8Type: (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
case kCFNumberSInt16Type: (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break; \
case kCFNumberSInt32Type: (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
case kCFNumberSInt64Type: (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break; \
case kCFNumberFloat32Type: (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break; \
case kCFNumberFloat64Type: (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break; \
default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
}
#define GET_VALUE(value, type, resultPtr) \
switch (type) { \
case kCFNumberSInt8Type: *(int8_t *)(resultPtr) = (int8_t)value; break; \
case kCFNumberSInt16Type: *(int16_t *)(resultPtr) = (int16_t)value; break; \
case kCFNumberSInt32Type: *(SInt32 *)(resultPtr) = (SInt32)value; break; \
case kCFNumberSInt64Type: *(int64_t *)(resultPtr) = (int64_t)value; break; \
case kCFNumberFloat32Type: *(Float32 *)(resultPtr) = (Float32)value; break; \
case kCFNumberFloat64Type: *(Float64 *)(resultPtr) = (Float64)value; break; \
default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
}
static void __CFNumberGetValue_old(const __CFNumberValue_old *value, CFNumberType numberType, CFNumberType typeToGet, void *valuePtr) {
switch (numberType) {
case kCFNumberSInt32Type: GET_VALUE(value->valSInt32, typeToGet, valuePtr); break;
case kCFNumberSInt64Type: GET_VALUE(value->valSInt64, typeToGet, valuePtr); break;
case kCFNumberFloat32Type: GET_VALUE(value->valFloat32, typeToGet, valuePtr); break;
case kCFNumberFloat64Type: GET_VALUE(value->valFloat64, typeToGet, valuePtr); break;
default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
}
}
static Boolean __CFNumberEqualValue_old(const __CFNumberValue_old *value1, CFNumberType type1, const __CFNumberValue_old *value2, CFNumberType type2) {
if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
Float64 d1, d2;
__CFNumberGetValue_old(value1, type1, kCFNumberFloat64Type, &d1);
__CFNumberGetValue_old(value2, type2, kCFNumberFloat64Type, &d2);
if (isnan(d1) && isnan(d2)) return true; return d1 == d2;
} else {
int64_t i1, i2;
__CFNumberGetValue_old(value1, type1, kCFNumberSInt64Type, &i1);
__CFNumberGetValue_old(value2, type2, kCFNumberSInt64Type, &i2);
return i1 == i2;
}
}
static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2) {
struct __CFNumber_old * number1 = (struct __CFNumber_old *)cf1;
struct __CFNumber_old * number2 = (struct __CFNumber_old *)cf2;
return __CFNumberEqualValue_old(&(number1->value), __CFNumberGetType_old(number1), &(number2->value), __CFNumberGetType_old(number2));
}
static CFHashCode __CFNumberHash_old(CFTypeRef cf) {
struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
switch (__CFNumberGetType_old((struct __CFNumber_old *)cf)) {
case kCFNumberSInt32Type: return _CFHashInt(number->value.valSInt32);
case kCFNumberSInt64Type: return _CFHashDouble((double)(number->value.valSInt64));
case kCFNumberFloat32Type: return _CFHashDouble((double)(number->value.valFloat32));
case kCFNumberFloat64Type: return _CFHashDouble((double)(number->value.valFloat64));
default: printf("*** WARNING default case in __CFNumberHash_old\n");
return 0;
}
}
#define BUFFER_SIZE 100
#define emitChar(ch) \
{if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
static void __CFNumberEmitInt64_old(CFMutableStringRef mstr, int64_t value, int32_t width, UniChar pad, bool explicitPlus) {
UniChar stackBuf[BUFFER_SIZE], *buf = stackBuf;
uint64_t uvalue, factor, tmp;
int32_t w;
bool neg;
neg = (value < 0) ? true : false;
uvalue = (neg) ? -value : value;
if (neg || explicitPlus) width--;
width--;
factor = 1;
tmp = uvalue;
while (9 < tmp) {
width--;
factor *= 10;
tmp /= 10;
}
for (w = 0; w < width; w++) emitChar(pad);
if (neg) {
emitChar('-');
} else if (explicitPlus) {
emitChar('+');
}
while (0 < factor) {
UniChar ch = '0' + (UniChar)(uvalue / factor);
uvalue %= factor;
emitChar(ch);
factor /= 10;
}
if (buf > stackBuf) CFStringAppendCharacters(mstr, stackBuf, buf - stackBuf);
}
static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf) {
struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
switch (__CFNumberGetType_old(number)) {
case kCFNumberSInt32Type:
__CFNumberEmitInt64_old(mstr, number->value.valSInt32, 0, ' ', true);
CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt32Type}"));
break;
case kCFNumberSInt64Type:
__CFNumberEmitInt64_old(mstr, number->value.valSInt64, 0, ' ', true);
CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt64Type}"));
break;
case kCFNumberFloat32Type:
if (isnan(number->value.valFloat32)) {
CFStringAppend(mstr, CFSTR("nan"));
} else if (isinf(number->value.valFloat32)) {
CFStringAppend(mstr, (0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
} else if (0.0f == number->value.valFloat32) {
CFStringAppend(mstr, (copysign(1.0, number->value.valFloat32) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
} else {
CFStringAppendFormat(mstr, NULL, CFSTR("%+.10f"), number->value.valFloat32);
}
CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat32Type}"));
break;
case kCFNumberFloat64Type:
if (isnan(number->value.valFloat64)) {
CFStringAppend(mstr, CFSTR("nan"));
} else if (isinf(number->value.valFloat64)) {
CFStringAppend(mstr, (0.0 < number->value.valFloat64) ? CFSTR("+infinity") : CFSTR("-infinity"));
} else if (0.0 == number->value.valFloat64) {
CFStringAppend(mstr, (copysign(1.0, number->value.valFloat64) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
} else {
CFStringAppendFormat(mstr, NULL, CFSTR("%+.20f"), number->value.valFloat64);
}
CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat64Type}"));
break;
default:
CFRelease(mstr);
return NULL;
}
return mstr;
}
__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf) {
double d;
CFNumberGetValue_old((struct __CFNumber_old *)cf, kCFNumberFloat64Type, &d);
if (isnan(d)) {
return (CFStringRef)CFRetain(CFSTR("nan"));
}
if (isinf(d)) {
return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
}
if (0.0 == d) {
return (CFStringRef)CFRetain(CFSTR("0.0"));
}
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
}
static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions) {
struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
CFMutableStringRef mstr;
int64_t value;
switch (__CFNumberGetType_old(number)) {
case kCFNumberSInt32Type:
case kCFNumberSInt64Type:
value = (__CFNumberGetType_old(number) == kCFNumberSInt32Type) ? number->value.valSInt32 : number->value.valSInt64;
mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
__CFNumberEmitInt64_old(mstr, value, 0, ' ', false);
return mstr;
case kCFNumberFloat32Type:
if (isnan(number->value.valFloat32)) {
return (CFStringRef)CFRetain(CFSTR("nan"));
}
if (isinf(number->value.valFloat32)) {
return (CFStringRef)CFRetain((0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
}
if (0.0f == number->value.valFloat32) {
return (CFStringRef)CFRetain(CFSTR("0.0"));
}
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), FLT_DIG + 2, number->value.valFloat32);
case kCFNumberFloat64Type:
return __CFNumberCopyFormattingDescriptionAsFloat64_old(number);
break;
default:
return NULL;
}
}
static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
struct __CFNumber_old * num;
CFNumberType equivType, storageType;
if (type == 17) {
CFSInt128Struct *s = valuePtr;
s->high = (int64_t)s->low;
type = kCFNumberSInt64Type;
}
equivType = __CFNumberGetCanonicalTypeForType_old(type);
storageType = __CFNumberGetStorageTypeForType_old(type);
num = (struct __CFNumber_old *)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, __CFNumberSizeOfType_old(storageType), NULL);
if (NULL == num) {
return NULL;
}
SET_VALUE((__CFNumberValue_old *)&(num->value), equivType, valuePtr);
__CFBitfieldSetValue(((struct __CFNumber_old *)num)->_base._cfinfo[CF_INFO_BITS], 6, 0, (uint8_t)storageType);
if (__CFNumberGetType_old(num) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num, storageType);
return num;
}
static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number) {
return __CFNumberGetType_old(number);
}
static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number) {
return __CFNumberSizeOfType_old(CFNumberGetType_old(number));
}
static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number) {
return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number));
}
static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr) {
uint8_t localMemory[sizeof(__CFNumberValue_old)];
__CFNumberValue_old localValue;
CFNumberType numType;
CFNumberType storageTypeForType;
if (type == 17) type = kCFNumberSInt64Type;
storageTypeForType = __CFNumberGetStorageTypeForType_old(type);
type = __CFNumberGetCanonicalTypeForType_old(type);
if (!valuePtr) valuePtr = &localMemory;
numType = __CFNumberGetType_old(number);
__CFNumberGetValue_old((__CFNumberValue_old *)&(number->value), numType, type, valuePtr);
if (numType == storageTypeForType) return true;
SET_VALUE(&localValue, type, valuePtr);
return __CFNumberEqualValue_old(&localValue, storageTypeForType, &(number->value), numType);
}
static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context) {
CFNumberType type1, type2;
type1 = __CFNumberGetType_old(number1);
type2 = __CFNumberGetType_old(number2);
if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
Float64 d1, d2;
double s1, s2;
__CFNumberGetValue_old(&(number1->value), type1, kCFNumberFloat64Type, &d1);
__CFNumberGetValue_old(&(number2->value), type2, kCFNumberFloat64Type, &d2);
s1 = copysign(1.0, d1);
s2 = copysign(1.0, d2);
if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
if (s1 < s2) return kCFCompareLessThan;
if (s2 < s1) return kCFCompareGreaterThan;
if (d1 < d2) return kCFCompareLessThan;
if (d2 < d1) return kCFCompareGreaterThan;
return kCFCompareEqualTo;
} else {
int64_t i1, i2;
__CFNumberGetValue_old(&(number1->value), type1, kCFNumberSInt64Type, &i1);
__CFNumberGetValue_old(&(number2->value), type2, kCFNumberSInt64Type, &i2);
return (i1 > i2) ? kCFCompareGreaterThan : ((i1 < i2) ? kCFCompareLessThan : kCFCompareEqualTo);
}
}
#endif
#undef __CFAssertIsBoolean
#undef __CFAssertIsNumber
#undef __CFAssertIsValidNumberType
#undef BITSFORDOUBLENAN
#undef BITSFORDOUBLEPOSINF
#undef BITSFORDOUBLENEGINF
#undef MinCachedInt
#undef MaxCachedInt
#undef NotToBeCached