2 * Copyright (c) 2013 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@
25 Copyright (c) 1999-2013, Apple Inc. All rights reserved.
26 Responsibility: Ali Ozer
29 #include <CoreFoundation/CFNumber.h>
30 #include "CFInternal.h"
31 #include <CoreFoundation/CFPriv.h>
36 #if DEPLOYMENT_TARGET_WINDOWS
37 #define isnan(A) _isnan(A)
38 #define isinf(A) !_finite(A)
39 #define copysign(A, B) _copysign(A, B)
42 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
48 static struct __CFBoolean __kCFBooleanTrue
= {
51 const CFBooleanRef kCFBooleanTrue
= &__kCFBooleanTrue
;
53 static struct __CFBoolean __kCFBooleanFalse
= {
56 const CFBooleanRef kCFBooleanFalse
= &__kCFBooleanFalse
;
58 static CFStringRef
__CFBooleanCopyDescription(CFTypeRef cf
) {
59 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
60 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf
, CFGetAllocator(cf
), (boolean
== kCFBooleanTrue
) ? "true" : "false");
63 CF_PRIVATE CFStringRef
__CFBooleanCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
64 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
65 return (CFStringRef
)CFRetain((boolean
== kCFBooleanTrue
) ? CFSTR("true") : CFSTR("false"));
68 static CFHashCode
__CFBooleanHash(CFTypeRef cf
) {
69 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
70 return (boolean
== kCFBooleanTrue
) ? _CFHashInt(1) : _CFHashInt(0);
73 static void __CFBooleanDeallocate(CFTypeRef cf
) {
74 CFAssert(false, __kCFLogAssertion
, "Deallocated CFBoolean!");
77 static CFTypeID __kCFBooleanTypeID
= _kCFRuntimeNotATypeID
;
79 static const CFRuntimeClass __CFBooleanClass
= {
84 __CFBooleanDeallocate
,
87 __CFBooleanCopyFormattingDescription
,
88 __CFBooleanCopyDescription
91 CF_PRIVATE
void __CFBooleanInitialize(void) {
92 __kCFBooleanTypeID
= _CFRuntimeRegisterClass(&__CFBooleanClass
);
93 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue
, __kCFBooleanTypeID
);
94 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse
, __kCFBooleanTypeID
);
97 CFTypeID
CFBooleanGetTypeID(void) {
98 return __kCFBooleanTypeID
;
101 Boolean
CFBooleanGetValue(CFBooleanRef boolean
) {
102 CF_OBJC_FUNCDISPATCHV(__kCFBooleanTypeID
, Boolean
, (NSNumber
*)boolean
, boolValue
);
103 return (boolean
== kCFBooleanTrue
) ? true : false;
109 #define OLD_CRAP_TOO 0
113 // old implementation, for runtime comparison purposes
120 } __CFNumberValue_old
;
122 struct __CFNumber_old
{ /* Only as many bytes as necessary are allocated */
124 __CFNumberValue_old value
;
127 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
);
128 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
);
129 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
);
130 CF_PRIVATE CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
);
131 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
);
132 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
);
133 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
);
134 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
);
135 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
);
136 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
);
137 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
);
142 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
143 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
145 /* The IEEE bit patterns... Also have:
146 0x7f800000 float +Inf
148 0xff800000 float -Inf
150 #define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
151 #define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
152 #define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
154 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
155 #define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
156 #define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
157 #define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
158 #elif DEPLOYMENT_TARGET_WINDOWS
159 #define FLOAT_POSITIVE_2_TO_THE_64 18446744073709551616.0
160 #define FLOAT_NEGATIVE_2_TO_THE_127 -170141183460469231731687303715884105728.0
161 #define FLOAT_POSITIVE_2_TO_THE_127 170141183460469231731687303715884105728.0
163 #error Unknown or unspecified DEPLOYMENT_TARGET
166 typedef struct { // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
172 kCFNumberSInt128Type
= 17
175 static uint8_t isNeg128(const CFSInt128Struct
*in
) {
179 static CFComparisonResult
cmp128(const CFSInt128Struct
*in1
, const CFSInt128Struct
*in2
) {
180 if (in1
->high
< in2
->high
) return kCFCompareLessThan
;
181 if (in1
->high
> in2
->high
) return kCFCompareGreaterThan
;
182 if (in1
->low
< in2
->low
) return kCFCompareLessThan
;
183 if (in1
->low
> in2
->low
) return kCFCompareGreaterThan
;
184 return kCFCompareEqualTo
;
187 // allows out to be the same as in1 or in2
188 static void add128(CFSInt128Struct
*out
, CFSInt128Struct
*in1
, CFSInt128Struct
*in2
) {
190 tmp
.low
= in1
->low
+ in2
->low
;
191 tmp
.high
= in1
->high
+ in2
->high
;
192 if (UINT64_MAX
- in1
->low
< in2
->low
) {
198 // allows out to be the same as in
199 static void neg128(CFSInt128Struct
*out
, CFSInt128Struct
*in
) {
200 uint64_t tmplow
= ~in
->low
;
201 out
->low
= tmplow
+ 1;
202 out
->high
= ~in
->high
;
203 if (UINT64_MAX
== tmplow
) {
208 static const CFSInt128Struct powersOf10
[] = {
209 { 0x4B3B4CA85A86C47ALL
, 0x098A224000000000ULL
},
210 { 0x0785EE10D5DA46D9LL
, 0x00F436A000000000ULL
},
211 { 0x00C097CE7BC90715LL
, 0xB34B9F1000000000ULL
},
212 { 0x0013426172C74D82LL
, 0x2B878FE800000000ULL
},
213 { 0x0001ED09BEAD87C0LL
, 0x378D8E6400000000ULL
},
214 { 0x0000314DC6448D93LL
, 0x38C15B0A00000000ULL
},
215 { 0x000004EE2D6D415BLL
, 0x85ACEF8100000000ULL
},
216 { 0x0000007E37BE2022LL
, 0xC0914B2680000000ULL
},
217 { 0x0000000C9F2C9CD0LL
, 0x4674EDEA40000000ULL
},
218 { 0x00000001431E0FAELL
, 0x6D7217CAA0000000ULL
},
219 { 0x00000000204FCE5ELL
, 0x3E25026110000000ULL
},
220 { 0x00000000033B2E3CLL
, 0x9FD0803CE8000000ULL
},
221 { 0x000000000052B7D2LL
, 0xDCC80CD2E4000000ULL
},
222 { 0x0000000000084595LL
, 0x161401484A000000ULL
},
223 { 0x000000000000D3C2LL
, 0x1BCECCEDA1000000ULL
},
224 { 0x000000000000152DLL
, 0x02C7E14AF6800000ULL
},
225 { 0x000000000000021ELL
, 0x19E0C9BAB2400000ULL
},
226 { 0x0000000000000036LL
, 0x35C9ADC5DEA00000ULL
},
227 { 0x0000000000000005LL
, 0x6BC75E2D63100000ULL
},
228 { 0x0000000000000000LL
, 0x8AC7230489E80000ULL
},
229 { 0x0000000000000000LL
, 0x0DE0B6B3A7640000ULL
},
230 { 0x0000000000000000LL
, 0x016345785D8A0000ULL
},
231 { 0x0000000000000000LL
, 0x002386F26FC10000ULL
},
232 { 0x0000000000000000LL
, 0x00038D7EA4C68000ULL
},
233 { 0x0000000000000000LL
, 0x00005AF3107A4000ULL
},
234 { 0x0000000000000000LL
, 0x000009184E72A000ULL
},
235 { 0x0000000000000000LL
, 0x000000E8D4A51000ULL
},
236 { 0x0000000000000000LL
, 0x000000174876E800ULL
},
237 { 0x0000000000000000LL
, 0x00000002540BE400ULL
},
238 { 0x0000000000000000LL
, 0x000000003B9ACA00ULL
},
239 { 0x0000000000000000LL
, 0x0000000005F5E100ULL
},
240 { 0x0000000000000000LL
, 0x0000000000989680ULL
},
241 { 0x0000000000000000LL
, 0x00000000000F4240ULL
},
242 { 0x0000000000000000LL
, 0x00000000000186A0ULL
},
243 { 0x0000000000000000LL
, 0x0000000000002710ULL
},
244 { 0x0000000000000000LL
, 0x00000000000003E8ULL
},
245 { 0x0000000000000000LL
, 0x0000000000000064ULL
},
246 { 0x0000000000000000LL
, 0x000000000000000AULL
},
247 { 0x0000000000000000LL
, 0x0000000000000001ULL
},
250 static const CFSInt128Struct neg_powersOf10
[] = {
251 { 0xB4C4B357A5793B85LL
, 0xF675DDC000000000ULL
},
252 { 0xF87A11EF2A25B926LL
, 0xFF0BC96000000000ULL
},
253 { 0xFF3F68318436F8EALL
, 0x4CB460F000000000ULL
},
254 { 0xFFECBD9E8D38B27DLL
, 0xD478701800000000ULL
},
255 { 0xFFFE12F64152783FLL
, 0xC872719C00000000ULL
},
256 { 0xFFFFCEB239BB726CLL
, 0xC73EA4F600000000ULL
},
257 { 0xFFFFFB11D292BEA4LL
, 0x7A53107F00000000ULL
},
258 { 0xFFFFFF81C841DFDDLL
, 0x3F6EB4D980000000ULL
},
259 { 0xFFFFFFF360D3632FLL
, 0xB98B1215C0000000ULL
},
260 { 0xFFFFFFFEBCE1F051LL
, 0x928DE83560000000ULL
},
261 { 0xFFFFFFFFDFB031A1LL
, 0xC1DAFD9EF0000000ULL
},
262 { 0xFFFFFFFFFCC4D1C3LL
, 0x602F7FC318000000ULL
},
263 { 0xFFFFFFFFFFAD482DLL
, 0x2337F32D1C000000ULL
},
264 { 0xFFFFFFFFFFF7BA6ALL
, 0xE9EBFEB7B6000000ULL
},
265 { 0xFFFFFFFFFFFF2C3DLL
, 0xE43133125F000000ULL
},
266 { 0xFFFFFFFFFFFFEAD2LL
, 0xFD381EB509800000ULL
},
267 { 0xFFFFFFFFFFFFFDE1LL
, 0xE61F36454DC00000ULL
},
268 { 0xFFFFFFFFFFFFFFC9LL
, 0xCA36523A21600000ULL
},
269 { 0xFFFFFFFFFFFFFFFALL
, 0x9438A1D29CF00000ULL
},
270 { 0xFFFFFFFFFFFFFFFFLL
, 0x7538DCFB76180000ULL
},
271 { 0xFFFFFFFFFFFFFFFFLL
, 0xF21F494C589C0000ULL
},
272 { 0xFFFFFFFFFFFFFFFFLL
, 0xFE9CBA87A2760000ULL
},
273 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFDC790D903F0000ULL
},
274 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFC72815B398000ULL
},
275 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFA50CEF85C000ULL
},
276 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFF6E7B18D6000ULL
},
277 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFF172B5AF000ULL
},
278 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFE8B7891800ULL
},
279 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFDABF41C00ULL
},
280 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFC4653600ULL
},
281 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFA0A1F00ULL
},
282 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFF676980ULL
},
283 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFF0BDC0ULL
},
284 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFE7960ULL
},
285 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFD8F0ULL
},
286 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFC18ULL
},
287 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFF9CULL
},
288 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFF6ULL
},
289 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFFFULL
},
292 static void emit128(char *buffer
, const CFSInt128Struct
*in
, Boolean forcePlus
) {
293 CFSInt128Struct tmp
= *in
;
294 if (isNeg128(&tmp
)) {
297 } else if (forcePlus
) {
300 Boolean doneOne
= false;
302 for (idx
= 0; idx
< sizeof(powersOf10
) / sizeof(powersOf10
[0]); idx
++) {
304 while (cmp128(&powersOf10
[idx
], &tmp
) <= 0) {
305 add128(&tmp
, &tmp
, (CFSInt128Struct
*)&neg_powersOf10
[idx
]);
308 if (0 != count
|| doneOne
) {
309 *buffer
++ = '0' + count
;
319 static void cvtSInt128ToFloat64(Float64
*out
, const CFSInt128Struct
*in
) {
320 // switching to a positive number results in better accuracy
321 // for negative numbers close to zero, because the multiply
322 // of -1 by 2^64 (scaling the Float64 high) is avoided
323 Boolean wasNeg
= false;
324 CFSInt128Struct tmp
= *in
;
325 if (isNeg128(&tmp
)) {
329 Float64 d
= (Float64
)tmp
.high
* FLOAT_POSITIVE_2_TO_THE_64
+ (Float64
)tmp
.low
;
334 static void cvtFloat64ToSInt128(CFSInt128Struct
*out
, const Float64
*in
) {
337 if (d
< FLOAT_NEGATIVE_2_TO_THE_127
) {
338 i
.high
= 0x8000000000000000LL
;
339 i
.low
= 0x0000000000000000ULL
;
343 if (FLOAT_POSITIVE_2_TO_THE_127
<= d
) {
344 i
.high
= 0x7fffffffffffffffLL
;
345 i
.low
= 0xffffffffffffffffULL
;
349 Float64 t
= floor(d
/ FLOAT_POSITIVE_2_TO_THE_64
);
351 i
.low
= (uint64_t)(d
- t
* FLOAT_POSITIVE_2_TO_THE_64
);
358 struct __CFNumber_old
*__old__
;
361 uint64_t _pad
; // need this space here for the constant objects
362 /* 0 or 8 more bytes allocated here */
365 /* Seven bits in base:
367 Bits 4..0: CFNumber type
370 static struct __CFNumber __kCFNumberNaN
= {
371 INIT_CFRUNTIME_BASE(), 0ULL
373 const CFNumberRef kCFNumberNaN
= &__kCFNumberNaN
;
375 static struct __CFNumber __kCFNumberNegativeInfinity
= {
376 INIT_CFRUNTIME_BASE(), 0ULL
378 const CFNumberRef kCFNumberNegativeInfinity
= &__kCFNumberNegativeInfinity
;
380 static struct __CFNumber __kCFNumberPositiveInfinity
= {
381 INIT_CFRUNTIME_BASE(), 0ULL
383 const CFNumberRef kCFNumberPositiveInfinity
= &__kCFNumberPositiveInfinity
;
385 static const struct {
386 uint16_t canonicalType
:5; // canonical fixed-width type
387 uint16_t floatBit
:1; // is float
388 uint16_t storageBit
:1; // storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
389 uint16_t lgByteSize
:3; // base-2 log byte size of public type
391 } __CFNumberTypeTable
[] = {
392 /* 0 */ {0, 0, 0, 0},
394 /* kCFNumberSInt8Type */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
395 /* kCFNumberSInt16Type */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
396 /* kCFNumberSInt32Type */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
397 /* kCFNumberSInt64Type */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
398 /* kCFNumberFloat32Type */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
399 /* kCFNumberFloat64Type */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
401 /* kCFNumberCharType */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
402 /* kCFNumberShortType */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
403 /* kCFNumberIntType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
405 /* kCFNumberLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
407 /* kCFNumberLongType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
409 /* kCFNumberLongLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
410 /* kCFNumberFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
411 /* kCFNumberDoubleType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
414 /* kCFNumberCFIndexType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
415 /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
416 /* kCFNumberCGFloatType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
418 /* kCFNumberCFIndexType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
419 /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
420 /* kCFNumberCGFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
423 /* kCFNumberSInt128Type */ {kCFNumberSInt128Type
, 0, 1, 4, 0},
426 CF_INLINE CFNumberType
__CFNumberGetType(CFNumberRef num
) {
427 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
430 #define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
431 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
432 DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
433 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
434 SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
437 #define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
438 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
439 DST_TYPE dv; Boolean noLoss = false; \
440 if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
442 } else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
445 dv = (DST_TYPE)sv.low; \
448 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
452 // returns false if the output value is not the same as the number's value, which
453 // can occur due to accuracy loss and the value not being within the target range
454 static Boolean
__CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
455 type
= __CFNumberTypeTable
[type
].canonicalType
;
456 CFNumberType ntype
= __CFNumberGetType(number
);
457 const void *data
= &(number
->_pad
);
459 case kCFNumberSInt8Type
:
460 if (__CFNumberTypeTable
[ntype
].floatBit
) {
461 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
462 CVT(Float32
, int8_t, INT8_MIN
, INT8_MAX
);
464 CVT(Float64
, int8_t, INT8_MIN
, INT8_MAX
);
467 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
468 CVT(int64_t, int8_t, INT8_MIN
, INT8_MAX
);
470 CVT128ToInt(CFSInt128Struct
, int8_t, INT8_MIN
, INT8_MAX
);
474 case kCFNumberSInt16Type
:
475 if (__CFNumberTypeTable
[ntype
].floatBit
) {
476 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
477 CVT(Float32
, int16_t, INT16_MIN
, INT16_MAX
);
479 CVT(Float64
, int16_t, INT16_MIN
, INT16_MAX
);
482 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
483 CVT(int64_t, int16_t, INT16_MIN
, INT16_MAX
);
485 CVT128ToInt(CFSInt128Struct
, int16_t, INT16_MIN
, INT16_MAX
);
489 case kCFNumberSInt32Type
:
490 if (__CFNumberTypeTable
[ntype
].floatBit
) {
491 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
492 CVT(Float32
, int32_t, INT32_MIN
, INT32_MAX
);
494 CVT(Float64
, int32_t, INT32_MIN
, INT32_MAX
);
497 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
498 CVT(int64_t, int32_t, INT32_MIN
, INT32_MAX
);
500 CVT128ToInt(CFSInt128Struct
, int32_t, INT32_MIN
, INT32_MAX
);
504 case kCFNumberSInt64Type
:
505 if (__CFNumberTypeTable
[ntype
].floatBit
) {
506 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
507 CVT(Float32
, int64_t, INT64_MIN
, INT64_MAX
);
509 CVT(Float64
, int64_t, INT64_MIN
, INT64_MAX
);
512 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
513 memmove(valuePtr
, data
, 8);
515 CVT128ToInt(CFSInt128Struct
, int64_t, INT64_MIN
, INT64_MAX
);
519 case kCFNumberSInt128Type
:
520 if (__CFNumberTypeTable
[ntype
].floatBit
) {
521 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
523 memmove(&f
, data
, 4);
526 cvtFloat64ToSInt128(&i
, &d
);
527 memmove(valuePtr
, &i
, 16);
529 cvtSInt128ToFloat64(&d2
, &i
);
530 Float32 f2
= (Float32
)d2
;
534 memmove(&d
, data
, 8);
536 cvtFloat64ToSInt128(&i
, &d
);
537 memmove(valuePtr
, &i
, 16);
539 cvtSInt128ToFloat64(&d2
, &i
);
543 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
545 memmove(&j
, data
, 8);
548 i
.high
= (j
< 0) ? -1LL : 0LL;
549 memmove(valuePtr
, &i
, 16);
551 memmove(valuePtr
, data
, 16);
555 case kCFNumberFloat32Type
:
556 if (__CFNumberTypeTable
[ntype
].floatBit
) {
557 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
558 memmove(valuePtr
, data
, 4);
561 memmove(&d
, data
, 8);
563 uint32_t l
= 0x7fc00000;
564 memmove(valuePtr
, &l
, 4);
566 } else if (isinf(d
)) {
567 uint32_t l
= 0x7f800000;
568 if (d
< 0.0) l
+= 0x80000000UL
;
569 memmove(valuePtr
, &l
, 4);
572 CVT(Float64
, Float32
, -FLT_MAX
, FLT_MAX
);
575 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
576 CVT(int64_t, Float32
, -FLT_MAX
, FLT_MAX
);
579 memmove(&i
, data
, 16);
581 cvtSInt128ToFloat64(&d
, &i
);
582 Float32 f
= (Float32
)d
;
583 memmove(valuePtr
, &f
, 4);
586 cvtFloat64ToSInt128(&i2
, &d
);
587 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
591 case kCFNumberFloat64Type
:
592 if (__CFNumberTypeTable
[ntype
].floatBit
) {
593 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
595 memmove(&f
, data
, 4);
597 uint64_t l
= BITSFORDOUBLENAN
;
598 memmove(valuePtr
, &l
, 8);
600 } else if (isinf(f
)) {
601 uint64_t l
= BITSFORDOUBLEPOSINF
;
602 if (f
< 0.0) l
+= 0x8000000000000000ULL
;
603 memmove(valuePtr
, &l
, 8);
606 CVT(Float32
, Float64
, -DBL_MAX
, DBL_MAX
);
608 memmove(valuePtr
, data
, 8);
611 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
612 CVT(int64_t, Float64
, -DBL_MAX
, DBL_MAX
);
615 memmove(&i
, data
, 16);
617 cvtSInt128ToFloat64(&d
, &i
);
618 memmove(valuePtr
, &d
, 8);
620 cvtFloat64ToSInt128(&i2
, &d
);
621 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
629 #define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
630 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
631 DST_TYPE dv = (DST_TYPE)(sv); \
632 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
633 SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
636 #define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
637 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
638 DST_TYPE dv; dv = (DST_TYPE)sv.low; \
639 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
640 uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
643 // this has the old cast-style behavior
644 static Boolean
__CFNumberGetValueCompat(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
645 type
= __CFNumberTypeTable
[type
].canonicalType
;
646 CFNumberType ntype
= __CFNumberGetType(number
);
647 const void *data
= &(number
->_pad
);
649 case kCFNumberSInt8Type
:
650 if (__CFNumberTypeTable
[ntype
].floatBit
) {
651 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
652 CVT_COMPAT(Float32
, int8_t, 0);
654 CVT_COMPAT(Float64
, int8_t, 0);
657 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
658 // Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
659 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
660 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
661 int8_t dv
= (int8_t)(sv
);
662 memmove(valuePtr
, &dv
, sizeof(int8_t));
663 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 8LL) == 0LL) || (vv
== sv
);
665 CVT128ToInt_COMPAT(CFSInt128Struct
, int8_t);
669 case kCFNumberSInt16Type
:
670 if (__CFNumberTypeTable
[ntype
].floatBit
) {
671 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
672 CVT_COMPAT(Float32
, int16_t, 0);
674 CVT_COMPAT(Float64
, int16_t, 0);
677 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
678 // Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
679 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
680 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
681 int16_t dv
= (int16_t)(sv
);
682 memmove(valuePtr
, &dv
, sizeof(int16_t));
683 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 16LL) == 0LL) || (vv
== sv
);
685 CVT128ToInt_COMPAT(CFSInt128Struct
, int16_t);
689 case kCFNumberSInt32Type
:
690 if (__CFNumberTypeTable
[ntype
].floatBit
) {
691 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
692 CVT_COMPAT(Float32
, int32_t, 0);
694 CVT_COMPAT(Float64
, int32_t, 0);
697 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
698 CVT_COMPAT(int64_t, int32_t, 0);
700 CVT128ToInt_COMPAT(CFSInt128Struct
, int32_t);
704 case kCFNumberSInt64Type
:
705 if (__CFNumberTypeTable
[ntype
].floatBit
) {
706 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
707 CVT_COMPAT(Float32
, int64_t, 0);
709 CVT_COMPAT(Float64
, int64_t, 0);
712 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
713 CVT_COMPAT(int64_t, int64_t, 0);
715 CVT128ToInt_COMPAT(CFSInt128Struct
, int64_t);
719 case kCFNumberSInt128Type
:
720 if (__CFNumberTypeTable
[ntype
].floatBit
) {
721 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
723 memmove(&f
, data
, 4);
726 cvtFloat64ToSInt128(&i
, &d
);
727 memmove(valuePtr
, &i
, 16);
729 cvtSInt128ToFloat64(&d2
, &i
);
730 Float32 f2
= (Float32
)d2
;
734 memmove(&d
, data
, 8);
736 cvtFloat64ToSInt128(&i
, &d
);
737 memmove(valuePtr
, &i
, 16);
739 cvtSInt128ToFloat64(&d2
, &i
);
743 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
745 memmove(&j
, data
, 8);
748 i
.high
= (j
< 0) ? -1LL : 0LL;
749 memmove(valuePtr
, &i
, 16);
751 memmove(valuePtr
, data
, 16);
755 case kCFNumberFloat32Type
:
756 if (__CFNumberTypeTable
[ntype
].floatBit
) {
757 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
758 memmove(valuePtr
, data
, 4);
760 CVT_COMPAT(Float64
, Float32
, 0);
763 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
764 CVT_COMPAT(int64_t, Float32
, 0);
767 memmove(&i
, data
, 16);
769 cvtSInt128ToFloat64(&d
, &i
);
770 Float32 f
= (Float32
)d
;
771 memmove(valuePtr
, &f
, 4);
774 cvtFloat64ToSInt128(&i2
, &d
);
775 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
779 case kCFNumberFloat64Type
:
780 if (__CFNumberTypeTable
[ntype
].floatBit
) {
781 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
782 CVT_COMPAT(Float32
, Float64
, 0);
784 memmove(valuePtr
, data
, 8);
787 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
788 CVT_COMPAT(int64_t, Float64
, 0);
791 memmove(&i
, data
, 16);
793 cvtSInt128ToFloat64(&d
, &i
);
794 memmove(valuePtr
, &d
, 8);
796 cvtFloat64ToSInt128(&i2
, &d
);
797 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
806 static void FAIL(void) {}
809 static CFStringRef
__CFNumberCopyDescription(CFTypeRef cf
) {
810 CFNumberRef number
= (CFNumberRef
)cf
;
811 CFNumberType type
= __CFNumberGetType(number
);
812 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
813 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
814 if (__CFNumberTypeTable
[type
].floatBit
) {
816 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
818 CFStringAppend(mstr
, CFSTR("nan"));
819 } else if (isinf(d
)) {
820 CFStringAppend(mstr
, (0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
821 } else if (0.0 == d
) {
822 CFStringAppend(mstr
, (copysign(1.0, d
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
824 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.*f"), (__CFNumberTypeTable
[type
].storageBit
? 20 : 10), d
);
826 const char *typeName
= "unknown float";
828 case kCFNumberFloat32Type
: typeName
= "kCFNumberFloat32Type"; break;
829 case kCFNumberFloat64Type
: typeName
= "kCFNumberFloat64Type"; break;
831 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = %s}"), typeName
);
834 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
836 emit128(buffer
, &i
, true);
837 const char *typeName
= "unknown integer";
839 case kCFNumberSInt8Type
: typeName
= "kCFNumberSInt8Type"; break;
840 case kCFNumberSInt16Type
: typeName
= "kCFNumberSInt16Type"; break;
841 case kCFNumberSInt32Type
: typeName
= "kCFNumberSInt32Type"; break;
842 case kCFNumberSInt64Type
: typeName
= "kCFNumberSInt64Type"; break;
843 case kCFNumberSInt128Type
: typeName
= "kCFNumberSInt128Type"; break;
845 CFStringAppendFormat(mstr
, NULL
, CFSTR("%s, type = %s}"), buffer
, typeName
);
848 if (! number
->__old__
) {
850 printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf
);
852 CFStringRef test
= __CFNumberCopyDescription_old(number
->__old__
);
853 if (!CFEqual(test
, mstr
)) {
854 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test
, mstr
); FAIL();
861 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
863 static CFStringRef
__CFNumberCreateFormattingDescriptionAsFloat64(CFAllocatorRef allocator
, CFTypeRef cf
) {
865 CFNumberGetValue((CFNumberRef
)cf
, kCFNumberFloat64Type
, &d
);
867 return (CFStringRef
)CFRetain(CFSTR("nan"));
870 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
873 return (CFStringRef
)CFRetain(CFSTR("0.0"));
875 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
876 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
879 CF_PRIVATE CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf
) {
880 CFStringRef result
= __CFNumberCreateFormattingDescriptionAsFloat64(kCFAllocatorSystemDefault
, cf
);
882 CFNumberRef number
= (CFNumberRef
)cf
;
883 if (! number
->__old__
) {
884 printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf
);
886 CFStringRef test
= __CFNumberCopyFormattingDescriptionAsFloat64_old(number
->__old__
);
887 if (!CFEqual(test
, result
)) {
888 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test
, result
); FAIL();
895 CF_PRIVATE CFStringRef
__CFNumberCreateFormattingDescription(CFAllocatorRef allocator
, CFTypeRef cf
, CFDictionaryRef formatOptions
) {
896 CFNumberRef number
= (CFNumberRef
)cf
;
897 CFNumberType type
= __CFNumberGetType(number
);
898 if (__CFNumberTypeTable
[type
].floatBit
) {
899 return __CFNumberCreateFormattingDescriptionAsFloat64(allocator
, number
);
902 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
904 emit128(buffer
, &i
, false);
905 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("%s"), buffer
);
908 static CFStringRef
__CFNumberCopyFormattingDescription_new(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
909 CFNumberRef number
= (CFNumberRef
)cf
;
910 CFNumberType type
= __CFNumberGetType(number
);
911 if (__CFNumberTypeTable
[type
].floatBit
) {
912 return __CFNumberCopyFormattingDescriptionAsFloat64(number
);
915 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
917 emit128(buffer
, &i
, false);
918 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%s"), buffer
);
921 CF_PRIVATE CFStringRef
__CFNumberCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
922 CFStringRef result
= __CFNumberCopyFormattingDescription_new(cf
, formatOptions
);
924 CFNumberRef number
= (CFNumberRef
)cf
;
925 if (! number
->__old__
) {
926 printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf
);
928 CFStringRef test
= __CFNumberCopyFormattingDescription_old(number
->__old__
, formatOptions
);
929 if (!CFEqual(test
, result
)) {
930 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test
, result
); FAIL();
938 static Boolean
__CFNumberEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
939 Boolean b
= CFNumberCompare((CFNumberRef
)cf1
, (CFNumberRef
)cf2
, 0) == kCFCompareEqualTo
;
941 CFNumberRef number1
= (CFNumberRef
)cf1
;
942 CFNumberRef number2
= (CFNumberRef
)cf2
;
943 if (! number1
->__old__
|| !number2
->__old__
) {
944 printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1
, cf2
);
946 Boolean b2
= __CFNumberEqual_old(number1
->__old__
, number2
->__old__
);
948 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2
, b
); FAIL();
955 static CFHashCode
__CFNumberHash(CFTypeRef cf
) {
957 CFNumberRef number
= (CFNumberRef
)cf
;
958 switch (__CFNumberGetType(number
)) {
959 case kCFNumberSInt8Type
:
960 case kCFNumberSInt16Type
:
961 case kCFNumberSInt32Type
: {
963 __CFNumberGetValue(number
, kCFNumberSInt32Type
, &i
);
969 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
970 h
= _CFHashDouble((double)d
);
975 CFNumberRef number1
= (CFNumberRef
)cf
;
976 if (! number1
->__old__
) {
977 printf("*** Test skipped in __CFNumberHash for number %p\n", cf
);
979 CFHashCode h2
= __CFNumberHash_old(number1
->__old__
);
981 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2
, h
); FAIL();
988 static CFTypeID __kCFNumberTypeID
= _kCFRuntimeNotATypeID
;
991 kCFNumberCachingEnabled
= 0,
992 kCFNumberCachingDisabled
= 1,
993 kCFNumberCachingFullyDisabled
= 2
995 static char __CFNumberCaching
= kCFNumberCachingEnabled
;
997 static const CFRuntimeClass __CFNumberClass
= {
1005 __CFNumberCopyFormattingDescription
,
1006 __CFNumberCopyDescription
1010 CF_PRIVATE
void __CFNumberInitialize(void) {
1011 __kCFNumberTypeID
= _CFRuntimeRegisterClass(&__CFNumberClass
);
1013 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN
, __kCFNumberTypeID
);
1014 __CFBitfieldSetValue(__kCFNumberNaN
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1015 __kCFNumberNaN
._pad
= BITSFORDOUBLENAN
;
1017 _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity
, __kCFNumberTypeID
);
1018 __CFBitfieldSetValue(__kCFNumberNegativeInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1019 __kCFNumberNegativeInfinity
._pad
= BITSFORDOUBLENEGINF
;
1021 _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity
, __kCFNumberTypeID
);
1022 __CFBitfieldSetValue(__kCFNumberPositiveInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1023 __kCFNumberPositiveInfinity
._pad
= BITSFORDOUBLEPOSINF
;
1026 const char *caching
= __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled
1027 if (caching
) __CFNumberCaching
= (!strcmp(caching
, "all")) ? kCFNumberCachingFullyDisabled
: kCFNumberCachingDisabled
; // initial state above is kCFNumberCachingEnabled
1030 CFTypeID
CFNumberGetTypeID(void) {
1031 return __kCFNumberTypeID
;
1034 #define MinCachedInt (-1)
1035 #define MaxCachedInt (12)
1036 #define NotToBeCached (MinCachedInt - 1)
1037 static CFNumberRef __CFNumberCache
[MaxCachedInt
- MinCachedInt
+ 1] = {NULL
}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
1039 CFNumberRef
CFNumberCreate(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1040 __CFAssertIsValidNumberType(type
);
1041 //printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
1043 if (!allocator
) allocator
= __CFGetDefaultAllocator();
1046 // Look for cases where we can return a cached instance.
1047 // We only use cached objects if the allocator is the system
1048 // default allocator, except for the special floating point
1049 // constant objects, where we return the cached object
1050 // regardless of allocator, since that is what has always
1051 // been done (and now must for compatibility).
1052 int64_t valToBeCached
= NotToBeCached
;
1054 if (__CFNumberTypeTable
[type
].floatBit
) {
1055 CFNumberRef cached
= NULL
;
1056 if (0 == __CFNumberTypeTable
[type
].storageBit
) {
1057 Float32 f
= *(Float32
*)valuePtr
;
1058 if (isnan(f
)) cached
= kCFNumberNaN
;
1059 if (isinf(f
)) cached
= (f
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1061 Float64 d
= *(Float64
*)valuePtr
;
1062 if (isnan(d
)) cached
= kCFNumberNaN
;
1063 if (isinf(d
)) cached
= (d
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1065 if (cached
) return (CFNumberRef
)CFRetain(cached
);
1066 } else if (_CFAllocatorIsSystemDefault(allocator
) && (__CFNumberCaching
== kCFNumberCachingEnabled
)) {
1067 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1068 case kCFNumberSInt8Type
: {int8_t val
= *(int8_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1069 case kCFNumberSInt16Type
: {int16_t val
= *(int16_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1070 case kCFNumberSInt32Type
: {int32_t val
= *(int32_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1071 case kCFNumberSInt64Type
: {int64_t val
= *(int64_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1073 if (NotToBeCached
!= valToBeCached
) {
1074 CFNumberRef cached
= __CFNumberCache
[valToBeCached
- MinCachedInt
]; // Atomic to access the value in the cache
1075 if (NULL
!= cached
) return (CFNumberRef
)CFRetain(cached
);
1079 CFIndex size
= 8 + ((!__CFNumberTypeTable
[type
].floatBit
&& __CFNumberTypeTable
[type
].storageBit
) ? 8 : 0);
1081 size
+= 2 * sizeof(void *);
1083 CFNumberRef result
= (CFNumberRef
)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, size
, NULL
);
1084 if (NULL
== result
) {
1087 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)__CFNumberTypeTable
[type
].canonicalType
);
1090 ((struct __CFNumber
*)result
)->__old__
= CFNumberCreate_old(allocator
, type
, valuePtr
);
1091 CFLog(kCFLogLevelWarning
, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result
->__old__
));
1095 // for a value to be cached, we already have the value handy
1096 if (NotToBeCached
!= valToBeCached
) {
1097 memmove((void *)&result
->_pad
, &valToBeCached
, 8);
1098 // 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.
1099 // 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.
1100 // Barrier assures that the number that is placed in the cache is properly formed.
1101 CFNumberType origType
= __CFNumberGetType(result
);
1102 // Force all cached numbers to have the same type, so that the type does not
1103 // depend on the order and original type in/with which the numbers are created.
1104 // Forcing the type AFTER it was cached would cause a race condition with other
1105 // threads pulling the number object out of the cache and using it.
1106 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)kCFNumberSInt32Type
);
1107 if (OSAtomicCompareAndSwapPtrBarrier(NULL
, (void *)result
, (void *volatile *)&__CFNumberCache
[valToBeCached
- MinCachedInt
])) {
1110 // Did not cache the number object, put original type back.
1111 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)origType
);
1117 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1118 case kCFNumberSInt8Type
: value
= (uint64_t)(int64_t)*(int8_t *)valuePtr
; goto smallVal
;
1119 case kCFNumberSInt16Type
: value
= (uint64_t)(int64_t)*(int16_t *)valuePtr
; goto smallVal
;
1120 case kCFNumberSInt32Type
: value
= (uint64_t)(int64_t)*(int32_t *)valuePtr
; goto smallVal
;
1121 smallVal
: memmove((void *)&result
->_pad
, &value
, 8); break;
1122 case kCFNumberSInt64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1123 case kCFNumberSInt128Type
: memmove((void *)&result
->_pad
, valuePtr
, 16); break;
1124 case kCFNumberFloat32Type
: memmove((void *)&result
->_pad
, valuePtr
, 4); break;
1125 case kCFNumberFloat64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1127 //printf(" => %p\n", result);
1131 CFNumberType
CFNumberGetType(CFNumberRef number
) {
1132 //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
1133 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID
, CFNumberType
, (NSNumber
*)number
, _cfNumberType
);
1134 __CFAssertIsNumber(number
);
1135 CFNumberType type
= __CFNumberGetType(number
);
1136 if (kCFNumberSInt128Type
== type
) type
= kCFNumberSInt64Type
; // must hide this type, since it is not public
1137 //printf(" => %d\n", type);
1139 if (! number
->__old__
) {
1140 printf("*** Test skipped in CFNumberGetType for number %p\n", number
);
1142 CFNumberType t2
= CFNumberGetType_old(number
->__old__
);
1144 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2
, type
); FAIL();
1151 CF_EXPORT CFNumberType
_CFNumberGetType2(CFNumberRef number
) {
1152 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID
, CFNumberType
, (NSNumber
*)number
, _cfNumberType
);
1153 __CFAssertIsNumber(number
);
1154 return __CFNumberGetType(number
);
1157 CFIndex
CFNumberGetByteSize(CFNumberRef number
) {
1158 //printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
1159 __CFAssertIsNumber(number
);
1160 CFIndex r
= 1 << __CFNumberTypeTable
[CFNumberGetType(number
)].lgByteSize
;
1161 //printf(" => %d\n", r);
1163 if (! number
->__old__
) {
1164 printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number
);
1166 CFIndex r2
= CFNumberGetByteSize_old(number
->__old__
);
1168 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2
, r
); FAIL();
1175 Boolean
CFNumberIsFloatType(CFNumberRef number
) {
1176 //printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1177 __CFAssertIsNumber(number
);
1178 Boolean r
= __CFNumberTypeTable
[CFNumberGetType(number
)].floatBit
;
1179 //printf(" => %d\n", r);
1181 if (! number
->__old__
) {
1182 printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number
);
1184 Boolean r2
= CFNumberIsFloatType_old(number
->__old__
);
1186 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2
, r
); FAIL();
1193 Boolean
CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
1194 //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1196 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID
, Boolean
, (NSNumber
*)number
, _getValue
:(void *)valuePtr forType
:(CFNumberType
)__CFNumberTypeTable
[type
].canonicalType
);
1197 __CFAssertIsNumber(number
);
1198 __CFAssertIsValidNumberType(type
);
1199 uint8_t localMemory
[128];
1200 Boolean r
= __CFNumberGetValueCompat(number
, type
, valuePtr
? valuePtr
: localMemory
);
1201 //printf(" => %d\n", r);
1203 if (! number
->__old__
) {
1204 printf("*** Test skipped in CFNumberGetValue for number %p\n", number
);
1206 uint8_t localMemory2
[128];
1207 Boolean r2
= CFNumberGetValue_old(number
->__old__
, type
, localMemory2
);
1209 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2
, r
); FAIL();
1211 if (0 != memcmp(localMemory2
, valuePtr
, CFNumberGetByteSize(number
))) {
1212 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME")); FAIL();
1219 static CFComparisonResult
CFNumberCompare_new(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1220 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID
, CFComparisonResult
, (NSNumber
*)number1
, compare
:(NSNumber
*)number2
);
1221 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID
, CFComparisonResult
, (NSNumber
*)number2
, _reverseCompare
:(NSNumber
*)number1
);
1222 __CFAssertIsNumber(number1
);
1223 __CFAssertIsNumber(number2
);
1225 CFNumberType type1
= __CFNumberGetType(number1
);
1226 CFNumberType type2
= __CFNumberGetType(number2
);
1227 // Both numbers are integers
1228 if (!__CFNumberTypeTable
[type1
].floatBit
&& !__CFNumberTypeTable
[type2
].floatBit
) {
1229 CFSInt128Struct i1
, i2
;
1230 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1231 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1232 return cmp128(&i1
, &i2
);
1234 // Both numbers are floats
1235 if (__CFNumberTypeTable
[type1
].floatBit
&& __CFNumberTypeTable
[type2
].floatBit
) {
1237 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1238 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1239 double s1
= copysign(1.0, d1
);
1240 double s2
= copysign(1.0, d2
);
1241 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1242 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1243 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1244 // at this point, we know we don't have any NaNs
1245 if (s1
< s2
) return kCFCompareLessThan
;
1246 if (s2
< s1
) return kCFCompareGreaterThan
;
1247 // at this point, we know the signs are the same; do not combine these tests
1248 if (d1
< d2
) return kCFCompareLessThan
;
1249 if (d2
< d1
) return kCFCompareGreaterThan
;
1250 return kCFCompareEqualTo
;
1252 // One float, one integer; swap if necessary so number1 is the float
1253 Boolean swapResult
= false;
1254 if (__CFNumberTypeTable
[type2
].floatBit
) {
1255 CFNumberRef tmp
= number1
;
1260 // At large integer values, the precision of double is quite low
1261 // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1262 // If we just used double compare, that would make the 2^73 largest 128-bit
1263 // integers look equal, so we have to use integer comparison when possible.
1265 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1266 // if the double value is really big, cannot be equal to integer
1267 // nan d1 will not compare true here
1268 if (d1
< FLOAT_NEGATIVE_2_TO_THE_127
) {
1269 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1271 if (FLOAT_POSITIVE_2_TO_THE_127
<= d1
) {
1272 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1274 CFSInt128Struct i1
, i2
;
1275 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1276 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1277 CFComparisonResult res
= cmp128(&i1
, &i2
);
1278 if (kCFCompareEqualTo
!= res
) {
1279 return !swapResult
? res
: -res
;
1281 // now things are equal, but perhaps due to rounding or nan
1283 if (isNeg128(&i2
)) {
1284 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1286 // nan compares less than positive 0 too
1287 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1289 // at this point, we know we don't have NaN
1290 double s1
= copysign(1.0, d1
);
1291 double s2
= isNeg128(&i2
) ? -1.0 : 1.0;
1292 if (s1
< s2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1293 if (s2
< s1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1294 // at this point, we know the signs are the same; do not combine these tests
1295 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1296 if (d1
< d2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1297 if (d2
< d1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1298 return kCFCompareEqualTo
;
1301 CFComparisonResult
CFNumberCompare(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1302 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1303 CFComparisonResult r
= CFNumberCompare_new(number1
, number2
, context
);
1304 //printf(" => %d\n", r);
1306 if (! number1
->__old__
|| !number2
->__old__
) {
1307 printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1
, number2
);
1309 CFComparisonResult r2
= CFNumberCompare_old(number1
->__old__
, number2
->__old__
, context
);
1311 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2
, r
); FAIL();
1320 static const unsigned char __CFNumberCanonicalType
[kCFNumberMaxType
+ 1] = {
1321 0, kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1322 kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1323 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1326 static const unsigned char __CFNumberStorageType
[kCFNumberMaxType
+ 1] = {
1327 0, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1328 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1329 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1334 // Returns the type that is used to store the specified type
1335 static CFNumberType
__CFNumberGetStorageTypeForType_old(CFNumberType type
) {
1336 return __CFNumberStorageType
[type
];
1339 // Returns the canonical type used to represent the specified type
1340 static CFNumberType
__CFNumberGetCanonicalTypeForType_old(CFNumberType type
) {
1341 return __CFNumberCanonicalType
[type
];
1344 // Extracts and returns the type out of the CFNumber
1345 static CFNumberType
__CFNumberGetType_old(struct __CFNumber_old
* num
) {
1346 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
1349 // Returns true if the argument type is float or double
1350 static Boolean
__CFNumberTypeIsFloat_old(CFNumberType type
) {
1351 return (type
== kCFNumberFloat64Type
) || (type
== kCFNumberFloat32Type
) || (type
== kCFNumberDoubleType
) || (type
== kCFNumberFloatType
);
1354 // Returns the number of bytes necessary to store the specified type
1355 // Needs to handle all canonical types
1356 static CFIndex
__CFNumberSizeOfType_old(CFNumberType type
) {
1358 case kCFNumberSInt8Type
: return sizeof(int8_t);
1359 case kCFNumberSInt16Type
: return sizeof(int16_t);
1360 case kCFNumberSInt32Type
: return sizeof(SInt32
);
1361 case kCFNumberSInt64Type
: return sizeof(int64_t);
1362 case kCFNumberFloat32Type
: return sizeof(Float32
);
1363 case kCFNumberFloat64Type
: return sizeof(Float64
);
1364 default: printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
1368 // Copies an external value of a given type into the appropriate slot in the union (does no type conversion)
1369 // Needs to handle all canonical types
1370 #define SET_VALUE(valueUnion, type, valuePtr) \
1372 case kCFNumberSInt8Type: (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
1373 case kCFNumberSInt16Type: (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break; \
1374 case kCFNumberSInt32Type: (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
1375 case kCFNumberSInt64Type: (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break; \
1376 case kCFNumberFloat32Type: (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break; \
1377 case kCFNumberFloat64Type: (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break; \
1378 default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
1381 // Casts the specified value into the specified type and copies it into the provided memory
1382 // Needs to handle all canonical types
1383 #define GET_VALUE(value, type, resultPtr) \
1385 case kCFNumberSInt8Type: *(int8_t *)(resultPtr) = (int8_t)value; break; \
1386 case kCFNumberSInt16Type: *(int16_t *)(resultPtr) = (int16_t)value; break; \
1387 case kCFNumberSInt32Type: *(SInt32 *)(resultPtr) = (SInt32)value; break; \
1388 case kCFNumberSInt64Type: *(int64_t *)(resultPtr) = (int64_t)value; break; \
1389 case kCFNumberFloat32Type: *(Float32 *)(resultPtr) = (Float32)value; break; \
1390 case kCFNumberFloat64Type: *(Float64 *)(resultPtr) = (Float64)value; break; \
1391 default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
1394 // Extracts the stored type out of the union and copies it in the desired type into the provided memory
1395 // Needs to handle all storage types
1396 static void __CFNumberGetValue_old(const __CFNumberValue_old
*value
, CFNumberType numberType
, CFNumberType typeToGet
, void *valuePtr
) {
1397 switch (numberType
) {
1398 case kCFNumberSInt32Type
: GET_VALUE(value
->valSInt32
, typeToGet
, valuePtr
); break;
1399 case kCFNumberSInt64Type
: GET_VALUE(value
->valSInt64
, typeToGet
, valuePtr
); break;
1400 case kCFNumberFloat32Type
: GET_VALUE(value
->valFloat32
, typeToGet
, valuePtr
); break;
1401 case kCFNumberFloat64Type
: GET_VALUE(value
->valFloat64
, typeToGet
, valuePtr
); break;
1402 default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
1406 // Sees if two value union structs have the same value (will do type conversion)
1407 static Boolean
__CFNumberEqualValue_old(const __CFNumberValue_old
*value1
, CFNumberType type1
, const __CFNumberValue_old
*value2
, CFNumberType type2
) {
1408 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1410 __CFNumberGetValue_old(value1
, type1
, kCFNumberFloat64Type
, &d1
);
1411 __CFNumberGetValue_old(value2
, type2
, kCFNumberFloat64Type
, &d2
);
1412 if (isnan(d1
) && isnan(d2
)) return true; // Not mathematically sound, but required
1416 __CFNumberGetValue_old(value1
, type1
, kCFNumberSInt64Type
, &i1
);
1417 __CFNumberGetValue_old(value2
, type2
, kCFNumberSInt64Type
, &i2
);
1422 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
) {
1423 struct __CFNumber_old
* number1
= (struct __CFNumber_old
*)cf1
;
1424 struct __CFNumber_old
* number2
= (struct __CFNumber_old
*)cf2
;
1425 return __CFNumberEqualValue_old(&(number1
->value
), __CFNumberGetType_old(number1
), &(number2
->value
), __CFNumberGetType_old(number2
));
1428 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
) {
1429 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1430 switch (__CFNumberGetType_old((struct __CFNumber_old
*)cf
)) {
1431 case kCFNumberSInt32Type
: return _CFHashInt(number
->value
.valSInt32
);
1432 case kCFNumberSInt64Type
: return _CFHashDouble((double)(number
->value
.valSInt64
));
1433 case kCFNumberFloat32Type
: return _CFHashDouble((double)(number
->value
.valFloat32
));
1434 case kCFNumberFloat64Type
: return _CFHashDouble((double)(number
->value
.valFloat64
));
1435 default: printf("*** WARNING default case in __CFNumberHash_old\n");
1440 #define BUFFER_SIZE 100
1441 #define emitChar(ch) \
1442 {if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
1444 static void __CFNumberEmitInt64_old(CFMutableStringRef mstr
, int64_t value
, int32_t width
, UniChar pad
, bool explicitPlus
) {
1445 UniChar stackBuf
[BUFFER_SIZE
], *buf
= stackBuf
;
1446 uint64_t uvalue
, factor
, tmp
;
1450 neg
= (value
< 0) ? true : false;
1451 uvalue
= (neg
) ? -value
: value
;
1452 if (neg
|| explicitPlus
) width
--;
1461 for (w
= 0; w
< width
; w
++) emitChar(pad
);
1464 } else if (explicitPlus
) {
1467 while (0 < factor
) {
1468 UniChar ch
= '0' + (UniChar
)(uvalue
/ factor
);
1473 if (buf
> stackBuf
) CFStringAppendCharacters(mstr
, stackBuf
, buf
- stackBuf
);
1476 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
) {
1477 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1478 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1479 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
1480 switch (__CFNumberGetType_old(number
)) {
1481 case kCFNumberSInt32Type
:
1482 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt32
, 0, ' ', true);
1483 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt32Type}"));
1485 case kCFNumberSInt64Type
:
1486 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt64
, 0, ' ', true);
1487 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt64Type}"));
1489 case kCFNumberFloat32Type
:
1490 // debugging formatting is intentionally more verbose and explicit about the value of the number
1491 if (isnan(number
->value
.valFloat32
)) {
1492 CFStringAppend(mstr
, CFSTR("nan"));
1493 } else if (isinf(number
->value
.valFloat32
)) {
1494 CFStringAppend(mstr
, (0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1495 } else if (0.0f
== number
->value
.valFloat32
) {
1496 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat32
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1498 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.10f"), number
->value
.valFloat32
);
1500 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat32Type}"));
1502 case kCFNumberFloat64Type
:
1503 // debugging formatting is intentionally more verbose and explicit about the value of the number
1504 if (isnan(number
->value
.valFloat64
)) {
1505 CFStringAppend(mstr
, CFSTR("nan"));
1506 } else if (isinf(number
->value
.valFloat64
)) {
1507 CFStringAppend(mstr
, (0.0 < number
->value
.valFloat64
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1508 } else if (0.0 == number
->value
.valFloat64
) {
1509 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat64
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1511 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.20f"), number
->value
.valFloat64
);
1513 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat64Type}"));
1522 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
1524 CF_PRIVATE CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
) {
1526 CFNumberGetValue_old((struct __CFNumber_old
*)cf
, kCFNumberFloat64Type
, &d
);
1528 return (CFStringRef
)CFRetain(CFSTR("nan"));
1531 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1534 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1536 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
1537 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
1540 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
1541 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1542 CFMutableStringRef mstr
;
1544 switch (__CFNumberGetType_old(number
)) {
1545 case kCFNumberSInt32Type
:
1546 case kCFNumberSInt64Type
:
1547 value
= (__CFNumberGetType_old(number
) == kCFNumberSInt32Type
) ? number
->value
.valSInt32
: number
->value
.valSInt64
;
1548 mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1549 __CFNumberEmitInt64_old(mstr
, value
, 0, ' ', false);
1551 case kCFNumberFloat32Type
:
1552 if (isnan(number
->value
.valFloat32
)) {
1553 return (CFStringRef
)CFRetain(CFSTR("nan"));
1555 if (isinf(number
->value
.valFloat32
)) {
1556 return (CFStringRef
)CFRetain((0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1558 if (0.0f
== number
->value
.valFloat32
) {
1559 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1561 // if %g is used here, need to use FLT_DIG + 2 on Mac OS X, but %f needs +1
1562 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), FLT_DIG
+ 2, number
->value
.valFloat32
);
1563 case kCFNumberFloat64Type
:
1564 return __CFNumberCopyFormattingDescriptionAsFloat64_old(number
);
1573 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1574 struct __CFNumber_old
* num
;
1575 CFNumberType equivType
, storageType
;
1578 CFSInt128Struct
*s
= valuePtr
;
1579 s
->high
= (int64_t)s
->low
;
1580 type
= kCFNumberSInt64Type
;
1584 equivType
= __CFNumberGetCanonicalTypeForType_old(type
);
1586 storageType
= __CFNumberGetStorageTypeForType_old(type
);
1588 num
= (struct __CFNumber_old
*)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, __CFNumberSizeOfType_old(storageType
), NULL
);
1592 SET_VALUE((__CFNumberValue_old
*)&(num
->value
), equivType
, valuePtr
);
1593 __CFBitfieldSetValue(((struct __CFNumber_old
*)num
)->_base
._cfinfo
[CF_INFO_BITS
], 6, 0, (uint8_t)storageType
);
1595 if (__CFNumberGetType_old(num
) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num
, storageType
);
1599 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
) {
1601 return __CFNumberGetType_old(number
);
1604 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
) {
1605 return __CFNumberSizeOfType_old(CFNumberGetType_old(number
));
1608 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
) {
1609 return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number
));
1612 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
) {
1613 uint8_t localMemory
[sizeof(__CFNumberValue_old
)];
1614 __CFNumberValue_old localValue
;
1615 CFNumberType numType
;
1616 CFNumberType storageTypeForType
;
1618 if (type
== 17) type
= kCFNumberSInt64Type
;
1620 storageTypeForType
= __CFNumberGetStorageTypeForType_old(type
);
1621 type
= __CFNumberGetCanonicalTypeForType_old(type
);
1622 if (!valuePtr
) valuePtr
= &localMemory
;
1624 numType
= __CFNumberGetType_old(number
);
1625 __CFNumberGetValue_old((__CFNumberValue_old
*)&(number
->value
), numType
, type
, valuePtr
);
1627 // If the types match, then we're fine!
1628 if (numType
== storageTypeForType
) return true;
1630 // Test to see if the returned value is intact...
1631 SET_VALUE(&localValue
, type
, valuePtr
);
1632 return __CFNumberEqualValue_old(&localValue
, storageTypeForType
, &(number
->value
), numType
);
1635 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
) {
1636 CFNumberType type1
, type2
;
1639 type1
= __CFNumberGetType_old(number1
);
1640 type2
= __CFNumberGetType_old(number2
);
1642 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1645 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberFloat64Type
, &d1
);
1646 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberFloat64Type
, &d2
);
1647 s1
= copysign(1.0, d1
);
1648 s2
= copysign(1.0, d2
);
1649 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1650 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1651 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1652 // at this point, we know we don't have any NaNs
1653 if (s1
< s2
) return kCFCompareLessThan
;
1654 if (s2
< s1
) return kCFCompareGreaterThan
;
1655 // at this point, we know the signs are the same; do not combine these tests
1656 if (d1
< d2
) return kCFCompareLessThan
;
1657 if (d2
< d1
) return kCFCompareGreaterThan
;
1658 return kCFCompareEqualTo
;
1661 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberSInt64Type
, &i1
);
1662 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberSInt64Type
, &i2
);
1663 return (i1
> i2
) ? kCFCompareGreaterThan
: ((i1
< i2
) ? kCFCompareLessThan
: kCFCompareEqualTo
);
1670 #undef __CFAssertIsBoolean
1671 #undef __CFAssertIsNumber
1672 #undef __CFAssertIsValidNumberType
1673 #undef BITSFORDOUBLENAN
1674 #undef BITSFORDOUBLEPOSINF
1675 #undef BITSFORDOUBLENEGINF
1678 #undef NotToBeCached