2 * Copyright (c) 2009 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-2009, Apple Inc. All rights reserved.
26 Responsibility: Ali Ozer
29 #include <CoreFoundation/CFNumber.h>
30 #include "CFInternal.h"
31 #include <CoreFoundation/CFPriv.h>
35 #if DEPLOYMENT_TARGET_WINDOWS
36 #define isnan(A) _isnan(A)
37 #define isinf(A) !_finite(A)
38 #define copysign(A, B) _copysign(A, B)
39 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
41 #error Unknown or unspecified DEPLOYMENT_TARGET
44 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
50 static struct __CFBoolean __kCFBooleanTrue
= {
53 const CFBooleanRef kCFBooleanTrue
= &__kCFBooleanTrue
;
55 static struct __CFBoolean __kCFBooleanFalse
= {
58 const CFBooleanRef kCFBooleanFalse
= &__kCFBooleanFalse
;
60 static CFStringRef
__CFBooleanCopyDescription(CFTypeRef cf
) {
61 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
62 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf
, CFGetAllocator(cf
), (boolean
== kCFBooleanTrue
) ? "true" : "false");
65 static CFStringRef
__CFBooleanCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
66 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
67 return (CFStringRef
)CFRetain((boolean
== kCFBooleanTrue
) ? CFSTR("true") : CFSTR("false"));
70 static CFHashCode
__CFBooleanHash(CFTypeRef cf
) {
71 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
72 return (boolean
== kCFBooleanTrue
) ? _CFHashInt(1) : _CFHashInt(0);
75 static void __CFBooleanDeallocate(CFTypeRef cf
) {
76 CFAssert(false, __kCFLogAssertion
, "Deallocated CFBoolean!");
79 static CFTypeID __kCFBooleanTypeID
= _kCFRuntimeNotATypeID
;
81 static const CFRuntimeClass __CFBooleanClass
= {
86 __CFBooleanDeallocate
,
89 __CFBooleanCopyFormattingDescription
,
90 __CFBooleanCopyDescription
93 __private_extern__
void __CFBooleanInitialize(void) {
94 __kCFBooleanTypeID
= _CFRuntimeRegisterClass(&__CFBooleanClass
);
95 _CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue
, __kCFBooleanTypeID
);
96 __kCFBooleanTrue
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
97 _CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse
, __kCFBooleanTypeID
);
98 __kCFBooleanFalse
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
101 CFTypeID
CFBooleanGetTypeID(void) {
102 return __kCFBooleanTypeID
;
105 Boolean
CFBooleanGetValue(CFBooleanRef boolean
) {
106 CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID
, Boolean
, boolean
, "boolValue");
107 return (boolean
== kCFBooleanTrue
) ? true : false;
113 #define OLD_CRAP_TOO 0
122 } __CFNumberValue_old
;
124 struct __CFNumber_old
{ /* Only as many bytes as necessary are allocated */
126 __CFNumberValue_old value
;
129 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
);
130 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
);
131 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
);
132 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
);
133 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
);
134 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
);
135 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
);
136 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
);
137 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
);
138 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
);
139 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
);
144 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
145 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
147 /* The IEEE bit patterns... Also have:
148 0x7f800000 float +Inf
150 0xff800000 float -Inf
152 #define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
153 #define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
154 #define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
156 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
157 #define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
158 #define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
159 #define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
160 #elif DEPLOYMENT_TARGET_WINDOWS
161 #define FLOAT_POSITIVE_2_TO_THE_64 18446744073709551616.0
162 #define FLOAT_NEGATIVE_2_TO_THE_127 -170141183460469231731687303715884105728.0
163 #define FLOAT_POSITIVE_2_TO_THE_127 170141183460469231731687303715884105728.0
165 #error Unknown or unspecified DEPLOYMENT_TARGET
168 typedef struct { // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
174 kCFNumberSInt128Type
= 17
177 static uint8_t isNeg128(const CFSInt128Struct
*in
) {
181 static CFComparisonResult
cmp128(const CFSInt128Struct
*in1
, const CFSInt128Struct
*in2
) {
182 if (in1
->high
< in2
->high
) return kCFCompareLessThan
;
183 if (in1
->high
> in2
->high
) return kCFCompareGreaterThan
;
184 if (in1
->low
< in2
->low
) return kCFCompareLessThan
;
185 if (in1
->low
> in2
->low
) return kCFCompareGreaterThan
;
186 return kCFCompareEqualTo
;
189 // allows out to be the same as in1 or in2
190 static void add128(CFSInt128Struct
*out
, CFSInt128Struct
*in1
, CFSInt128Struct
*in2
) {
192 tmp
.low
= in1
->low
+ in2
->low
;
193 tmp
.high
= in1
->high
+ in2
->high
;
194 if (UINT64_MAX
- in1
->low
< in2
->low
) {
200 // allows out to be the same as in
201 static void neg128(CFSInt128Struct
*out
, CFSInt128Struct
*in
) {
202 uint64_t tmplow
= ~in
->low
;
203 out
->low
= tmplow
+ 1;
204 out
->high
= ~in
->high
;
205 if (UINT64_MAX
== tmplow
) {
210 static const CFSInt128Struct powersOf10
[] = {
211 { 0x4B3B4CA85A86C47ALL
, 0x098A224000000000ULL
},
212 { 0x0785EE10D5DA46D9LL
, 0x00F436A000000000ULL
},
213 { 0x00C097CE7BC90715LL
, 0xB34B9F1000000000ULL
},
214 { 0x0013426172C74D82LL
, 0x2B878FE800000000ULL
},
215 { 0x0001ED09BEAD87C0LL
, 0x378D8E6400000000ULL
},
216 { 0x0000314DC6448D93LL
, 0x38C15B0A00000000ULL
},
217 { 0x000004EE2D6D415BLL
, 0x85ACEF8100000000ULL
},
218 { 0x0000007E37BE2022LL
, 0xC0914B2680000000ULL
},
219 { 0x0000000C9F2C9CD0LL
, 0x4674EDEA40000000ULL
},
220 { 0x00000001431E0FAELL
, 0x6D7217CAA0000000ULL
},
221 { 0x00000000204FCE5ELL
, 0x3E25026110000000ULL
},
222 { 0x00000000033B2E3CLL
, 0x9FD0803CE8000000ULL
},
223 { 0x000000000052B7D2LL
, 0xDCC80CD2E4000000ULL
},
224 { 0x0000000000084595LL
, 0x161401484A000000ULL
},
225 { 0x000000000000D3C2LL
, 0x1BCECCEDA1000000ULL
},
226 { 0x000000000000152DLL
, 0x02C7E14AF6800000ULL
},
227 { 0x000000000000021ELL
, 0x19E0C9BAB2400000ULL
},
228 { 0x0000000000000036LL
, 0x35C9ADC5DEA00000ULL
},
229 { 0x0000000000000005LL
, 0x6BC75E2D63100000ULL
},
230 { 0x0000000000000000LL
, 0x8AC7230489E80000ULL
},
231 { 0x0000000000000000LL
, 0x0DE0B6B3A7640000ULL
},
232 { 0x0000000000000000LL
, 0x016345785D8A0000ULL
},
233 { 0x0000000000000000LL
, 0x002386F26FC10000ULL
},
234 { 0x0000000000000000LL
, 0x00038D7EA4C68000ULL
},
235 { 0x0000000000000000LL
, 0x00005AF3107A4000ULL
},
236 { 0x0000000000000000LL
, 0x000009184E72A000ULL
},
237 { 0x0000000000000000LL
, 0x000000E8D4A51000ULL
},
238 { 0x0000000000000000LL
, 0x000000174876E800ULL
},
239 { 0x0000000000000000LL
, 0x00000002540BE400ULL
},
240 { 0x0000000000000000LL
, 0x000000003B9ACA00ULL
},
241 { 0x0000000000000000LL
, 0x0000000005F5E100ULL
},
242 { 0x0000000000000000LL
, 0x0000000000989680ULL
},
243 { 0x0000000000000000LL
, 0x00000000000F4240ULL
},
244 { 0x0000000000000000LL
, 0x00000000000186A0ULL
},
245 { 0x0000000000000000LL
, 0x0000000000002710ULL
},
246 { 0x0000000000000000LL
, 0x00000000000003E8ULL
},
247 { 0x0000000000000000LL
, 0x0000000000000064ULL
},
248 { 0x0000000000000000LL
, 0x000000000000000AULL
},
249 { 0x0000000000000000LL
, 0x0000000000000001ULL
},
252 static const CFSInt128Struct neg_powersOf10
[] = {
253 { 0xB4C4B357A5793B85LL
, 0xF675DDC000000000ULL
},
254 { 0xF87A11EF2A25B926LL
, 0xFF0BC96000000000ULL
},
255 { 0xFF3F68318436F8EALL
, 0x4CB460F000000000ULL
},
256 { 0xFFECBD9E8D38B27DLL
, 0xD478701800000000ULL
},
257 { 0xFFFE12F64152783FLL
, 0xC872719C00000000ULL
},
258 { 0xFFFFCEB239BB726CLL
, 0xC73EA4F600000000ULL
},
259 { 0xFFFFFB11D292BEA4LL
, 0x7A53107F00000000ULL
},
260 { 0xFFFFFF81C841DFDDLL
, 0x3F6EB4D980000000ULL
},
261 { 0xFFFFFFF360D3632FLL
, 0xB98B1215C0000000ULL
},
262 { 0xFFFFFFFEBCE1F051LL
, 0x928DE83560000000ULL
},
263 { 0xFFFFFFFFDFB031A1LL
, 0xC1DAFD9EF0000000ULL
},
264 { 0xFFFFFFFFFCC4D1C3LL
, 0x602F7FC318000000ULL
},
265 { 0xFFFFFFFFFFAD482DLL
, 0x2337F32D1C000000ULL
},
266 { 0xFFFFFFFFFFF7BA6ALL
, 0xE9EBFEB7B6000000ULL
},
267 { 0xFFFFFFFFFFFF2C3DLL
, 0xE43133125F000000ULL
},
268 { 0xFFFFFFFFFFFFEAD2LL
, 0xFD381EB509800000ULL
},
269 { 0xFFFFFFFFFFFFFDE1LL
, 0xE61F36454DC00000ULL
},
270 { 0xFFFFFFFFFFFFFFC9LL
, 0xCA36523A21600000ULL
},
271 { 0xFFFFFFFFFFFFFFFALL
, 0x9438A1D29CF00000ULL
},
272 { 0xFFFFFFFFFFFFFFFFLL
, 0x7538DCFB76180000ULL
},
273 { 0xFFFFFFFFFFFFFFFFLL
, 0xF21F494C589C0000ULL
},
274 { 0xFFFFFFFFFFFFFFFFLL
, 0xFE9CBA87A2760000ULL
},
275 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFDC790D903F0000ULL
},
276 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFC72815B398000ULL
},
277 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFA50CEF85C000ULL
},
278 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFF6E7B18D6000ULL
},
279 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFF172B5AF000ULL
},
280 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFE8B7891800ULL
},
281 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFDABF41C00ULL
},
282 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFC4653600ULL
},
283 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFA0A1F00ULL
},
284 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFF676980ULL
},
285 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFF0BDC0ULL
},
286 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFE7960ULL
},
287 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFD8F0ULL
},
288 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFC18ULL
},
289 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFF9CULL
},
290 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFF6ULL
},
291 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFFFULL
},
294 static void emit128(char *buffer
, const CFSInt128Struct
*in
, Boolean forcePlus
) {
295 CFSInt128Struct tmp
= *in
;
296 if (isNeg128(&tmp
)) {
299 } else if (forcePlus
) {
302 Boolean doneOne
= false;
304 for (idx
= 0; idx
< sizeof(powersOf10
) / sizeof(powersOf10
[0]); idx
++) {
306 while (cmp128(&powersOf10
[idx
], &tmp
) <= 0) {
307 add128(&tmp
, &tmp
, (CFSInt128Struct
*)&neg_powersOf10
[idx
]);
310 if (0 != count
|| doneOne
) {
311 *buffer
++ = '0' + count
;
321 static void cvtSInt128ToFloat64(Float64
*out
, const CFSInt128Struct
*in
) {
322 // switching to a positive number results in better accuracy
323 // for negative numbers close to zero, because the multiply
324 // of -1 by 2^64 (scaling the Float64 high) is avoided
325 Boolean wasNeg
= false;
326 CFSInt128Struct tmp
= *in
;
327 if (isNeg128(&tmp
)) {
331 Float64 d
= (Float64
)tmp
.high
* FLOAT_POSITIVE_2_TO_THE_64
+ (Float64
)tmp
.low
;
336 static void cvtFloat64ToSInt128(CFSInt128Struct
*out
, const Float64
*in
) {
339 if (d
< FLOAT_NEGATIVE_2_TO_THE_127
) {
340 i
.high
= 0x8000000000000000LL
;
341 i
.low
= 0x0000000000000000ULL
;
345 if (FLOAT_POSITIVE_2_TO_THE_127
<= d
) {
346 i
.high
= 0x7fffffffffffffffLL
;
347 i
.low
= 0xffffffffffffffffULL
;
351 Float64 t
= floor(d
/ FLOAT_POSITIVE_2_TO_THE_64
);
353 i
.low
= (uint64_t)(d
- t
* FLOAT_POSITIVE_2_TO_THE_64
);
360 struct __CFNumber_old
*__old__
;
363 uint64_t _pad
; // need this space here for the constant objects
364 /* 0 or 8 more bytes allocated here */
367 /* Seven bits in base:
369 Bits 4..0: CFNumber type
372 static struct __CFNumber __kCFNumberNaN
= {
373 INIT_CFRUNTIME_BASE(), 0ULL
375 const CFNumberRef kCFNumberNaN
= &__kCFNumberNaN
;
377 static struct __CFNumber __kCFNumberNegativeInfinity
= {
378 INIT_CFRUNTIME_BASE(), 0ULL
380 const CFNumberRef kCFNumberNegativeInfinity
= &__kCFNumberNegativeInfinity
;
382 static struct __CFNumber __kCFNumberPositiveInfinity
= {
383 INIT_CFRUNTIME_BASE(), 0ULL
385 const CFNumberRef kCFNumberPositiveInfinity
= &__kCFNumberPositiveInfinity
;
387 static const struct {
388 uint16_t canonicalType
:5; // canonical fixed-width type
389 uint16_t floatBit
:1; // is float
390 uint16_t storageBit
:1; // storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
391 uint16_t lgByteSize
:3; // base-2 log byte size of public type
393 } __CFNumberTypeTable
[] = {
394 /* 0 */ {0, 0, 0, 0},
396 /* kCFNumberSInt8Type */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
397 /* kCFNumberSInt16Type */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
398 /* kCFNumberSInt32Type */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
399 /* kCFNumberSInt64Type */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
400 /* kCFNumberFloat32Type */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
401 /* kCFNumberFloat64Type */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
403 /* kCFNumberCharType */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
404 /* kCFNumberShortType */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
405 /* kCFNumberIntType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
407 /* kCFNumberLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
409 /* kCFNumberLongType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
411 /* kCFNumberLongLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
412 /* kCFNumberFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
413 /* kCFNumberDoubleType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
416 /* kCFNumberCFIndexType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
417 /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
418 /* kCFNumberCGFloatType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
420 /* kCFNumberCFIndexType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
421 /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
422 /* kCFNumberCGFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
425 /* kCFNumberSInt128Type */ {kCFNumberSInt128Type
, 0, 1, 4, 0},
428 CF_INLINE CFNumberType
__CFNumberGetType(CFNumberRef num
) {
429 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
432 #define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
433 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
434 DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
435 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
436 SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
439 #define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
440 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
441 DST_TYPE dv; Boolean noLoss = false; \
442 if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
444 } else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
447 dv = (DST_TYPE)sv.low; \
450 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
454 // returns false if the output value is not the same as the number's value, which
455 // can occur due to accuracy loss and the value not being within the target range
456 static Boolean
__CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
457 type
= __CFNumberTypeTable
[type
].canonicalType
;
458 CFNumberType ntype
= __CFNumberGetType(number
);
459 const void *data
= &(number
->_pad
);
461 case kCFNumberSInt8Type
:
462 if (__CFNumberTypeTable
[ntype
].floatBit
) {
463 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
464 CVT(Float32
, int8_t, INT8_MIN
, INT8_MAX
);
466 CVT(Float64
, int8_t, INT8_MIN
, INT8_MAX
);
469 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
470 CVT(int64_t, int8_t, INT8_MIN
, INT8_MAX
);
472 CVT128ToInt(CFSInt128Struct
, int8_t, INT8_MIN
, INT8_MAX
);
476 case kCFNumberSInt16Type
:
477 if (__CFNumberTypeTable
[ntype
].floatBit
) {
478 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
479 CVT(Float32
, int16_t, INT16_MIN
, INT16_MAX
);
481 CVT(Float64
, int16_t, INT16_MIN
, INT16_MAX
);
484 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
485 CVT(int64_t, int16_t, INT16_MIN
, INT16_MAX
);
487 CVT128ToInt(CFSInt128Struct
, int16_t, INT16_MIN
, INT16_MAX
);
491 case kCFNumberSInt32Type
:
492 if (__CFNumberTypeTable
[ntype
].floatBit
) {
493 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
494 CVT(Float32
, int32_t, INT32_MIN
, INT32_MAX
);
496 CVT(Float64
, int32_t, INT32_MIN
, INT32_MAX
);
499 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
500 CVT(int64_t, int32_t, INT32_MIN
, INT32_MAX
);
502 CVT128ToInt(CFSInt128Struct
, int32_t, INT32_MIN
, INT32_MAX
);
506 case kCFNumberSInt64Type
:
507 if (__CFNumberTypeTable
[ntype
].floatBit
) {
508 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
509 CVT(Float32
, int64_t, INT64_MIN
, INT64_MAX
);
511 CVT(Float64
, int64_t, INT64_MIN
, INT64_MAX
);
514 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
515 memmove(valuePtr
, data
, 8);
517 CVT128ToInt(CFSInt128Struct
, int64_t, INT64_MIN
, INT64_MAX
);
521 case kCFNumberSInt128Type
:
522 if (__CFNumberTypeTable
[ntype
].floatBit
) {
523 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
525 memmove(&f
, data
, 4);
528 cvtFloat64ToSInt128(&i
, &d
);
529 memmove(valuePtr
, &i
, 16);
531 cvtSInt128ToFloat64(&d2
, &i
);
532 Float32 f2
= (Float32
)d2
;
536 memmove(&d
, data
, 8);
538 cvtFloat64ToSInt128(&i
, &d
);
539 memmove(valuePtr
, &i
, 16);
541 cvtSInt128ToFloat64(&d2
, &i
);
545 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
547 memmove(&j
, data
, 8);
550 i
.high
= (j
< 0) ? -1LL : 0LL;
551 memmove(valuePtr
, &i
, 16);
553 memmove(valuePtr
, data
, 16);
557 case kCFNumberFloat32Type
:
558 if (__CFNumberTypeTable
[ntype
].floatBit
) {
559 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
560 memmove(valuePtr
, data
, 4);
563 memmove(&d
, data
, 8);
565 uint32_t l
= 0x7fc00000;
566 memmove(valuePtr
, &l
, 4);
568 } else if (isinf(d
)) {
569 uint32_t l
= 0x7f800000;
570 if (d
< 0.0) l
+= 0x80000000UL
;
571 memmove(valuePtr
, &l
, 4);
574 CVT(Float64
, Float32
, -FLT_MAX
, FLT_MAX
);
577 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
578 CVT(int64_t, Float32
, -FLT_MAX
, FLT_MAX
);
581 memmove(&i
, data
, 16);
583 cvtSInt128ToFloat64(&d
, &i
);
584 Float32 f
= (Float32
)d
;
585 memmove(valuePtr
, &f
, 4);
588 cvtFloat64ToSInt128(&i2
, &d
);
589 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
593 case kCFNumberFloat64Type
:
594 if (__CFNumberTypeTable
[ntype
].floatBit
) {
595 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
597 memmove(&f
, data
, 4);
599 uint64_t l
= BITSFORDOUBLENAN
;
600 memmove(valuePtr
, &l
, 8);
602 } else if (isinf(f
)) {
603 uint64_t l
= BITSFORDOUBLEPOSINF
;
604 if (f
< 0.0) l
+= 0x8000000000000000ULL
;
605 memmove(valuePtr
, &l
, 8);
608 CVT(Float32
, Float64
, -DBL_MAX
, DBL_MAX
);
610 memmove(valuePtr
, data
, 8);
613 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
614 CVT(int64_t, Float64
, -DBL_MAX
, DBL_MAX
);
617 memmove(&i
, data
, 16);
619 cvtSInt128ToFloat64(&d
, &i
);
620 memmove(valuePtr
, &d
, 8);
622 cvtFloat64ToSInt128(&i2
, &d
);
623 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
631 #define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
632 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
633 DST_TYPE dv = (DST_TYPE)(sv); \
634 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
635 SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
638 #define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
639 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
640 DST_TYPE dv; dv = (DST_TYPE)sv.low; \
641 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
642 uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
645 // this has the old cast-style behavior
646 static Boolean
__CFNumberGetValueCompat(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
647 type
= __CFNumberTypeTable
[type
].canonicalType
;
648 CFNumberType ntype
= __CFNumberGetType(number
);
649 const void *data
= &(number
->_pad
);
651 case kCFNumberSInt8Type
:
652 if (__CFNumberTypeTable
[ntype
].floatBit
) {
653 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
654 CVT_COMPAT(Float32
, int8_t, 0);
656 CVT_COMPAT(Float64
, int8_t, 0);
659 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
660 // 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>
661 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
662 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
663 int8_t dv
= (int8_t)(sv
);
664 memmove(valuePtr
, &dv
, sizeof(int8_t));
665 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 8LL) == 0LL) || (vv
== sv
);
667 CVT128ToInt_COMPAT(CFSInt128Struct
, int8_t);
671 case kCFNumberSInt16Type
:
672 if (__CFNumberTypeTable
[ntype
].floatBit
) {
673 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
674 CVT_COMPAT(Float32
, int16_t, 0);
676 CVT_COMPAT(Float64
, int16_t, 0);
679 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
680 // 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>
681 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
682 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
683 int16_t dv
= (int16_t)(sv
);
684 memmove(valuePtr
, &dv
, sizeof(int16_t));
685 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 16LL) == 0LL) || (vv
== sv
);
687 CVT128ToInt_COMPAT(CFSInt128Struct
, int16_t);
691 case kCFNumberSInt32Type
:
692 if (__CFNumberTypeTable
[ntype
].floatBit
) {
693 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
694 CVT_COMPAT(Float32
, int32_t, 0);
696 CVT_COMPAT(Float64
, int32_t, 0);
699 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
700 CVT_COMPAT(int64_t, int32_t, 0);
702 CVT128ToInt_COMPAT(CFSInt128Struct
, int32_t);
706 case kCFNumberSInt64Type
:
707 if (__CFNumberTypeTable
[ntype
].floatBit
) {
708 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
709 CVT_COMPAT(Float32
, int64_t, 0);
711 CVT_COMPAT(Float64
, int64_t, 0);
714 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
715 CVT_COMPAT(int64_t, int64_t, 0);
717 CVT128ToInt_COMPAT(CFSInt128Struct
, int64_t);
721 case kCFNumberSInt128Type
:
722 if (__CFNumberTypeTable
[ntype
].floatBit
) {
723 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
725 memmove(&f
, data
, 4);
728 cvtFloat64ToSInt128(&i
, &d
);
729 memmove(valuePtr
, &i
, 16);
731 cvtSInt128ToFloat64(&d2
, &i
);
732 Float32 f2
= (Float32
)d2
;
736 memmove(&d
, data
, 8);
738 cvtFloat64ToSInt128(&i
, &d
);
739 memmove(valuePtr
, &i
, 16);
741 cvtSInt128ToFloat64(&d2
, &i
);
745 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
747 memmove(&j
, data
, 8);
750 i
.high
= (j
< 0) ? -1LL : 0LL;
751 memmove(valuePtr
, &i
, 16);
753 memmove(valuePtr
, data
, 16);
757 case kCFNumberFloat32Type
:
758 if (__CFNumberTypeTable
[ntype
].floatBit
) {
759 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
760 memmove(valuePtr
, data
, 4);
762 CVT_COMPAT(Float64
, Float32
, 0);
765 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
766 CVT_COMPAT(int64_t, Float32
, 0);
769 memmove(&i
, data
, 16);
771 cvtSInt128ToFloat64(&d
, &i
);
772 Float32 f
= (Float32
)d
;
773 memmove(valuePtr
, &f
, 4);
776 cvtFloat64ToSInt128(&i2
, &d
);
777 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
781 case kCFNumberFloat64Type
:
782 if (__CFNumberTypeTable
[ntype
].floatBit
) {
783 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
784 CVT_COMPAT(Float32
, Float64
, 0);
786 memmove(valuePtr
, data
, 8);
789 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
790 CVT_COMPAT(int64_t, Float64
, 0);
793 memmove(&i
, data
, 16);
795 cvtSInt128ToFloat64(&d
, &i
);
796 memmove(valuePtr
, &d
, 8);
798 cvtFloat64ToSInt128(&i2
, &d
);
799 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
808 static void FAIL(void) {}
811 static CFStringRef
__CFNumberCopyDescription(CFTypeRef cf
) {
812 CFNumberRef number
= (CFNumberRef
)cf
;
813 CFNumberType type
= __CFNumberGetType(number
);
814 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
815 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
816 if (__CFNumberTypeTable
[type
].floatBit
) {
818 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
820 CFStringAppend(mstr
, CFSTR("nan"));
821 } else if (isinf(d
)) {
822 CFStringAppend(mstr
, (0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
823 } else if (0.0 == d
) {
824 CFStringAppend(mstr
, (copysign(1.0, d
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
826 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.*f"), (__CFNumberTypeTable
[type
].storageBit
? 20 : 10), d
);
828 const char *typeName
= "unknown float";
830 case kCFNumberFloat32Type
: typeName
= "kCFNumberFloat32Type"; break;
831 case kCFNumberFloat64Type
: typeName
= "kCFNumberFloat64Type"; break;
833 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = %s}"), typeName
);
836 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
838 emit128(buffer
, &i
, true);
839 const char *typeName
= "unknown integer";
841 case kCFNumberSInt8Type
: typeName
= "kCFNumberSInt8Type"; break;
842 case kCFNumberSInt16Type
: typeName
= "kCFNumberSInt16Type"; break;
843 case kCFNumberSInt32Type
: typeName
= "kCFNumberSInt32Type"; break;
844 case kCFNumberSInt64Type
: typeName
= "kCFNumberSInt64Type"; break;
845 case kCFNumberSInt128Type
: typeName
= "kCFNumberSInt128Type"; break;
847 CFStringAppendFormat(mstr
, NULL
, CFSTR("%s, type = %s}"), buffer
, typeName
);
850 if (! number
->__old__
) {
852 printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf
);
854 CFStringRef test
= __CFNumberCopyDescription_old(number
->__old__
);
855 if (!CFEqual(test
, mstr
)) {
856 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test
, mstr
); FAIL();
863 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
865 static CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_new(CFTypeRef cf
) {
867 CFNumberGetValue((CFNumberRef
)cf
, kCFNumberFloat64Type
, &d
);
869 return (CFStringRef
)CFRetain(CFSTR("nan"));
872 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
875 return (CFStringRef
)CFRetain(CFSTR("0.0"));
877 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
878 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
881 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf
) {
882 CFStringRef result
= __CFNumberCopyFormattingDescriptionAsFloat64_new(cf
);
884 CFNumberRef number
= (CFNumberRef
)cf
;
885 if (! number
->__old__
) {
886 printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf
);
888 CFStringRef test
= __CFNumberCopyFormattingDescriptionAsFloat64_old(number
->__old__
);
889 if (!CFEqual(test
, result
)) {
890 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test
, result
); FAIL();
897 static CFStringRef
__CFNumberCopyFormattingDescription_new(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
898 CFNumberRef number
= (CFNumberRef
)cf
;
899 CFNumberType type
= __CFNumberGetType(number
);
900 if (__CFNumberTypeTable
[type
].floatBit
) {
901 return __CFNumberCopyFormattingDescriptionAsFloat64(number
);
904 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
906 emit128(buffer
, &i
, false);
907 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%s"), buffer
);
910 static CFStringRef
__CFNumberCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
911 CFStringRef result
= __CFNumberCopyFormattingDescription_new(cf
, formatOptions
);
913 CFNumberRef number
= (CFNumberRef
)cf
;
914 if (! number
->__old__
) {
915 printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf
);
917 CFStringRef test
= __CFNumberCopyFormattingDescription_old(number
->__old__
, formatOptions
);
918 if (!CFEqual(test
, result
)) {
919 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test
, result
); FAIL();
927 static Boolean
__CFNumberEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
928 Boolean b
= CFNumberCompare((CFNumberRef
)cf1
, (CFNumberRef
)cf2
, 0) == kCFCompareEqualTo
;
930 CFNumberRef number1
= (CFNumberRef
)cf1
;
931 CFNumberRef number2
= (CFNumberRef
)cf2
;
932 if (! number1
->__old__
|| !number2
->__old__
) {
933 printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1
, cf2
);
935 Boolean b2
= __CFNumberEqual_old(number1
->__old__
, number2
->__old__
);
937 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2
, b
); FAIL();
944 static CFHashCode
__CFNumberHash(CFTypeRef cf
) {
946 CFNumberRef number
= (CFNumberRef
)cf
;
947 switch (__CFNumberGetType(number
)) {
948 case kCFNumberSInt8Type
:
949 case kCFNumberSInt16Type
:
950 case kCFNumberSInt32Type
: {
952 __CFNumberGetValue(number
, kCFNumberSInt32Type
, &i
);
958 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
959 h
= _CFHashDouble((double)d
);
964 CFNumberRef number1
= (CFNumberRef
)cf
;
965 if (! number1
->__old__
) {
966 printf("*** Test skipped in __CFNumberHash for number %p\n", cf
);
968 CFHashCode h2
= __CFNumberHash_old(number1
->__old__
);
970 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2
, h
); FAIL();
977 static CFTypeID __kCFNumberTypeID
= _kCFRuntimeNotATypeID
;
979 static const CFRuntimeClass __CFNumberClass
= {
987 __CFNumberCopyFormattingDescription
,
988 __CFNumberCopyDescription
991 __private_extern__
void __CFNumberInitialize(void) {
992 __kCFNumberTypeID
= _CFRuntimeRegisterClass(&__CFNumberClass
);
994 _CFRuntimeSetInstanceTypeID(&__kCFNumberNaN
, __kCFNumberTypeID
);
995 __kCFNumberNaN
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
996 __CFBitfieldSetValue(__kCFNumberNaN
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
997 __kCFNumberNaN
._pad
= BITSFORDOUBLENAN
;
999 _CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity
, __kCFNumberTypeID
);
1000 __kCFNumberNegativeInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
1001 __CFBitfieldSetValue(__kCFNumberNegativeInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1002 __kCFNumberNegativeInfinity
._pad
= BITSFORDOUBLENEGINF
;
1004 _CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity
, __kCFNumberTypeID
);
1005 __kCFNumberPositiveInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
1006 __CFBitfieldSetValue(__kCFNumberPositiveInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1007 __kCFNumberPositiveInfinity
._pad
= BITSFORDOUBLEPOSINF
;
1010 CFTypeID
CFNumberGetTypeID(void) {
1011 return __kCFNumberTypeID
;
1014 #define MinCachedInt (-1)
1015 #define MaxCachedInt (12)
1016 #define NotToBeCached (MinCachedInt - 1)
1017 static CFNumberRef __CFNumberCache
[MaxCachedInt
- MinCachedInt
+ 1] = {NULL
}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
1019 CFNumberRef
CFNumberCreate(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1020 __CFAssertIsValidNumberType(type
);
1021 //printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
1023 // Look for cases where we can return a cached instance.
1024 // We only use cached objects if the allocator is the system
1025 // default allocator, except for the special floating point
1026 // constant objects, where we return the cached object
1027 // regardless of allocator, since that is what has always
1028 // been done (and now must for compatibility).
1029 if (!allocator
) allocator
= __CFGetDefaultAllocator();
1030 int64_t valToBeCached
= NotToBeCached
;
1032 if (__CFNumberTypeTable
[type
].floatBit
) {
1033 CFNumberRef cached
= NULL
;
1034 if (0 == __CFNumberTypeTable
[type
].storageBit
) {
1035 Float32 f
= *(Float32
*)valuePtr
;
1036 if (isnan(f
)) cached
= kCFNumberNaN
;
1037 if (isinf(f
)) cached
= (f
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1039 Float64 d
= *(Float64
*)valuePtr
;
1040 if (isnan(d
)) cached
= kCFNumberNaN
;
1041 if (isinf(d
)) cached
= (d
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1043 if (cached
) return (CFNumberRef
)CFRetain(cached
);
1044 } else if (kCFAllocatorSystemDefault
== allocator
) {
1045 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1046 case kCFNumberSInt8Type
: {int8_t val
= *(int8_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1047 case kCFNumberSInt16Type
: {int16_t val
= *(int16_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1048 case kCFNumberSInt32Type
: {int32_t val
= *(int32_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1049 case kCFNumberSInt64Type
: {int64_t val
= *(int64_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1051 if (NotToBeCached
!= valToBeCached
) {
1052 CFNumberRef cached
= __CFNumberCache
[valToBeCached
- MinCachedInt
]; // Atomic to access the value in the cache
1053 if (NULL
!= cached
) return (CFNumberRef
)CFRetain(cached
);
1057 CFIndex size
= 8 + ((!__CFNumberTypeTable
[type
].floatBit
&& __CFNumberTypeTable
[type
].storageBit
) ? 8 : 0);
1059 size
+= 2 * sizeof(void *);
1061 CFNumberRef result
= (CFNumberRef
)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, size
, NULL
);
1062 if (NULL
== result
) {
1065 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)__CFNumberTypeTable
[type
].canonicalType
);
1068 ((struct __CFNumber
*)result
)->__old__
= CFNumberCreate_old(allocator
, type
, valuePtr
);
1069 CFLog(kCFLogLevelWarning
, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result
->__old__
));
1073 // for a value to be cached, we already have the value handy
1074 if (NotToBeCached
!= valToBeCached
) {
1075 memmove((void *)&result
->_pad
, &valToBeCached
, 8);
1076 // 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.
1077 // 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.
1078 // Barrier assures that the number that is placed in the cache is properly formed.
1079 CFNumberType origType
= __CFNumberGetType(result
);
1080 // Force all cached numbers to have the same type, so that the type does not
1081 // depend on the order and original type in/with which the numbers are created.
1082 // Forcing the type AFTER it was cached would cause a race condition with other
1083 // threads pulling the number object out of the cache and using it.
1084 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)kCFNumberSInt32Type
);
1085 if (OSAtomicCompareAndSwapPtrBarrier(NULL
, (void *)result
, (void *volatile *)&__CFNumberCache
[valToBeCached
- MinCachedInt
])) {
1088 // Did not cache the number object, put original type back.
1089 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)origType
);
1095 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1096 case kCFNumberSInt8Type
: value
= (uint64_t)(int64_t)*(int8_t *)valuePtr
; goto smallVal
;
1097 case kCFNumberSInt16Type
: value
= (uint64_t)(int64_t)*(int16_t *)valuePtr
; goto smallVal
;
1098 case kCFNumberSInt32Type
: value
= (uint64_t)(int64_t)*(int32_t *)valuePtr
; goto smallVal
;
1099 smallVal
: memmove((void *)&result
->_pad
, &value
, 8); break;
1100 case kCFNumberSInt64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1101 case kCFNumberSInt128Type
: memmove((void *)&result
->_pad
, valuePtr
, 16); break;
1102 case kCFNumberFloat32Type
: memmove((void *)&result
->_pad
, valuePtr
, 4); break;
1103 case kCFNumberFloat64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1105 //printf(" => %p\n", result);
1109 CFNumberType
CFNumberGetType(CFNumberRef number
) {
1110 //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
1111 CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID
, CFNumberType
, number
, "_cfNumberType");
1112 __CFAssertIsNumber(number
);
1113 CFNumberType type
= __CFNumberGetType(number
);
1114 if (kCFNumberSInt128Type
== type
) type
= kCFNumberSInt64Type
; // must hide this type, since it is not public
1115 //printf(" => %d\n", type);
1117 if (! number
->__old__
) {
1118 printf("*** Test skipped in CFNumberGetType for number %p\n", number
);
1120 CFNumberType t2
= CFNumberGetType_old(number
->__old__
);
1122 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2
, type
); FAIL();
1129 CF_EXPORT CFNumberType
_CFNumberGetType2(CFNumberRef number
) {
1130 __CFAssertIsNumber(number
);
1131 return __CFNumberGetType(number
);
1134 CFIndex
CFNumberGetByteSize(CFNumberRef number
) {
1135 //printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
1136 __CFAssertIsNumber(number
);
1137 CFIndex r
= 1 << __CFNumberTypeTable
[CFNumberGetType(number
)].lgByteSize
;
1138 //printf(" => %d\n", r);
1140 if (! number
->__old__
) {
1141 printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number
);
1143 CFIndex r2
= CFNumberGetByteSize_old(number
->__old__
);
1145 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2
, r
); FAIL();
1152 Boolean
CFNumberIsFloatType(CFNumberRef number
) {
1153 //printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1154 __CFAssertIsNumber(number
);
1155 Boolean r
= __CFNumberTypeTable
[CFNumberGetType(number
)].floatBit
;
1156 //printf(" => %d\n", r);
1158 if (! number
->__old__
) {
1159 printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number
);
1161 Boolean r2
= CFNumberIsFloatType_old(number
->__old__
);
1163 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2
, r
); FAIL();
1170 Boolean
CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
1171 //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1172 CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID
, Boolean
, number
, "_getValue:forType:", valuePtr
, __CFNumberTypeTable
[type
].canonicalType
);
1173 __CFAssertIsNumber(number
);
1174 __CFAssertIsValidNumberType(type
);
1175 uint8_t localMemory
[128];
1176 Boolean r
= __CFNumberGetValueCompat(number
, type
, valuePtr
? valuePtr
: localMemory
);
1177 //printf(" => %d\n", r);
1179 if (! number
->__old__
) {
1180 printf("*** Test skipped in CFNumberGetValue for number %p\n", number
);
1182 uint8_t localMemory2
[128];
1183 Boolean r2
= CFNumberGetValue_old(number
->__old__
, type
, localMemory2
);
1185 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2
, r
); FAIL();
1187 if (0 != memcmp(localMemory2
, valuePtr
, CFNumberGetByteSize(number
))) {
1188 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME")); FAIL();
1195 static CFComparisonResult
CFNumberCompare_new(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1196 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number1
, "compare:", number2
);
1197 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number2
, "_reverseCompare:", number1
);
1198 __CFAssertIsNumber(number1
);
1199 __CFAssertIsNumber(number2
);
1201 CFNumberType type1
= __CFNumberGetType(number1
);
1202 CFNumberType type2
= __CFNumberGetType(number2
);
1203 // Both numbers are integers
1204 if (!__CFNumberTypeTable
[type1
].floatBit
&& !__CFNumberTypeTable
[type2
].floatBit
) {
1205 CFSInt128Struct i1
, i2
;
1206 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1207 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1208 return cmp128(&i1
, &i2
);
1210 // Both numbers are floats
1211 if (__CFNumberTypeTable
[type1
].floatBit
&& __CFNumberTypeTable
[type2
].floatBit
) {
1213 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1214 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1215 double s1
= copysign(1.0, d1
);
1216 double s2
= copysign(1.0, d2
);
1217 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1218 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1219 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1220 // at this point, we know we don't have any NaNs
1221 if (s1
< s2
) return kCFCompareLessThan
;
1222 if (s2
< s1
) return kCFCompareGreaterThan
;
1223 // at this point, we know the signs are the same; do not combine these tests
1224 if (d1
< d2
) return kCFCompareLessThan
;
1225 if (d2
< d1
) return kCFCompareGreaterThan
;
1226 return kCFCompareEqualTo
;
1228 // One float, one integer; swap if necessary so number1 is the float
1229 Boolean swapResult
= false;
1230 if (__CFNumberTypeTable
[type2
].floatBit
) {
1231 CFNumberRef tmp
= number1
;
1236 // At large integer values, the precision of double is quite low
1237 // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1238 // If we just used double compare, that would make the 2^73 largest 128-bit
1239 // integers look equal, so we have to use integer comparison when possible.
1241 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1242 // if the double value is really big, cannot be equal to integer
1243 // nan d1 will not compare true here
1244 if (d1
< FLOAT_NEGATIVE_2_TO_THE_127
) {
1245 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1247 if (FLOAT_POSITIVE_2_TO_THE_127
<= d1
) {
1248 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1250 CFSInt128Struct i1
, i2
;
1251 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1252 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1253 CFComparisonResult res
= cmp128(&i1
, &i2
);
1254 if (kCFCompareEqualTo
!= res
) {
1255 return !swapResult
? res
: -res
;
1257 // now things are equal, but perhaps due to rounding or nan
1259 if (isNeg128(&i2
)) {
1260 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1262 // nan compares less than positive 0 too
1263 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1265 // at this point, we know we don't have NaN
1266 double s1
= copysign(1.0, d1
);
1267 double s2
= isNeg128(&i2
) ? -1.0 : 1.0;
1268 if (s1
< s2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1269 if (s2
< s1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1270 // at this point, we know the signs are the same; do not combine these tests
1271 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1272 if (d1
< d2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1273 if (d2
< d1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1274 return kCFCompareEqualTo
;
1277 CFComparisonResult
CFNumberCompare(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1278 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1279 CFComparisonResult r
= CFNumberCompare_new(number1
, number2
, context
);
1280 //printf(" => %d\n", r);
1282 if (! number1
->__old__
|| !number2
->__old__
) {
1283 printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1
, number2
);
1285 CFComparisonResult r2
= CFNumberCompare_old(number1
->__old__
, number2
->__old__
, context
);
1287 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2
, r
); FAIL();
1296 static const unsigned char __CFNumberCanonicalType
[kCFNumberMaxType
+ 1] = {
1297 0, kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1298 kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1299 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1302 static const unsigned char __CFNumberStorageType
[kCFNumberMaxType
+ 1] = {
1303 0, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1304 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1305 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1310 // Returns the type that is used to store the specified type
1311 static CFNumberType
__CFNumberGetStorageTypeForType_old(CFNumberType type
) {
1312 return __CFNumberStorageType
[type
];
1315 // Returns the canonical type used to represent the specified type
1316 static CFNumberType
__CFNumberGetCanonicalTypeForType_old(CFNumberType type
) {
1317 return __CFNumberCanonicalType
[type
];
1320 // Extracts and returns the type out of the CFNumber
1321 static CFNumberType
__CFNumberGetType_old(struct __CFNumber_old
* num
) {
1322 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
1325 // Returns true if the argument type is float or double
1326 static Boolean
__CFNumberTypeIsFloat_old(CFNumberType type
) {
1327 return (type
== kCFNumberFloat64Type
) || (type
== kCFNumberFloat32Type
) || (type
== kCFNumberDoubleType
) || (type
== kCFNumberFloatType
);
1330 // Returns the number of bytes necessary to store the specified type
1331 // Needs to handle all canonical types
1332 static CFIndex
__CFNumberSizeOfType_old(CFNumberType type
) {
1334 case kCFNumberSInt8Type
: return sizeof(int8_t);
1335 case kCFNumberSInt16Type
: return sizeof(int16_t);
1336 case kCFNumberSInt32Type
: return sizeof(SInt32
);
1337 case kCFNumberSInt64Type
: return sizeof(int64_t);
1338 case kCFNumberFloat32Type
: return sizeof(Float32
);
1339 case kCFNumberFloat64Type
: return sizeof(Float64
);
1340 default: printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
1344 // Copies an external value of a given type into the appropriate slot in the union (does no type conversion)
1345 // Needs to handle all canonical types
1346 #define SET_VALUE(valueUnion, type, valuePtr) \
1348 case kCFNumberSInt8Type: (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
1349 case kCFNumberSInt16Type: (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break; \
1350 case kCFNumberSInt32Type: (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
1351 case kCFNumberSInt64Type: (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break; \
1352 case kCFNumberFloat32Type: (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break; \
1353 case kCFNumberFloat64Type: (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break; \
1354 default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
1357 // Casts the specified value into the specified type and copies it into the provided memory
1358 // Needs to handle all canonical types
1359 #define GET_VALUE(value, type, resultPtr) \
1361 case kCFNumberSInt8Type: *(int8_t *)(resultPtr) = (int8_t)value; break; \
1362 case kCFNumberSInt16Type: *(int16_t *)(resultPtr) = (int16_t)value; break; \
1363 case kCFNumberSInt32Type: *(SInt32 *)(resultPtr) = (SInt32)value; break; \
1364 case kCFNumberSInt64Type: *(int64_t *)(resultPtr) = (int64_t)value; break; \
1365 case kCFNumberFloat32Type: *(Float32 *)(resultPtr) = (Float32)value; break; \
1366 case kCFNumberFloat64Type: *(Float64 *)(resultPtr) = (Float64)value; break; \
1367 default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
1370 // Extracts the stored type out of the union and copies it in the desired type into the provided memory
1371 // Needs to handle all storage types
1372 static void __CFNumberGetValue_old(const __CFNumberValue_old
*value
, CFNumberType numberType
, CFNumberType typeToGet
, void *valuePtr
) {
1373 switch (numberType
) {
1374 case kCFNumberSInt32Type
: GET_VALUE(value
->valSInt32
, typeToGet
, valuePtr
); break;
1375 case kCFNumberSInt64Type
: GET_VALUE(value
->valSInt64
, typeToGet
, valuePtr
); break;
1376 case kCFNumberFloat32Type
: GET_VALUE(value
->valFloat32
, typeToGet
, valuePtr
); break;
1377 case kCFNumberFloat64Type
: GET_VALUE(value
->valFloat64
, typeToGet
, valuePtr
); break;
1378 default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
1382 // Sees if two value union structs have the same value (will do type conversion)
1383 static Boolean
__CFNumberEqualValue_old(const __CFNumberValue_old
*value1
, CFNumberType type1
, const __CFNumberValue_old
*value2
, CFNumberType type2
) {
1384 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1386 __CFNumberGetValue_old(value1
, type1
, kCFNumberFloat64Type
, &d1
);
1387 __CFNumberGetValue_old(value2
, type2
, kCFNumberFloat64Type
, &d2
);
1388 if (isnan(d1
) && isnan(d2
)) return true; // Not mathematically sound, but required
1392 __CFNumberGetValue_old(value1
, type1
, kCFNumberSInt64Type
, &i1
);
1393 __CFNumberGetValue_old(value2
, type2
, kCFNumberSInt64Type
, &i2
);
1398 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
) {
1399 struct __CFNumber_old
* number1
= (struct __CFNumber_old
*)cf1
;
1400 struct __CFNumber_old
* number2
= (struct __CFNumber_old
*)cf2
;
1401 return __CFNumberEqualValue_old(&(number1
->value
), __CFNumberGetType_old(number1
), &(number2
->value
), __CFNumberGetType_old(number2
));
1404 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
) {
1405 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1406 switch (__CFNumberGetType_old((struct __CFNumber_old
*)cf
)) {
1407 case kCFNumberSInt32Type
: return _CFHashInt(number
->value
.valSInt32
);
1408 case kCFNumberSInt64Type
: return _CFHashDouble((double)(number
->value
.valSInt64
));
1409 case kCFNumberFloat32Type
: return _CFHashDouble((double)(number
->value
.valFloat32
));
1410 case kCFNumberFloat64Type
: return _CFHashDouble((double)(number
->value
.valFloat64
));
1411 default: printf("*** WARNING default case in __CFNumberHash_old\n");
1416 #define BUFFER_SIZE 100
1417 #define emitChar(ch) \
1418 {if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
1420 static void __CFNumberEmitInt64_old(CFMutableStringRef mstr
, int64_t value
, int32_t width
, UniChar pad
, bool explicitPlus
) {
1421 UniChar stackBuf
[BUFFER_SIZE
], *buf
= stackBuf
;
1422 uint64_t uvalue
, factor
, tmp
;
1426 neg
= (value
< 0) ? true : false;
1427 uvalue
= (neg
) ? -value
: value
;
1428 if (neg
|| explicitPlus
) width
--;
1437 for (w
= 0; w
< width
; w
++) emitChar(pad
);
1440 } else if (explicitPlus
) {
1443 while (0 < factor
) {
1444 UniChar ch
= '0' + (UniChar
)(uvalue
/ factor
);
1449 if (buf
> stackBuf
) CFStringAppendCharacters(mstr
, stackBuf
, buf
- stackBuf
);
1452 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
) {
1453 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1454 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1455 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
1456 switch (__CFNumberGetType_old(number
)) {
1457 case kCFNumberSInt32Type
:
1458 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt32
, 0, ' ', true);
1459 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt32Type}"));
1461 case kCFNumberSInt64Type
:
1462 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt64
, 0, ' ', true);
1463 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt64Type}"));
1465 case kCFNumberFloat32Type
:
1466 // debugging formatting is intentionally more verbose and explicit about the value of the number
1467 if (isnan(number
->value
.valFloat32
)) {
1468 CFStringAppend(mstr
, CFSTR("nan"));
1469 } else if (isinf(number
->value
.valFloat32
)) {
1470 CFStringAppend(mstr
, (0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1471 } else if (0.0f
== number
->value
.valFloat32
) {
1472 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat32
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1474 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.10f"), number
->value
.valFloat32
);
1476 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat32Type}"));
1478 case kCFNumberFloat64Type
:
1479 // debugging formatting is intentionally more verbose and explicit about the value of the number
1480 if (isnan(number
->value
.valFloat64
)) {
1481 CFStringAppend(mstr
, CFSTR("nan"));
1482 } else if (isinf(number
->value
.valFloat64
)) {
1483 CFStringAppend(mstr
, (0.0 < number
->value
.valFloat64
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1484 } else if (0.0 == number
->value
.valFloat64
) {
1485 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat64
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1487 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.20f"), number
->value
.valFloat64
);
1489 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat64Type}"));
1498 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
1500 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
) {
1502 CFNumberGetValue_old((struct __CFNumber_old
*)cf
, kCFNumberFloat64Type
, &d
);
1504 return (CFStringRef
)CFRetain(CFSTR("nan"));
1507 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1510 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1512 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
1513 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
1516 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
1517 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1518 CFMutableStringRef mstr
;
1520 switch (__CFNumberGetType_old(number
)) {
1521 case kCFNumberSInt32Type
:
1522 case kCFNumberSInt64Type
:
1523 value
= (__CFNumberGetType_old(number
) == kCFNumberSInt32Type
) ? number
->value
.valSInt32
: number
->value
.valSInt64
;
1524 mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1525 __CFNumberEmitInt64_old(mstr
, value
, 0, ' ', false);
1527 case kCFNumberFloat32Type
:
1528 if (isnan(number
->value
.valFloat32
)) {
1529 return (CFStringRef
)CFRetain(CFSTR("nan"));
1531 if (isinf(number
->value
.valFloat32
)) {
1532 return (CFStringRef
)CFRetain((0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1534 if (0.0f
== number
->value
.valFloat32
) {
1535 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1537 // if %g is used here, need to use FLT_DIG + 2 on Mac OS X, but %f needs +1
1538 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), FLT_DIG
+ 2, number
->value
.valFloat32
);
1539 case kCFNumberFloat64Type
:
1540 return __CFNumberCopyFormattingDescriptionAsFloat64_old(number
);
1549 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1550 struct __CFNumber_old
* num
;
1551 CFNumberType equivType
, storageType
;
1554 CFSInt128Struct
*s
= valuePtr
;
1555 s
->high
= (int64_t)s
->low
;
1556 type
= kCFNumberSInt64Type
;
1560 equivType
= __CFNumberGetCanonicalTypeForType_old(type
);
1562 storageType
= __CFNumberGetStorageTypeForType_old(type
);
1564 num
= (struct __CFNumber_old
*)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, __CFNumberSizeOfType_old(storageType
), NULL
);
1568 SET_VALUE((__CFNumberValue_old
*)&(num
->value
), equivType
, valuePtr
);
1569 __CFBitfieldSetValue(((struct __CFNumber_old
*)num
)->_base
._cfinfo
[CF_INFO_BITS
], 6, 0, (uint8_t)storageType
);
1571 if (__CFNumberGetType_old(num
) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num
, storageType
);
1575 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
) {
1577 return __CFNumberGetType_old(number
);
1580 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
) {
1581 return __CFNumberSizeOfType_old(CFNumberGetType_old(number
));
1584 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
) {
1585 return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number
));
1588 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
) {
1589 uint8_t localMemory
[sizeof(__CFNumberValue_old
)];
1590 __CFNumberValue_old localValue
;
1591 CFNumberType numType
;
1592 CFNumberType storageTypeForType
;
1594 if (type
== 17) type
= kCFNumberSInt64Type
;
1596 storageTypeForType
= __CFNumberGetStorageTypeForType_old(type
);
1597 type
= __CFNumberGetCanonicalTypeForType_old(type
);
1598 if (!valuePtr
) valuePtr
= &localMemory
;
1600 numType
= __CFNumberGetType_old(number
);
1601 __CFNumberGetValue_old((__CFNumberValue_old
*)&(number
->value
), numType
, type
, valuePtr
);
1603 // If the types match, then we're fine!
1604 if (numType
== storageTypeForType
) return true;
1606 // Test to see if the returned value is intact...
1607 SET_VALUE(&localValue
, type
, valuePtr
);
1608 return __CFNumberEqualValue_old(&localValue
, storageTypeForType
, &(number
->value
), numType
);
1611 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
) {
1612 CFNumberType type1
, type2
;
1615 type1
= __CFNumberGetType_old(number1
);
1616 type2
= __CFNumberGetType_old(number2
);
1618 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1621 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberFloat64Type
, &d1
);
1622 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberFloat64Type
, &d2
);
1623 s1
= copysign(1.0, d1
);
1624 s2
= copysign(1.0, d2
);
1625 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1626 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1627 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1628 // at this point, we know we don't have any NaNs
1629 if (s1
< s2
) return kCFCompareLessThan
;
1630 if (s2
< s1
) return kCFCompareGreaterThan
;
1631 // at this point, we know the signs are the same; do not combine these tests
1632 if (d1
< d2
) return kCFCompareLessThan
;
1633 if (d2
< d1
) return kCFCompareGreaterThan
;
1634 return kCFCompareEqualTo
;
1637 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberSInt64Type
, &i1
);
1638 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberSInt64Type
, &i2
);
1639 return (i1
> i2
) ? kCFCompareGreaterThan
: ((i1
< i2
) ? kCFCompareLessThan
: kCFCompareEqualTo
);
1646 #undef __CFAssertIsBoolean
1647 #undef __CFAssertIsNumber
1648 #undef __CFAssertIsValidNumberType
1649 #undef BITSFORDOUBLENAN
1650 #undef BITSFORDOUBLEPOSINF
1651 #undef BITSFORDOUBLENEGINF
1654 #undef NotToBeCached