2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Ali Ozer
28 #include <CoreFoundation/CFNumber.h>
29 #include "CFInternal.h"
34 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
40 static struct __CFBoolean __kCFBooleanTrue
= {
43 const CFBooleanRef kCFBooleanTrue
= &__kCFBooleanTrue
;
45 static struct __CFBoolean __kCFBooleanFalse
= {
48 const CFBooleanRef kCFBooleanFalse
= &__kCFBooleanFalse
;
50 static CFStringRef
__CFBooleanCopyDescription(CFTypeRef cf
) {
51 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
52 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf
, CFGetAllocator(cf
), (boolean
== kCFBooleanTrue
) ? "true" : "false");
55 static CFStringRef
__CFBooleanCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
56 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
57 return (CFStringRef
)CFRetain((boolean
== kCFBooleanTrue
) ? CFSTR("true") : CFSTR("false"));
60 static void __CFBooleanDeallocate(CFTypeRef cf
) {
61 CFAssert(false, __kCFLogAssertion
, "Deallocated CFBoolean!");
64 static CFTypeID __kCFBooleanTypeID
= _kCFRuntimeNotATypeID
;
66 static const CFRuntimeClass __CFBooleanClass
= {
71 __CFBooleanDeallocate
,
74 __CFBooleanCopyFormattingDescription
,
75 __CFBooleanCopyDescription
78 __private_extern__
void __CFBooleanInitialize(void) {
79 __kCFBooleanTypeID
= _CFRuntimeRegisterClass(&__CFBooleanClass
);
80 _CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue
, __kCFBooleanTypeID
);
81 __kCFBooleanTrue
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
82 _CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse
, __kCFBooleanTypeID
);
83 __kCFBooleanFalse
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
86 CFTypeID
CFBooleanGetTypeID(void) {
87 return __kCFBooleanTypeID
;
90 Boolean
CFBooleanGetValue(CFBooleanRef boolean
) {
91 CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID
, Boolean
, boolean
, "boolValue");
92 return (boolean
== kCFBooleanTrue
) ? true : false;
98 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
99 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
101 /* The IEEE bit patterns... Also have:
102 0x7f800000 float +Inf
104 0xff800000 float -Inf
106 #define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
107 #define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
108 #define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
110 #if DEPLOYMENT_TARGET_MACOSX
111 #define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
112 #define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
113 #define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
116 typedef struct { // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
122 kCFNumberSInt128Type
= 17
125 static uint8_t isNeg128(const CFSInt128Struct
*in
) {
129 static CFComparisonResult
cmp128(const CFSInt128Struct
*in1
, const CFSInt128Struct
*in2
) {
130 if (in1
->high
< in2
->high
) return kCFCompareLessThan
;
131 if (in1
->high
> in2
->high
) return kCFCompareGreaterThan
;
132 if (in1
->low
< in2
->low
) return kCFCompareLessThan
;
133 if (in1
->low
> in2
->low
) return kCFCompareGreaterThan
;
134 return kCFCompareEqualTo
;
137 // allows out to be the same as in1 or in2
138 static void add128(CFSInt128Struct
*out
, CFSInt128Struct
*in1
, CFSInt128Struct
*in2
) {
140 tmp
.low
= in1
->low
+ in2
->low
;
141 tmp
.high
= in1
->high
+ in2
->high
;
142 if (UINT64_MAX
- in1
->low
< in2
->low
) {
148 // allows out to be the same as in
149 static void neg128(CFSInt128Struct
*out
, CFSInt128Struct
*in
) {
150 uint64_t tmplow
= ~in
->low
;
151 out
->low
= tmplow
+ 1;
152 out
->high
= ~in
->high
;
153 if (UINT64_MAX
== tmplow
) {
158 static const CFSInt128Struct powersOf10
[] = {
159 { 0x4B3B4CA85A86C47ALL
, 0x098A224000000000ULL
},
160 { 0x0785EE10D5DA46D9LL
, 0x00F436A000000000ULL
},
161 { 0x00C097CE7BC90715LL
, 0xB34B9F1000000000ULL
},
162 { 0x0013426172C74D82LL
, 0x2B878FE800000000ULL
},
163 { 0x0001ED09BEAD87C0LL
, 0x378D8E6400000000ULL
},
164 { 0x0000314DC6448D93LL
, 0x38C15B0A00000000ULL
},
165 { 0x000004EE2D6D415BLL
, 0x85ACEF8100000000ULL
},
166 { 0x0000007E37BE2022LL
, 0xC0914B2680000000ULL
},
167 { 0x0000000C9F2C9CD0LL
, 0x4674EDEA40000000ULL
},
168 { 0x00000001431E0FAELL
, 0x6D7217CAA0000000ULL
},
169 { 0x00000000204FCE5ELL
, 0x3E25026110000000ULL
},
170 { 0x00000000033B2E3CLL
, 0x9FD0803CE8000000ULL
},
171 { 0x000000000052B7D2LL
, 0xDCC80CD2E4000000ULL
},
172 { 0x0000000000084595LL
, 0x161401484A000000ULL
},
173 { 0x000000000000D3C2LL
, 0x1BCECCEDA1000000ULL
},
174 { 0x000000000000152DLL
, 0x02C7E14AF6800000ULL
},
175 { 0x000000000000021ELL
, 0x19E0C9BAB2400000ULL
},
176 { 0x0000000000000036LL
, 0x35C9ADC5DEA00000ULL
},
177 { 0x0000000000000005LL
, 0x6BC75E2D63100000ULL
},
178 { 0x0000000000000000LL
, 0x8AC7230489E80000ULL
},
179 { 0x0000000000000000LL
, 0x0DE0B6B3A7640000ULL
},
180 { 0x0000000000000000LL
, 0x016345785D8A0000ULL
},
181 { 0x0000000000000000LL
, 0x002386F26FC10000ULL
},
182 { 0x0000000000000000LL
, 0x00038D7EA4C68000ULL
},
183 { 0x0000000000000000LL
, 0x00005AF3107A4000ULL
},
184 { 0x0000000000000000LL
, 0x000009184E72A000ULL
},
185 { 0x0000000000000000LL
, 0x000000E8D4A51000ULL
},
186 { 0x0000000000000000LL
, 0x000000174876E800ULL
},
187 { 0x0000000000000000LL
, 0x00000002540BE400ULL
},
188 { 0x0000000000000000LL
, 0x000000003B9ACA00ULL
},
189 { 0x0000000000000000LL
, 0x0000000005F5E100ULL
},
190 { 0x0000000000000000LL
, 0x0000000000989680ULL
},
191 { 0x0000000000000000LL
, 0x00000000000F4240ULL
},
192 { 0x0000000000000000LL
, 0x00000000000186A0ULL
},
193 { 0x0000000000000000LL
, 0x0000000000002710ULL
},
194 { 0x0000000000000000LL
, 0x00000000000003E8ULL
},
195 { 0x0000000000000000LL
, 0x0000000000000064ULL
},
196 { 0x0000000000000000LL
, 0x000000000000000AULL
},
197 { 0x0000000000000000LL
, 0x0000000000000001ULL
},
200 static const CFSInt128Struct neg_powersOf10
[] = {
201 { 0xB4C4B357A5793B85LL
, 0xF675DDC000000000ULL
},
202 { 0xF87A11EF2A25B926LL
, 0xFF0BC96000000000ULL
},
203 { 0xFF3F68318436F8EALL
, 0x4CB460F000000000ULL
},
204 { 0xFFECBD9E8D38B27DLL
, 0xD478701800000000ULL
},
205 { 0xFFFE12F64152783FLL
, 0xC872719C00000000ULL
},
206 { 0xFFFFCEB239BB726CLL
, 0xC73EA4F600000000ULL
},
207 { 0xFFFFFB11D292BEA4LL
, 0x7A53107F00000000ULL
},
208 { 0xFFFFFF81C841DFDDLL
, 0x3F6EB4D980000000ULL
},
209 { 0xFFFFFFF360D3632FLL
, 0xB98B1215C0000000ULL
},
210 { 0xFFFFFFFEBCE1F051LL
, 0x928DE83560000000ULL
},
211 { 0xFFFFFFFFDFB031A1LL
, 0xC1DAFD9EF0000000ULL
},
212 { 0xFFFFFFFFFCC4D1C3LL
, 0x602F7FC318000000ULL
},
213 { 0xFFFFFFFFFFAD482DLL
, 0x2337F32D1C000000ULL
},
214 { 0xFFFFFFFFFFF7BA6ALL
, 0xE9EBFEB7B6000000ULL
},
215 { 0xFFFFFFFFFFFF2C3DLL
, 0xE43133125F000000ULL
},
216 { 0xFFFFFFFFFFFFEAD2LL
, 0xFD381EB509800000ULL
},
217 { 0xFFFFFFFFFFFFFDE1LL
, 0xE61F36454DC00000ULL
},
218 { 0xFFFFFFFFFFFFFFC9LL
, 0xCA36523A21600000ULL
},
219 { 0xFFFFFFFFFFFFFFFALL
, 0x9438A1D29CF00000ULL
},
220 { 0xFFFFFFFFFFFFFFFFLL
, 0x7538DCFB76180000ULL
},
221 { 0xFFFFFFFFFFFFFFFFLL
, 0xF21F494C589C0000ULL
},
222 { 0xFFFFFFFFFFFFFFFFLL
, 0xFE9CBA87A2760000ULL
},
223 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFDC790D903F0000ULL
},
224 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFC72815B398000ULL
},
225 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFA50CEF85C000ULL
},
226 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFF6E7B18D6000ULL
},
227 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFF172B5AF000ULL
},
228 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFE8B7891800ULL
},
229 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFDABF41C00ULL
},
230 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFC4653600ULL
},
231 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFA0A1F00ULL
},
232 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFF676980ULL
},
233 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFF0BDC0ULL
},
234 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFE7960ULL
},
235 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFD8F0ULL
},
236 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFC18ULL
},
237 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFF9CULL
},
238 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFF6ULL
},
239 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFFFULL
},
242 static void emit128(char *buffer
, const CFSInt128Struct
*in
, Boolean forcePlus
) {
243 CFSInt128Struct tmp
= *in
;
244 if (isNeg128(&tmp
)) {
247 } else if (forcePlus
) {
250 Boolean doneOne
= false;
252 for (idx
= 0; idx
< sizeof(powersOf10
) / sizeof(powersOf10
[0]); idx
++) {
254 while (cmp128(&powersOf10
[idx
], &tmp
) <= 0) {
255 add128(&tmp
, &tmp
, (CFSInt128Struct
*)&neg_powersOf10
[idx
]);
258 if (0 != count
|| doneOne
) {
259 *buffer
++ = '0' + count
;
269 static void cvtSInt128ToFloat64(Float64
*out
, const CFSInt128Struct
*in
) {
270 // switching to a positive number results in better accuracy
271 // for negative numbers close to zero, because the multiply
272 // of -1 by 2^64 (scaling the Float64 high) is avoided
273 Boolean wasNeg
= false;
274 CFSInt128Struct tmp
= *in
;
275 if (isNeg128(&tmp
)) {
279 Float64 d
= (Float64
)tmp
.high
* FLOAT_POSITIVE_2_TO_THE_64
+ (Float64
)tmp
.low
;
284 static void cvtFloat64ToSInt128(CFSInt128Struct
*out
, const Float64
*in
) {
287 if (d
< FLOAT_NEGATIVE_2_TO_THE_127
) {
288 i
.high
= 0x8000000000000000LL
;
289 i
.low
= 0x0000000000000000ULL
;
293 if (FLOAT_POSITIVE_2_TO_THE_127
<= d
) {
294 i
.high
= 0x7fffffffffffffffLL
;
295 i
.low
= 0xffffffffffffffffULL
;
299 Float64 t
= floor(d
/ FLOAT_POSITIVE_2_TO_THE_64
);
301 i
.low
= (uint64_t)(d
- t
* FLOAT_POSITIVE_2_TO_THE_64
);
307 uint64_t _pad
; // need this space here for the constant objects
308 /* 0 or 8 more bytes allocated here */
311 /* Seven bits in base:
313 Bits 4..0: CFNumber type
316 static struct __CFNumber __kCFNumberNaN
= {
317 INIT_CFRUNTIME_BASE(), 0ULL
319 const CFNumberRef kCFNumberNaN
= &__kCFNumberNaN
;
321 static struct __CFNumber __kCFNumberNegativeInfinity
= {
322 INIT_CFRUNTIME_BASE(), 0ULL
324 const CFNumberRef kCFNumberNegativeInfinity
= &__kCFNumberNegativeInfinity
;
326 static struct __CFNumber __kCFNumberPositiveInfinity
= {
327 INIT_CFRUNTIME_BASE(), 0ULL
329 const CFNumberRef kCFNumberPositiveInfinity
= &__kCFNumberPositiveInfinity
;
331 static const struct {
332 uint16_t canonicalType
:5; // canonical fixed-width type
333 uint16_t floatBit
:1; // is float
334 uint16_t storageBit
:1; // storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
335 uint16_t lgByteSize
:3; // base-2 log byte size of public type
337 } __CFNumberTypeTable
[] = {
338 /* 0 */ {0, 0, 0, 0},
340 /* kCFNumberSInt8Type */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
341 /* kCFNumberSInt16Type */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
342 /* kCFNumberSInt32Type */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
343 /* kCFNumberSInt64Type */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
344 /* kCFNumberFloat32Type */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
345 /* kCFNumberFloat64Type */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
347 /* kCFNumberCharType */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
348 /* kCFNumberShortType */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
349 /* kCFNumberIntType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
351 /* kCFNumberLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
353 /* kCFNumberLongType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
355 /* kCFNumberLongLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
356 /* kCFNumberFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
357 /* kCFNumberDoubleType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
360 /* kCFNumberCFIndexType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
361 /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
362 /* kCFNumberCGFloatType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
364 /* kCFNumberCFIndexType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
365 /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
366 /* kCFNumberCGFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
369 /* kCFNumberSInt128Type */ {kCFNumberSInt128Type
, 0, 1, 4, 0},
372 CF_INLINE CFNumberType
__CFNumberGetType(CFNumberRef num
) {
373 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
376 #define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
377 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
378 DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
379 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
380 SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
383 #define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
384 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
385 DST_TYPE dv; Boolean noLoss = false; \
386 if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
388 } else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
391 dv = (DST_TYPE)sv.low; \
394 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
398 // returns false if the output value is not the same as the number's value, which
399 // can occur due to accuracy loss and the value not being within the target range
400 static Boolean
__CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
401 type
= __CFNumberTypeTable
[type
].canonicalType
;
402 CFNumberType ntype
= __CFNumberGetType(number
);
403 const void *data
= &(number
->_pad
);
405 case kCFNumberSInt8Type
:
406 if (__CFNumberTypeTable
[ntype
].floatBit
) {
407 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
408 CVT(Float32
, int8_t, INT8_MIN
, INT8_MAX
);
410 CVT(Float64
, int8_t, INT8_MIN
, INT8_MAX
);
413 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
414 CVT(int64_t, int8_t, INT8_MIN
, INT8_MAX
);
416 CVT128ToInt(CFSInt128Struct
, int8_t, INT8_MIN
, INT8_MAX
);
420 case kCFNumberSInt16Type
:
421 if (__CFNumberTypeTable
[ntype
].floatBit
) {
422 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
423 CVT(Float32
, int16_t, INT16_MIN
, INT16_MAX
);
425 CVT(Float64
, int16_t, INT16_MIN
, INT16_MAX
);
428 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
429 CVT(int64_t, int16_t, INT16_MIN
, INT16_MAX
);
431 CVT128ToInt(CFSInt128Struct
, int16_t, INT16_MIN
, INT16_MAX
);
435 case kCFNumberSInt32Type
:
436 if (__CFNumberTypeTable
[ntype
].floatBit
) {
437 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
438 CVT(Float32
, int32_t, INT32_MIN
, INT32_MAX
);
440 CVT(Float64
, int32_t, INT32_MIN
, INT32_MAX
);
443 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
444 CVT(int64_t, int32_t, INT32_MIN
, INT32_MAX
);
446 CVT128ToInt(CFSInt128Struct
, int32_t, INT32_MIN
, INT32_MAX
);
450 case kCFNumberSInt64Type
:
451 if (__CFNumberTypeTable
[ntype
].floatBit
) {
452 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
453 CVT(Float32
, int64_t, INT64_MIN
, INT64_MAX
);
455 CVT(Float64
, int64_t, INT64_MIN
, INT64_MAX
);
458 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
459 memmove(valuePtr
, data
, 8);
461 CVT128ToInt(CFSInt128Struct
, int64_t, INT64_MIN
, INT64_MAX
);
465 case kCFNumberSInt128Type
:
466 if (__CFNumberTypeTable
[ntype
].floatBit
) {
467 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
469 memmove(&f
, data
, 4);
472 cvtFloat64ToSInt128(&i
, &d
);
473 memmove(valuePtr
, &i
, 16);
475 cvtSInt128ToFloat64(&d2
, &i
);
476 Float32 f2
= (Float32
)d2
;
480 memmove(&d
, data
, 8);
482 cvtFloat64ToSInt128(&i
, &d
);
483 memmove(valuePtr
, &i
, 16);
485 cvtSInt128ToFloat64(&d2
, &i
);
489 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
491 memmove(&j
, data
, 8);
494 i
.high
= (j
< 0) ? -1LL : 0LL;
495 memmove(valuePtr
, &i
, 16);
497 memmove(valuePtr
, data
, 16);
501 case kCFNumberFloat32Type
:
502 if (__CFNumberTypeTable
[ntype
].floatBit
) {
503 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
504 memmove(valuePtr
, data
, 4);
507 memmove(&d
, data
, 8);
509 uint32_t l
= 0x7fc00000;
510 memmove(valuePtr
, &l
, 4);
512 } else if (isinf(d
)) {
513 uint32_t l
= 0x7f800000;
514 if (d
< 0.0) l
+= 0x80000000UL
;
515 memmove(valuePtr
, &l
, 4);
518 CVT(Float64
, Float32
, -FLT_MAX
, FLT_MAX
);
521 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
522 CVT(int64_t, Float32
, -FLT_MAX
, FLT_MAX
);
525 memmove(&i
, data
, 16);
527 cvtSInt128ToFloat64(&d
, &i
);
528 Float32 f
= (Float32
)d
;
529 memmove(valuePtr
, &f
, 4);
532 cvtFloat64ToSInt128(&i2
, &d
);
533 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
537 case kCFNumberFloat64Type
:
538 if (__CFNumberTypeTable
[ntype
].floatBit
) {
539 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
541 memmove(&f
, data
, 4);
543 uint64_t l
= BITSFORDOUBLENAN
;
544 memmove(valuePtr
, &l
, 8);
546 } else if (isinf(f
)) {
547 uint64_t l
= BITSFORDOUBLEPOSINF
;
548 if (f
< 0.0) l
+= 0x8000000000000000ULL
;
549 memmove(valuePtr
, &l
, 8);
552 CVT(Float32
, Float64
, -DBL_MAX
, DBL_MAX
);
554 memmove(valuePtr
, data
, 8);
557 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
558 CVT(int64_t, Float64
, -DBL_MAX
, DBL_MAX
);
561 memmove(&i
, data
, 16);
563 cvtSInt128ToFloat64(&d
, &i
);
564 memmove(valuePtr
, &d
, 8);
566 cvtFloat64ToSInt128(&i2
, &d
);
567 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
575 #define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
576 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
577 DST_TYPE dv = (DST_TYPE)(sv); \
578 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
579 SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
582 #define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
583 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
584 DST_TYPE dv; dv = (DST_TYPE)sv.low; \
585 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
586 uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
589 // this has the old cast-style behavior
590 static Boolean
__CFNumberGetValueCompat(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
591 type
= __CFNumberTypeTable
[type
].canonicalType
;
592 CFNumberType ntype
= __CFNumberGetType(number
);
593 const void *data
= &(number
->_pad
);
595 case kCFNumberSInt8Type
:
596 if (__CFNumberTypeTable
[ntype
].floatBit
) {
597 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
598 CVT_COMPAT(Float32
, int8_t, 0);
600 CVT_COMPAT(Float64
, int8_t, 0);
603 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
604 CVT_COMPAT(int64_t, int8_t, 1);
606 CVT128ToInt_COMPAT(CFSInt128Struct
, int8_t);
610 case kCFNumberSInt16Type
:
611 if (__CFNumberTypeTable
[ntype
].floatBit
) {
612 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
613 CVT_COMPAT(Float32
, int16_t, 0);
615 CVT_COMPAT(Float64
, int16_t, 0);
618 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
619 CVT_COMPAT(int64_t, int16_t, 1);
621 CVT128ToInt_COMPAT(CFSInt128Struct
, int16_t);
625 case kCFNumberSInt32Type
:
626 if (__CFNumberTypeTable
[ntype
].floatBit
) {
627 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
628 CVT_COMPAT(Float32
, int32_t, 0);
630 CVT_COMPAT(Float64
, int32_t, 0);
633 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
634 CVT_COMPAT(int64_t, int32_t, 0);
636 CVT128ToInt_COMPAT(CFSInt128Struct
, int32_t);
640 case kCFNumberSInt64Type
:
641 if (__CFNumberTypeTable
[ntype
].floatBit
) {
642 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
643 CVT_COMPAT(Float32
, int64_t, 0);
645 CVT_COMPAT(Float64
, int64_t, 0);
648 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
649 CVT_COMPAT(int64_t, int64_t, 0);
651 CVT128ToInt_COMPAT(CFSInt128Struct
, int64_t);
655 case kCFNumberSInt128Type
:
656 if (__CFNumberTypeTable
[ntype
].floatBit
) {
657 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
659 memmove(&f
, data
, 4);
662 cvtFloat64ToSInt128(&i
, &d
);
663 memmove(valuePtr
, &i
, 16);
665 cvtSInt128ToFloat64(&d2
, &i
);
666 Float32 f2
= (Float32
)d2
;
670 memmove(&d
, data
, 8);
672 cvtFloat64ToSInt128(&i
, &d
);
673 memmove(valuePtr
, &i
, 16);
675 cvtSInt128ToFloat64(&d2
, &i
);
679 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
681 memmove(&j
, data
, 8);
684 i
.high
= (j
< 0) ? -1LL : 0LL;
685 memmove(valuePtr
, &i
, 16);
687 memmove(valuePtr
, data
, 16);
691 case kCFNumberFloat32Type
:
692 if (__CFNumberTypeTable
[ntype
].floatBit
) {
693 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
694 memmove(valuePtr
, data
, 4);
696 CVT_COMPAT(Float64
, Float32
, 0);
699 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
700 CVT_COMPAT(int64_t, Float32
, 0);
703 memmove(&i
, data
, 16);
705 cvtSInt128ToFloat64(&d
, &i
);
706 Float32 f
= (Float32
)d
;
707 memmove(valuePtr
, &f
, 4);
710 cvtFloat64ToSInt128(&i2
, &d
);
711 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
715 case kCFNumberFloat64Type
:
716 if (__CFNumberTypeTable
[ntype
].floatBit
) {
717 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
718 CVT_COMPAT(Float32
, Float64
, 0);
720 memmove(valuePtr
, data
, 8);
723 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
724 CVT_COMPAT(int64_t, Float64
, 0);
727 memmove(&i
, data
, 16);
729 cvtSInt128ToFloat64(&d
, &i
);
730 memmove(valuePtr
, &d
, 8);
732 cvtFloat64ToSInt128(&i2
, &d
);
733 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
741 static CFStringRef
__CFNumberCopyDescription(CFTypeRef cf
) {
742 CFNumberRef number
= (CFNumberRef
)cf
;
743 CFNumberType type
= __CFNumberGetType(number
);
744 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
745 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
746 if (__CFNumberTypeTable
[type
].floatBit
) {
748 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
750 CFStringAppend(mstr
, CFSTR("nan"));
751 } else if (isinf(d
)) {
752 CFStringAppend(mstr
, (0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
753 } else if (0.0 == d
) {
754 CFStringAppend(mstr
, (copysign(1.0, d
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
756 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.*f"), (__CFNumberTypeTable
[type
].storageBit
? 20 : 10), d
);
758 const char *typeName
= "unknown float";
760 case kCFNumberFloat32Type
: typeName
= "kCFNumberFloat32Type"; break;
761 case kCFNumberFloat64Type
: typeName
= "kCFNumberFloat64Type"; break;
763 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = %s}"), typeName
);
766 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
768 emit128(buffer
, &i
, true);
769 const char *typeName
= "unknown integer";
771 case kCFNumberSInt8Type
: typeName
= "kCFNumberSInt8Type"; break;
772 case kCFNumberSInt16Type
: typeName
= "kCFNumberSInt16Type"; break;
773 case kCFNumberSInt32Type
: typeName
= "kCFNumberSInt32Type"; break;
774 case kCFNumberSInt64Type
: typeName
= "kCFNumberSInt64Type"; break;
775 case kCFNumberSInt128Type
: typeName
= "kCFNumberSInt128Type"; break;
777 CFStringAppendFormat(mstr
, NULL
, CFSTR("%s, type = %s}"), buffer
, typeName
);
782 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
784 static CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_new(CFTypeRef cf
) {
786 CFNumberGetValue((CFNumberRef
)cf
, kCFNumberFloat64Type
, &d
);
788 return (CFStringRef
)CFRetain(CFSTR("nan"));
791 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
794 return (CFStringRef
)CFRetain(CFSTR("0.0"));
796 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
797 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
800 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf
) {
801 CFStringRef result
= __CFNumberCopyFormattingDescriptionAsFloat64_new(cf
);
805 static CFStringRef
__CFNumberCopyFormattingDescription_new(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
806 CFNumberRef number
= (CFNumberRef
)cf
;
807 CFNumberType type
= __CFNumberGetType(number
);
808 if (__CFNumberTypeTable
[type
].floatBit
) {
809 return __CFNumberCopyFormattingDescriptionAsFloat64(number
);
812 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
814 emit128(buffer
, &i
, false);
815 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%s"), buffer
);
818 static CFStringRef
__CFNumberCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
819 CFStringRef result
= __CFNumberCopyFormattingDescription_new(cf
, formatOptions
);
824 static Boolean
__CFNumberEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
825 Boolean b
= CFNumberCompare((CFNumberRef
)cf1
, (CFNumberRef
)cf2
, 0) == kCFCompareEqualTo
;
829 static CFHashCode
__CFNumberHash(CFTypeRef cf
) {
831 CFNumberRef number
= (CFNumberRef
)cf
;
832 switch (__CFNumberGetType(number
)) {
833 case kCFNumberSInt8Type
:
834 case kCFNumberSInt16Type
:
835 case kCFNumberSInt32Type
: {
837 __CFNumberGetValue(number
, kCFNumberSInt32Type
, &i
);
843 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
844 h
= _CFHashDouble((double)d
);
851 static CFTypeID __kCFNumberTypeID
= _kCFRuntimeNotATypeID
;
853 static const CFRuntimeClass __CFNumberClass
= {
861 __CFNumberCopyFormattingDescription
,
862 __CFNumberCopyDescription
865 __private_extern__
void __CFNumberInitialize(void) {
866 __kCFNumberTypeID
= _CFRuntimeRegisterClass(&__CFNumberClass
);
868 _CFRuntimeSetInstanceTypeID(&__kCFNumberNaN
, __kCFNumberTypeID
);
869 __kCFNumberNaN
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
870 __CFBitfieldSetValue(__kCFNumberNaN
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
871 __kCFNumberNaN
._pad
= BITSFORDOUBLENAN
;
873 _CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity
, __kCFNumberTypeID
);
874 __kCFNumberNegativeInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
875 __CFBitfieldSetValue(__kCFNumberNegativeInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
876 __kCFNumberNegativeInfinity
._pad
= BITSFORDOUBLENEGINF
;
878 _CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity
, __kCFNumberTypeID
);
879 __kCFNumberPositiveInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
880 __CFBitfieldSetValue(__kCFNumberPositiveInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
881 __kCFNumberPositiveInfinity
._pad
= BITSFORDOUBLEPOSINF
;
884 CFTypeID
CFNumberGetTypeID(void) {
885 return __kCFNumberTypeID
;
888 #define MinCachedInt (-1)
889 #define MaxCachedInt (12)
890 #define NotToBeCached (MinCachedInt - 1)
891 static CFNumberRef __CFNumberCache
[MaxCachedInt
- MinCachedInt
+ 1] = {NULL
}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
893 CFNumberRef
CFNumberCreate(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
894 __CFAssertIsValidNumberType(type
);
895 //printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
897 // Look for cases where we can return a cached instance.
898 // We only use cached objects if the allocator is the system
899 // default allocator, except for the special floating point
900 // constant objects, where we return the cached object
901 // regardless of allocator, since that is what has always
902 // been done (and now must for compatibility).
903 if (!allocator
) allocator
= __CFGetDefaultAllocator();
904 int64_t valToBeCached
= NotToBeCached
;
906 if (__CFNumberTypeTable
[type
].floatBit
) {
907 CFNumberRef cached
= NULL
;
908 if (0 == __CFNumberTypeTable
[type
].storageBit
) {
909 Float32 f
= *(Float32
*)valuePtr
;
910 if (isnan(f
)) cached
= kCFNumberNaN
;
911 if (isinf(f
)) cached
= (f
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
913 Float64 d
= *(Float64
*)valuePtr
;
914 if (isnan(d
)) cached
= kCFNumberNaN
;
915 if (isinf(d
)) cached
= (d
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
917 if (cached
) return (CFNumberRef
)CFRetain(cached
);
918 } else if (kCFAllocatorSystemDefault
== allocator
) {
919 switch (__CFNumberTypeTable
[type
].canonicalType
) {
920 case kCFNumberSInt8Type
: {int8_t val
= *(int8_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
921 case kCFNumberSInt16Type
: {int16_t val
= *(int16_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
922 case kCFNumberSInt32Type
: {int32_t val
= *(int32_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
923 case kCFNumberSInt64Type
: {int64_t val
= *(int64_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
925 if (NotToBeCached
!= valToBeCached
) {
926 CFNumberRef cached
= __CFNumberCache
[valToBeCached
- MinCachedInt
]; // Atomic to access the value in the cache
927 if (NULL
!= cached
) return (CFNumberRef
)CFRetain(cached
);
931 CFIndex size
= 8 + ((!__CFNumberTypeTable
[type
].floatBit
&& __CFNumberTypeTable
[type
].storageBit
) ? 8 : 0);
932 CFNumberRef result
= (CFNumberRef
)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, size
, NULL
);
933 if (NULL
== result
) {
936 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)__CFNumberTypeTable
[type
].canonicalType
);
939 // for a value to be cached, we already have the value handy
940 if (NotToBeCached
!= valToBeCached
) {
941 memmove((void *)&result
->_pad
, &valToBeCached
, 8);
942 // Put this in the cache unless the cache is already filled (by another thread). If we do put it in the cache, retain it an extra time for the cache.
943 // Note that we don't bother freeing this result and returning the cached value if the cache was filled, since cached CFNumbers are not guaranteed unique.
944 // Barrier assures that the number that is placed in the cache is properly formed.
945 CFNumberType origType
= __CFNumberGetType(result
);
946 // Force all cached numbers to have the same type, so that the type does not
947 // depend on the order and original type in/with which the numbers are created.
948 // Forcing the type AFTER it was cached would cause a race condition with other
949 // threads pulling the number object out of the cache and using it.
950 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)kCFNumberSInt32Type
);
951 if (OSAtomicCompareAndSwapPtrBarrier(NULL
, (void *)result
, (void *volatile *)&__CFNumberCache
[valToBeCached
- MinCachedInt
])) {
954 // Did not cache the number object, put original type back.
955 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)origType
);
961 switch (__CFNumberTypeTable
[type
].canonicalType
) {
962 case kCFNumberSInt8Type
: value
= (uint64_t)(int64_t)*(int8_t *)valuePtr
; goto smallVal
;
963 case kCFNumberSInt16Type
: value
= (uint64_t)(int64_t)*(int16_t *)valuePtr
; goto smallVal
;
964 case kCFNumberSInt32Type
: value
= (uint64_t)(int64_t)*(int32_t *)valuePtr
; goto smallVal
;
965 smallVal
: memmove((void *)&result
->_pad
, &value
, 8); break;
966 case kCFNumberSInt64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
967 case kCFNumberSInt128Type
: memmove((void *)&result
->_pad
, valuePtr
, 16); break;
968 case kCFNumberFloat32Type
: memmove((void *)&result
->_pad
, valuePtr
, 4); break;
969 case kCFNumberFloat64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
971 //printf(" => %p\n", result);
975 CFNumberType
CFNumberGetType(CFNumberRef number
) {
976 //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
977 CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID
, CFNumberType
, number
, "_cfNumberType");
978 __CFAssertIsNumber(number
);
979 CFNumberType type
= __CFNumberGetType(number
);
980 if (kCFNumberSInt128Type
== type
) type
= kCFNumberSInt64Type
; // must hide this type, since it is not public
981 //printf(" => %d\n", type);
985 CFNumberType
_CFNumberGetType2(CFNumberRef number
) {
986 __CFAssertIsNumber(number
);
987 return __CFNumberGetType(number
);
990 CFIndex
CFNumberGetByteSize(CFNumberRef number
) {
991 //printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
992 __CFAssertIsNumber(number
);
993 CFIndex r
= 1 << __CFNumberTypeTable
[CFNumberGetType(number
)].lgByteSize
;
994 //printf(" => %d\n", r);
998 Boolean
CFNumberIsFloatType(CFNumberRef number
) {
999 //printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1000 __CFAssertIsNumber(number
);
1001 Boolean r
= __CFNumberTypeTable
[CFNumberGetType(number
)].floatBit
;
1002 //printf(" => %d\n", r);
1006 Boolean
CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
1007 //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1008 CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID
, Boolean
, number
, "_getValue:forType:", valuePtr
, __CFNumberTypeTable
[type
].canonicalType
);
1009 __CFAssertIsNumber(number
);
1010 __CFAssertIsValidNumberType(type
);
1011 uint8_t localMemory
[128];
1012 Boolean r
= __CFNumberGetValueCompat(number
, type
, valuePtr
? valuePtr
: localMemory
);
1013 //printf(" => %d\n", r);
1017 static CFComparisonResult
CFNumberCompare_new(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1018 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number1
, "compare:", number2
);
1019 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number2
, "_reverseCompare:", number1
);
1020 __CFAssertIsNumber(number1
);
1021 __CFAssertIsNumber(number2
);
1023 CFNumberType type1
= __CFNumberGetType(number1
);
1024 CFNumberType type2
= __CFNumberGetType(number2
);
1025 // Both numbers are integers
1026 if (!__CFNumberTypeTable
[type1
].floatBit
&& !__CFNumberTypeTable
[type2
].floatBit
) {
1027 CFSInt128Struct i1
, i2
;
1028 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1029 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1030 return cmp128(&i1
, &i2
);
1032 // Both numbers are floats
1033 if (__CFNumberTypeTable
[type1
].floatBit
&& __CFNumberTypeTable
[type2
].floatBit
) {
1035 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1036 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1037 double s1
= copysign(1.0, d1
);
1038 double s2
= copysign(1.0, d2
);
1039 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1040 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1041 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1042 // at this point, we know we don't have any NaNs
1043 if (s1
< s2
) return kCFCompareLessThan
;
1044 if (s2
< s1
) return kCFCompareGreaterThan
;
1045 // at this point, we know the signs are the same; do not combine these tests
1046 if (d1
< d2
) return kCFCompareLessThan
;
1047 if (d2
< d1
) return kCFCompareGreaterThan
;
1048 return kCFCompareEqualTo
;
1050 // One float, one integer; swap if necessary so number1 is the float
1051 Boolean swapResult
= false;
1052 if (__CFNumberTypeTable
[type2
].floatBit
) {
1053 CFNumberRef tmp
= number1
;
1058 // At large integer values, the precision of double is quite low
1059 // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1060 // If we just used double compare, that would make the 2^73 largest 128-bit
1061 // integers look equal, so we have to use integer comparison when possible.
1063 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1064 // if the double value is really big, cannot be equal to integer
1065 // nan d1 will not compare true here
1066 if (d1
< FLOAT_NEGATIVE_2_TO_THE_127
) {
1067 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1069 if (FLOAT_POSITIVE_2_TO_THE_127
<= d1
) {
1070 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1072 CFSInt128Struct i1
, i2
;
1073 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1074 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1075 CFComparisonResult res
= cmp128(&i1
, &i2
);
1076 if (kCFCompareEqualTo
!= res
) {
1077 return !swapResult
? res
: -res
;
1079 // now things are equal, but perhaps due to rounding or nan
1081 if (isNeg128(&i2
)) {
1082 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1084 // nan compares less than positive 0 too
1085 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1087 // at this point, we know we don't have NaN
1088 double s1
= copysign(1.0, d1
);
1089 double s2
= isNeg128(&i2
) ? -1.0 : 1.0;
1090 if (s1
< s2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1091 if (s2
< s1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1092 // at this point, we know the signs are the same; do not combine these tests
1093 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1094 if (d1
< d2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1095 if (d2
< d1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1096 return kCFCompareEqualTo
;
1099 CFComparisonResult
CFNumberCompare(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1100 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1101 CFComparisonResult r
= CFNumberCompare_new(number1
, number2
, context
);
1102 //printf(" => %d\n", r);
1106 #undef __CFAssertIsBoolean
1107 #undef __CFAssertIsNumber
1108 #undef __CFAssertIsValidNumberType
1109 #undef BITSFORDOUBLENAN
1110 #undef BITSFORDOUBLEPOSINF
1111 #undef BITSFORDOUBLENEGINF
1114 #undef NotToBeCached