2 * Copyright (c) 2012 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-2011, 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)
41 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
47 static struct __CFBoolean __kCFBooleanTrue
= {
50 const CFBooleanRef kCFBooleanTrue
= &__kCFBooleanTrue
;
52 static struct __CFBoolean __kCFBooleanFalse
= {
55 const CFBooleanRef kCFBooleanFalse
= &__kCFBooleanFalse
;
57 static CFStringRef
__CFBooleanCopyDescription(CFTypeRef cf
) {
58 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
59 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf
, CFGetAllocator(cf
), (boolean
== kCFBooleanTrue
) ? "true" : "false");
62 __private_extern__ CFStringRef
__CFBooleanCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
63 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
64 return (CFStringRef
)CFRetain((boolean
== kCFBooleanTrue
) ? CFSTR("true") : CFSTR("false"));
67 static CFHashCode
__CFBooleanHash(CFTypeRef cf
) {
68 CFBooleanRef boolean
= (CFBooleanRef
)cf
;
69 return (boolean
== kCFBooleanTrue
) ? _CFHashInt(1) : _CFHashInt(0);
72 static void __CFBooleanDeallocate(CFTypeRef cf
) {
73 CFAssert(false, __kCFLogAssertion
, "Deallocated CFBoolean!");
76 static CFTypeID __kCFBooleanTypeID
= _kCFRuntimeNotATypeID
;
78 static const CFRuntimeClass __CFBooleanClass
= {
83 __CFBooleanDeallocate
,
86 __CFBooleanCopyFormattingDescription
,
87 __CFBooleanCopyDescription
90 __private_extern__
void __CFBooleanInitialize(void) {
91 __kCFBooleanTypeID
= _CFRuntimeRegisterClass(&__CFBooleanClass
);
92 _CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue
, __kCFBooleanTypeID
);
93 __kCFBooleanTrue
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
94 _CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse
, __kCFBooleanTypeID
);
95 __kCFBooleanFalse
._base
._cfisa
= __CFISAForTypeID(__kCFBooleanTypeID
);
98 CFTypeID
CFBooleanGetTypeID(void) {
99 return __kCFBooleanTypeID
;
102 Boolean
CFBooleanGetValue(CFBooleanRef boolean
) {
103 CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID
, Boolean
, boolean
, "boolValue");
104 return (boolean
== kCFBooleanTrue
) ? true : false;
110 #define OLD_CRAP_TOO 0
119 } __CFNumberValue_old
;
121 struct __CFNumber_old
{ /* Only as many bytes as necessary are allocated */
123 __CFNumberValue_old value
;
126 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
);
127 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
);
128 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
);
129 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
);
130 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
);
131 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
);
132 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
);
133 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
);
134 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
);
135 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
);
136 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
);
141 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
142 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
144 /* The IEEE bit patterns... Also have:
145 0x7f800000 float +Inf
147 0xff800000 float -Inf
149 #define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
150 #define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
151 #define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
153 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
154 #define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
155 #define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
156 #define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
157 #elif DEPLOYMENT_TARGET_WINDOWS
158 #define FLOAT_POSITIVE_2_TO_THE_64 18446744073709551616.0
159 #define FLOAT_NEGATIVE_2_TO_THE_127 -170141183460469231731687303715884105728.0
160 #define FLOAT_POSITIVE_2_TO_THE_127 170141183460469231731687303715884105728.0
162 #error Unknown or unspecified DEPLOYMENT_TARGET
165 typedef struct { // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
171 kCFNumberSInt128Type
= 17
174 static uint8_t isNeg128(const CFSInt128Struct
*in
) {
178 static CFComparisonResult
cmp128(const CFSInt128Struct
*in1
, const CFSInt128Struct
*in2
) {
179 if (in1
->high
< in2
->high
) return kCFCompareLessThan
;
180 if (in1
->high
> in2
->high
) return kCFCompareGreaterThan
;
181 if (in1
->low
< in2
->low
) return kCFCompareLessThan
;
182 if (in1
->low
> in2
->low
) return kCFCompareGreaterThan
;
183 return kCFCompareEqualTo
;
186 // allows out to be the same as in1 or in2
187 static void add128(CFSInt128Struct
*out
, CFSInt128Struct
*in1
, CFSInt128Struct
*in2
) {
189 tmp
.low
= in1
->low
+ in2
->low
;
190 tmp
.high
= in1
->high
+ in2
->high
;
191 if (UINT64_MAX
- in1
->low
< in2
->low
) {
197 // allows out to be the same as in
198 static void neg128(CFSInt128Struct
*out
, CFSInt128Struct
*in
) {
199 uint64_t tmplow
= ~in
->low
;
200 out
->low
= tmplow
+ 1;
201 out
->high
= ~in
->high
;
202 if (UINT64_MAX
== tmplow
) {
207 static const CFSInt128Struct powersOf10
[] = {
208 { 0x4B3B4CA85A86C47ALL
, 0x098A224000000000ULL
},
209 { 0x0785EE10D5DA46D9LL
, 0x00F436A000000000ULL
},
210 { 0x00C097CE7BC90715LL
, 0xB34B9F1000000000ULL
},
211 { 0x0013426172C74D82LL
, 0x2B878FE800000000ULL
},
212 { 0x0001ED09BEAD87C0LL
, 0x378D8E6400000000ULL
},
213 { 0x0000314DC6448D93LL
, 0x38C15B0A00000000ULL
},
214 { 0x000004EE2D6D415BLL
, 0x85ACEF8100000000ULL
},
215 { 0x0000007E37BE2022LL
, 0xC0914B2680000000ULL
},
216 { 0x0000000C9F2C9CD0LL
, 0x4674EDEA40000000ULL
},
217 { 0x00000001431E0FAELL
, 0x6D7217CAA0000000ULL
},
218 { 0x00000000204FCE5ELL
, 0x3E25026110000000ULL
},
219 { 0x00000000033B2E3CLL
, 0x9FD0803CE8000000ULL
},
220 { 0x000000000052B7D2LL
, 0xDCC80CD2E4000000ULL
},
221 { 0x0000000000084595LL
, 0x161401484A000000ULL
},
222 { 0x000000000000D3C2LL
, 0x1BCECCEDA1000000ULL
},
223 { 0x000000000000152DLL
, 0x02C7E14AF6800000ULL
},
224 { 0x000000000000021ELL
, 0x19E0C9BAB2400000ULL
},
225 { 0x0000000000000036LL
, 0x35C9ADC5DEA00000ULL
},
226 { 0x0000000000000005LL
, 0x6BC75E2D63100000ULL
},
227 { 0x0000000000000000LL
, 0x8AC7230489E80000ULL
},
228 { 0x0000000000000000LL
, 0x0DE0B6B3A7640000ULL
},
229 { 0x0000000000000000LL
, 0x016345785D8A0000ULL
},
230 { 0x0000000000000000LL
, 0x002386F26FC10000ULL
},
231 { 0x0000000000000000LL
, 0x00038D7EA4C68000ULL
},
232 { 0x0000000000000000LL
, 0x00005AF3107A4000ULL
},
233 { 0x0000000000000000LL
, 0x000009184E72A000ULL
},
234 { 0x0000000000000000LL
, 0x000000E8D4A51000ULL
},
235 { 0x0000000000000000LL
, 0x000000174876E800ULL
},
236 { 0x0000000000000000LL
, 0x00000002540BE400ULL
},
237 { 0x0000000000000000LL
, 0x000000003B9ACA00ULL
},
238 { 0x0000000000000000LL
, 0x0000000005F5E100ULL
},
239 { 0x0000000000000000LL
, 0x0000000000989680ULL
},
240 { 0x0000000000000000LL
, 0x00000000000F4240ULL
},
241 { 0x0000000000000000LL
, 0x00000000000186A0ULL
},
242 { 0x0000000000000000LL
, 0x0000000000002710ULL
},
243 { 0x0000000000000000LL
, 0x00000000000003E8ULL
},
244 { 0x0000000000000000LL
, 0x0000000000000064ULL
},
245 { 0x0000000000000000LL
, 0x000000000000000AULL
},
246 { 0x0000000000000000LL
, 0x0000000000000001ULL
},
249 static const CFSInt128Struct neg_powersOf10
[] = {
250 { 0xB4C4B357A5793B85LL
, 0xF675DDC000000000ULL
},
251 { 0xF87A11EF2A25B926LL
, 0xFF0BC96000000000ULL
},
252 { 0xFF3F68318436F8EALL
, 0x4CB460F000000000ULL
},
253 { 0xFFECBD9E8D38B27DLL
, 0xD478701800000000ULL
},
254 { 0xFFFE12F64152783FLL
, 0xC872719C00000000ULL
},
255 { 0xFFFFCEB239BB726CLL
, 0xC73EA4F600000000ULL
},
256 { 0xFFFFFB11D292BEA4LL
, 0x7A53107F00000000ULL
},
257 { 0xFFFFFF81C841DFDDLL
, 0x3F6EB4D980000000ULL
},
258 { 0xFFFFFFF360D3632FLL
, 0xB98B1215C0000000ULL
},
259 { 0xFFFFFFFEBCE1F051LL
, 0x928DE83560000000ULL
},
260 { 0xFFFFFFFFDFB031A1LL
, 0xC1DAFD9EF0000000ULL
},
261 { 0xFFFFFFFFFCC4D1C3LL
, 0x602F7FC318000000ULL
},
262 { 0xFFFFFFFFFFAD482DLL
, 0x2337F32D1C000000ULL
},
263 { 0xFFFFFFFFFFF7BA6ALL
, 0xE9EBFEB7B6000000ULL
},
264 { 0xFFFFFFFFFFFF2C3DLL
, 0xE43133125F000000ULL
},
265 { 0xFFFFFFFFFFFFEAD2LL
, 0xFD381EB509800000ULL
},
266 { 0xFFFFFFFFFFFFFDE1LL
, 0xE61F36454DC00000ULL
},
267 { 0xFFFFFFFFFFFFFFC9LL
, 0xCA36523A21600000ULL
},
268 { 0xFFFFFFFFFFFFFFFALL
, 0x9438A1D29CF00000ULL
},
269 { 0xFFFFFFFFFFFFFFFFLL
, 0x7538DCFB76180000ULL
},
270 { 0xFFFFFFFFFFFFFFFFLL
, 0xF21F494C589C0000ULL
},
271 { 0xFFFFFFFFFFFFFFFFLL
, 0xFE9CBA87A2760000ULL
},
272 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFDC790D903F0000ULL
},
273 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFC72815B398000ULL
},
274 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFA50CEF85C000ULL
},
275 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFF6E7B18D6000ULL
},
276 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFF172B5AF000ULL
},
277 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFE8B7891800ULL
},
278 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFDABF41C00ULL
},
279 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFC4653600ULL
},
280 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFA0A1F00ULL
},
281 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFF676980ULL
},
282 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFF0BDC0ULL
},
283 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFE7960ULL
},
284 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFD8F0ULL
},
285 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFC18ULL
},
286 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFF9CULL
},
287 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFF6ULL
},
288 { 0xFFFFFFFFFFFFFFFFLL
, 0xFFFFFFFFFFFFFFFFULL
},
291 static void emit128(char *buffer
, const CFSInt128Struct
*in
, Boolean forcePlus
) {
292 CFSInt128Struct tmp
= *in
;
293 if (isNeg128(&tmp
)) {
296 } else if (forcePlus
) {
299 Boolean doneOne
= false;
301 for (idx
= 0; idx
< sizeof(powersOf10
) / sizeof(powersOf10
[0]); idx
++) {
303 while (cmp128(&powersOf10
[idx
], &tmp
) <= 0) {
304 add128(&tmp
, &tmp
, (CFSInt128Struct
*)&neg_powersOf10
[idx
]);
307 if (0 != count
|| doneOne
) {
308 *buffer
++ = '0' + count
;
318 static void cvtSInt128ToFloat64(Float64
*out
, const CFSInt128Struct
*in
) {
319 // switching to a positive number results in better accuracy
320 // for negative numbers close to zero, because the multiply
321 // of -1 by 2^64 (scaling the Float64 high) is avoided
322 Boolean wasNeg
= false;
323 CFSInt128Struct tmp
= *in
;
324 if (isNeg128(&tmp
)) {
328 Float64 d
= (Float64
)tmp
.high
* FLOAT_POSITIVE_2_TO_THE_64
+ (Float64
)tmp
.low
;
333 static void cvtFloat64ToSInt128(CFSInt128Struct
*out
, const Float64
*in
) {
336 if (d
< FLOAT_NEGATIVE_2_TO_THE_127
) {
337 i
.high
= 0x8000000000000000LL
;
338 i
.low
= 0x0000000000000000ULL
;
342 if (FLOAT_POSITIVE_2_TO_THE_127
<= d
) {
343 i
.high
= 0x7fffffffffffffffLL
;
344 i
.low
= 0xffffffffffffffffULL
;
348 Float64 t
= floor(d
/ FLOAT_POSITIVE_2_TO_THE_64
);
350 i
.low
= (uint64_t)(d
- t
* FLOAT_POSITIVE_2_TO_THE_64
);
357 struct __CFNumber_old
*__old__
;
360 uint64_t _pad
; // need this space here for the constant objects
361 /* 0 or 8 more bytes allocated here */
364 /* Seven bits in base:
366 Bits 4..0: CFNumber type
369 static struct __CFNumber __kCFNumberNaN
= {
370 INIT_CFRUNTIME_BASE(), 0ULL
372 const CFNumberRef kCFNumberNaN
= &__kCFNumberNaN
;
374 static struct __CFNumber __kCFNumberNegativeInfinity
= {
375 INIT_CFRUNTIME_BASE(), 0ULL
377 const CFNumberRef kCFNumberNegativeInfinity
= &__kCFNumberNegativeInfinity
;
379 static struct __CFNumber __kCFNumberPositiveInfinity
= {
380 INIT_CFRUNTIME_BASE(), 0ULL
382 const CFNumberRef kCFNumberPositiveInfinity
= &__kCFNumberPositiveInfinity
;
384 static const struct {
385 uint16_t canonicalType
:5; // canonical fixed-width type
386 uint16_t floatBit
:1; // is float
387 uint16_t storageBit
:1; // storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
388 uint16_t lgByteSize
:3; // base-2 log byte size of public type
390 } __CFNumberTypeTable
[] = {
391 /* 0 */ {0, 0, 0, 0},
393 /* kCFNumberSInt8Type */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
394 /* kCFNumberSInt16Type */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
395 /* kCFNumberSInt32Type */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
396 /* kCFNumberSInt64Type */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
397 /* kCFNumberFloat32Type */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
398 /* kCFNumberFloat64Type */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
400 /* kCFNumberCharType */ {kCFNumberSInt8Type
, 0, 0, 0, 0},
401 /* kCFNumberShortType */ {kCFNumberSInt16Type
, 0, 0, 1, 0},
402 /* kCFNumberIntType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
404 /* kCFNumberLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
406 /* kCFNumberLongType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
408 /* kCFNumberLongLongType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
409 /* kCFNumberFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
410 /* kCFNumberDoubleType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
413 /* kCFNumberCFIndexType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
414 /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type
, 0, 0, 3, 0},
415 /* kCFNumberCGFloatType */ {kCFNumberFloat64Type
, 1, 1, 3, 0},
417 /* kCFNumberCFIndexType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
418 /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type
, 0, 0, 2, 0},
419 /* kCFNumberCGFloatType */ {kCFNumberFloat32Type
, 1, 0, 2, 0},
422 /* kCFNumberSInt128Type */ {kCFNumberSInt128Type
, 0, 1, 4, 0},
425 #define CF_IS_TAGGED_INT(OBJ) (CF_TAGGED_OBJ_TYPE(OBJ) == kCFTaggedObjectID_Integer)
427 CF_INLINE CFNumberType
__CFNumberGetType(CFNumberRef num
) {
428 if (CF_IS_TAGGED_INT(num
)) {
429 uintptr_t type_bits
= ((uintptr_t)num
>> 6) & 0x3; // top 2 bits of low byte
430 const CFNumberType canonical_types
[4] = {kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
};
431 return canonical_types
[type_bits
];
433 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
436 #define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
437 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
438 DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
439 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
440 SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
443 #define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
444 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
445 DST_TYPE dv; Boolean noLoss = false; \
446 if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
448 } else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
451 dv = (DST_TYPE)sv.low; \
454 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
458 // returns false if the output value is not the same as the number's value, which
459 // can occur due to accuracy loss and the value not being within the target range
460 static Boolean
__CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
461 type
= __CFNumberTypeTable
[type
].canonicalType
;
462 CFNumberType ntype
= __CFNumberGetType(number
);
463 const void *data
= &(number
->_pad
);
464 intptr_t taggedInteger
;
465 if (CF_IS_TAGGED_INT(number
)) {
466 taggedInteger
= (intptr_t)number
;
467 taggedInteger
= taggedInteger
>> 8;
468 data
= &taggedInteger
;
471 case kCFNumberSInt8Type
:
472 if (__CFNumberTypeTable
[ntype
].floatBit
) {
473 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
474 CVT(Float32
, int8_t, INT8_MIN
, INT8_MAX
);
476 CVT(Float64
, int8_t, INT8_MIN
, INT8_MAX
);
479 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
480 CVT(int64_t, int8_t, INT8_MIN
, INT8_MAX
);
482 CVT128ToInt(CFSInt128Struct
, int8_t, INT8_MIN
, INT8_MAX
);
486 case kCFNumberSInt16Type
:
487 if (__CFNumberTypeTable
[ntype
].floatBit
) {
488 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
489 CVT(Float32
, int16_t, INT16_MIN
, INT16_MAX
);
491 CVT(Float64
, int16_t, INT16_MIN
, INT16_MAX
);
494 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
495 CVT(int64_t, int16_t, INT16_MIN
, INT16_MAX
);
497 CVT128ToInt(CFSInt128Struct
, int16_t, INT16_MIN
, INT16_MAX
);
501 case kCFNumberSInt32Type
:
502 if (__CFNumberTypeTable
[ntype
].floatBit
) {
503 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
504 CVT(Float32
, int32_t, INT32_MIN
, INT32_MAX
);
506 CVT(Float64
, int32_t, INT32_MIN
, INT32_MAX
);
509 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
510 CVT(int64_t, int32_t, INT32_MIN
, INT32_MAX
);
512 CVT128ToInt(CFSInt128Struct
, int32_t, INT32_MIN
, INT32_MAX
);
516 case kCFNumberSInt64Type
:
517 if (__CFNumberTypeTable
[ntype
].floatBit
) {
518 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
519 CVT(Float32
, int64_t, INT64_MIN
, INT64_MAX
);
521 CVT(Float64
, int64_t, INT64_MIN
, INT64_MAX
);
524 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
525 memmove(valuePtr
, data
, 8);
527 CVT128ToInt(CFSInt128Struct
, int64_t, INT64_MIN
, INT64_MAX
);
531 case kCFNumberSInt128Type
:
532 if (__CFNumberTypeTable
[ntype
].floatBit
) {
533 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
535 memmove(&f
, data
, 4);
538 cvtFloat64ToSInt128(&i
, &d
);
539 memmove(valuePtr
, &i
, 16);
541 cvtSInt128ToFloat64(&d2
, &i
);
542 Float32 f2
= (Float32
)d2
;
546 memmove(&d
, data
, 8);
548 cvtFloat64ToSInt128(&i
, &d
);
549 memmove(valuePtr
, &i
, 16);
551 cvtSInt128ToFloat64(&d2
, &i
);
555 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
557 memmove(&j
, data
, 8);
560 i
.high
= (j
< 0) ? -1LL : 0LL;
561 memmove(valuePtr
, &i
, 16);
563 memmove(valuePtr
, data
, 16);
567 case kCFNumberFloat32Type
:
568 if (__CFNumberTypeTable
[ntype
].floatBit
) {
569 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
570 memmove(valuePtr
, data
, 4);
573 memmove(&d
, data
, 8);
575 uint32_t l
= 0x7fc00000;
576 memmove(valuePtr
, &l
, 4);
578 } else if (isinf(d
)) {
579 uint32_t l
= 0x7f800000;
580 if (d
< 0.0) l
+= 0x80000000UL
;
581 memmove(valuePtr
, &l
, 4);
584 CVT(Float64
, Float32
, -FLT_MAX
, FLT_MAX
);
587 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
588 CVT(int64_t, Float32
, -FLT_MAX
, FLT_MAX
);
591 memmove(&i
, data
, 16);
593 cvtSInt128ToFloat64(&d
, &i
);
594 Float32 f
= (Float32
)d
;
595 memmove(valuePtr
, &f
, 4);
598 cvtFloat64ToSInt128(&i2
, &d
);
599 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
603 case kCFNumberFloat64Type
:
604 if (__CFNumberTypeTable
[ntype
].floatBit
) {
605 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
607 memmove(&f
, data
, 4);
609 uint64_t l
= BITSFORDOUBLENAN
;
610 memmove(valuePtr
, &l
, 8);
612 } else if (isinf(f
)) {
613 uint64_t l
= BITSFORDOUBLEPOSINF
;
614 if (f
< 0.0) l
+= 0x8000000000000000ULL
;
615 memmove(valuePtr
, &l
, 8);
618 CVT(Float32
, Float64
, -DBL_MAX
, DBL_MAX
);
620 memmove(valuePtr
, data
, 8);
623 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
624 CVT(int64_t, Float64
, -DBL_MAX
, DBL_MAX
);
627 memmove(&i
, data
, 16);
629 cvtSInt128ToFloat64(&d
, &i
);
630 memmove(valuePtr
, &d
, 8);
632 cvtFloat64ToSInt128(&i2
, &d
);
633 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
641 #define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
642 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
643 DST_TYPE dv = (DST_TYPE)(sv); \
644 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
645 SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
648 #define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
649 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
650 DST_TYPE dv; dv = (DST_TYPE)sv.low; \
651 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
652 uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
655 // this has the old cast-style behavior
656 static Boolean
__CFNumberGetValueCompat(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
657 type
= __CFNumberTypeTable
[type
].canonicalType
;
658 CFNumberType ntype
= __CFNumberGetType(number
);
659 const void *data
= &(number
->_pad
);
660 intptr_t taggedInteger
;
661 if (CF_IS_TAGGED_INT(number
)) {
662 taggedInteger
= (intptr_t)number
;
663 taggedInteger
= taggedInteger
>> 8;
664 data
= &taggedInteger
;
667 case kCFNumberSInt8Type
:
668 if (__CFNumberTypeTable
[ntype
].floatBit
) {
669 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
670 CVT_COMPAT(Float32
, int8_t, 0);
672 CVT_COMPAT(Float64
, int8_t, 0);
675 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
676 // 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>
677 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
678 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
679 int8_t dv
= (int8_t)(sv
);
680 memmove(valuePtr
, &dv
, sizeof(int8_t));
681 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 8LL) == 0LL) || (vv
== sv
);
683 CVT128ToInt_COMPAT(CFSInt128Struct
, int8_t);
687 case kCFNumberSInt16Type
:
688 if (__CFNumberTypeTable
[ntype
].floatBit
) {
689 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
690 CVT_COMPAT(Float32
, int16_t, 0);
692 CVT_COMPAT(Float64
, int16_t, 0);
695 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
696 // 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>
697 // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
698 int64_t sv
; memmove(&sv
, data
, sizeof(int64_t));
699 int16_t dv
= (int16_t)(sv
);
700 memmove(valuePtr
, &dv
, sizeof(int16_t));
701 int64_t vv
= (int64_t)dv
; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
) || ((sv
>> 16LL) == 0LL) || (vv
== sv
);
703 CVT128ToInt_COMPAT(CFSInt128Struct
, int16_t);
707 case kCFNumberSInt32Type
:
708 if (__CFNumberTypeTable
[ntype
].floatBit
) {
709 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
710 CVT_COMPAT(Float32
, int32_t, 0);
712 CVT_COMPAT(Float64
, int32_t, 0);
715 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
716 CVT_COMPAT(int64_t, int32_t, 0);
718 CVT128ToInt_COMPAT(CFSInt128Struct
, int32_t);
722 case kCFNumberSInt64Type
:
723 if (__CFNumberTypeTable
[ntype
].floatBit
) {
724 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
725 CVT_COMPAT(Float32
, int64_t, 0);
727 CVT_COMPAT(Float64
, int64_t, 0);
730 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
731 CVT_COMPAT(int64_t, int64_t, 0);
733 CVT128ToInt_COMPAT(CFSInt128Struct
, int64_t);
737 case kCFNumberSInt128Type
:
738 if (__CFNumberTypeTable
[ntype
].floatBit
) {
739 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
741 memmove(&f
, data
, 4);
744 cvtFloat64ToSInt128(&i
, &d
);
745 memmove(valuePtr
, &i
, 16);
747 cvtSInt128ToFloat64(&d2
, &i
);
748 Float32 f2
= (Float32
)d2
;
752 memmove(&d
, data
, 8);
754 cvtFloat64ToSInt128(&i
, &d
);
755 memmove(valuePtr
, &i
, 16);
757 cvtSInt128ToFloat64(&d2
, &i
);
761 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
763 memmove(&j
, data
, 8);
766 i
.high
= (j
< 0) ? -1LL : 0LL;
767 memmove(valuePtr
, &i
, 16);
769 memmove(valuePtr
, data
, 16);
773 case kCFNumberFloat32Type
:
774 if (__CFNumberTypeTable
[ntype
].floatBit
) {
775 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
776 memmove(valuePtr
, data
, 4);
778 CVT_COMPAT(Float64
, Float32
, 0);
781 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
782 CVT_COMPAT(int64_t, Float32
, 0);
785 memmove(&i
, data
, 16);
787 cvtSInt128ToFloat64(&d
, &i
);
788 Float32 f
= (Float32
)d
;
789 memmove(valuePtr
, &f
, 4);
792 cvtFloat64ToSInt128(&i2
, &d
);
793 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
797 case kCFNumberFloat64Type
:
798 if (__CFNumberTypeTable
[ntype
].floatBit
) {
799 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
800 CVT_COMPAT(Float32
, Float64
, 0);
802 memmove(valuePtr
, data
, 8);
805 if (0 == __CFNumberTypeTable
[ntype
].storageBit
) {
806 CVT_COMPAT(int64_t, Float64
, 0);
809 memmove(&i
, data
, 16);
811 cvtSInt128ToFloat64(&d
, &i
);
812 memmove(valuePtr
, &d
, 8);
814 cvtFloat64ToSInt128(&i2
, &d
);
815 return cmp128(&i2
, &i
) == kCFCompareEqualTo
;
824 static void FAIL(void) {}
827 static CFStringRef
__CFNumberCopyDescription(CFTypeRef cf
) {
828 CFNumberRef number
= (CFNumberRef
)cf
;
829 CFNumberType type
= __CFNumberGetType(number
);
830 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
831 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
832 if (__CFNumberTypeTable
[type
].floatBit
) {
834 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
836 CFStringAppend(mstr
, CFSTR("nan"));
837 } else if (isinf(d
)) {
838 CFStringAppend(mstr
, (0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
839 } else if (0.0 == d
) {
840 CFStringAppend(mstr
, (copysign(1.0, d
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
842 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.*f"), (__CFNumberTypeTable
[type
].storageBit
? 20 : 10), d
);
844 const char *typeName
= "unknown float";
846 case kCFNumberFloat32Type
: typeName
= "kCFNumberFloat32Type"; break;
847 case kCFNumberFloat64Type
: typeName
= "kCFNumberFloat64Type"; break;
849 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = %s}"), typeName
);
852 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
854 emit128(buffer
, &i
, true);
855 const char *typeName
= "unknown integer";
857 case kCFNumberSInt8Type
: typeName
= "kCFNumberSInt8Type"; break;
858 case kCFNumberSInt16Type
: typeName
= "kCFNumberSInt16Type"; break;
859 case kCFNumberSInt32Type
: typeName
= "kCFNumberSInt32Type"; break;
860 case kCFNumberSInt64Type
: typeName
= "kCFNumberSInt64Type"; break;
861 case kCFNumberSInt128Type
: typeName
= "kCFNumberSInt128Type"; break;
863 CFStringAppendFormat(mstr
, NULL
, CFSTR("%s, type = %s}"), buffer
, typeName
);
866 if (! number
->__old__
) {
868 printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf
);
870 CFStringRef test
= __CFNumberCopyDescription_old(number
->__old__
);
871 if (!CFEqual(test
, mstr
)) {
872 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test
, mstr
); FAIL();
879 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
881 static CFStringRef
__CFNumberCreateFormattingDescriptionAsFloat64(CFAllocatorRef allocator
, CFTypeRef cf
) {
883 CFNumberGetValue((CFNumberRef
)cf
, kCFNumberFloat64Type
, &d
);
885 return (CFStringRef
)CFRetain(CFSTR("nan"));
888 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
891 return (CFStringRef
)CFRetain(CFSTR("0.0"));
893 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
894 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
897 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf
) {
898 CFStringRef result
= __CFNumberCreateFormattingDescriptionAsFloat64(kCFAllocatorSystemDefault
, cf
);
900 CFNumberRef number
= (CFNumberRef
)cf
;
901 if (! number
->__old__
) {
902 printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf
);
904 CFStringRef test
= __CFNumberCopyFormattingDescriptionAsFloat64_old(number
->__old__
);
905 if (!CFEqual(test
, result
)) {
906 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test
, result
); FAIL();
913 __private_extern__ CFStringRef
__CFNumberCreateFormattingDescription(CFAllocatorRef allocator
, CFTypeRef cf
, CFDictionaryRef formatOptions
) {
914 CFNumberRef number
= (CFNumberRef
)cf
;
915 CFNumberType type
= __CFNumberGetType(number
);
916 if (__CFNumberTypeTable
[type
].floatBit
) {
917 return __CFNumberCreateFormattingDescriptionAsFloat64(allocator
, number
);
920 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
922 emit128(buffer
, &i
, false);
923 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("%s"), buffer
);
926 static CFStringRef
__CFNumberCopyFormattingDescription_new(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
927 CFNumberRef number
= (CFNumberRef
)cf
;
928 CFNumberType type
= __CFNumberGetType(number
);
929 if (__CFNumberTypeTable
[type
].floatBit
) {
930 return __CFNumberCopyFormattingDescriptionAsFloat64(number
);
933 __CFNumberGetValue(number
, kCFNumberSInt128Type
, &i
);
935 emit128(buffer
, &i
, false);
936 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%s"), buffer
);
939 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
940 CFStringRef result
= __CFNumberCopyFormattingDescription_new(cf
, formatOptions
);
942 CFNumberRef number
= (CFNumberRef
)cf
;
943 if (! number
->__old__
) {
944 printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf
);
946 CFStringRef test
= __CFNumberCopyFormattingDescription_old(number
->__old__
, formatOptions
);
947 if (!CFEqual(test
, result
)) {
948 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test
, result
); FAIL();
956 static Boolean
__CFNumberEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
957 Boolean b
= CFNumberCompare((CFNumberRef
)cf1
, (CFNumberRef
)cf2
, 0) == kCFCompareEqualTo
;
959 CFNumberRef number1
= (CFNumberRef
)cf1
;
960 CFNumberRef number2
= (CFNumberRef
)cf2
;
961 if (! number1
->__old__
|| !number2
->__old__
) {
962 printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1
, cf2
);
964 Boolean b2
= __CFNumberEqual_old(number1
->__old__
, number2
->__old__
);
966 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2
, b
); FAIL();
973 static CFHashCode
__CFNumberHash(CFTypeRef cf
) {
975 CFNumberRef number
= (CFNumberRef
)cf
;
976 switch (__CFNumberGetType(number
)) {
977 case kCFNumberSInt8Type
:
978 case kCFNumberSInt16Type
:
979 case kCFNumberSInt32Type
: {
981 __CFNumberGetValue(number
, kCFNumberSInt32Type
, &i
);
987 __CFNumberGetValue(number
, kCFNumberFloat64Type
, &d
);
988 h
= _CFHashDouble((double)d
);
993 CFNumberRef number1
= (CFNumberRef
)cf
;
994 if (! number1
->__old__
) {
995 printf("*** Test skipped in __CFNumberHash for number %p\n", cf
);
997 CFHashCode h2
= __CFNumberHash_old(number1
->__old__
);
999 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2
, h
); FAIL();
1006 static CFTypeID __kCFNumberTypeID
= _kCFRuntimeNotATypeID
;
1007 static void *__CFTaggedNumberClass
= 0;
1010 kCFNumberCachingEnabled
= 0,
1011 kCFNumberCachingDisabled
= 1,
1012 kCFNumberCachingFullyDisabled
= 2
1014 static char __CFNumberCaching
= kCFNumberCachingEnabled
;
1016 static const CFRuntimeClass __CFNumberClass
= {
1024 __CFNumberCopyFormattingDescription
,
1025 __CFNumberCopyDescription
1028 __private_extern__
void __CFNumberInitialize(void) {
1029 __kCFNumberTypeID
= _CFRuntimeRegisterClass(&__CFNumberClass
);
1031 _CFRuntimeSetInstanceTypeID(&__kCFNumberNaN
, __kCFNumberTypeID
);
1032 __kCFNumberNaN
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
1033 __CFBitfieldSetValue(__kCFNumberNaN
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1034 __kCFNumberNaN
._pad
= BITSFORDOUBLENAN
;
1036 _CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity
, __kCFNumberTypeID
);
1037 __kCFNumberNegativeInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
1038 __CFBitfieldSetValue(__kCFNumberNegativeInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1039 __kCFNumberNegativeInfinity
._pad
= BITSFORDOUBLENEGINF
;
1041 _CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity
, __kCFNumberTypeID
);
1042 __kCFNumberPositiveInfinity
._base
._cfisa
= __CFISAForTypeID(__kCFNumberTypeID
);
1043 __CFBitfieldSetValue(__kCFNumberPositiveInfinity
._base
._cfinfo
[CF_INFO_BITS
], 4, 0, kCFNumberFloat64Type
);
1044 __kCFNumberPositiveInfinity
._pad
= BITSFORDOUBLEPOSINF
;
1047 const char *caching
= __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled
1048 if (caching
) __CFNumberCaching
= (!strcmp(caching
, "all")) ? kCFNumberCachingFullyDisabled
: kCFNumberCachingDisabled
; // initial state above is kCFNumberCachingEnabled
1051 CFTypeID
CFNumberGetTypeID(void) {
1052 return __kCFNumberTypeID
;
1055 #define MinCachedInt (-1)
1056 #define MaxCachedInt (12)
1057 #define NotToBeCached (MinCachedInt - 1)
1058 static CFNumberRef __CFNumberCache
[MaxCachedInt
- MinCachedInt
+ 1] = {NULL
}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
1060 CFNumberRef
CFNumberCreate(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1061 __CFAssertIsValidNumberType(type
);
1062 //printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
1064 if (!allocator
) allocator
= __CFGetDefaultAllocator();
1066 if (__CFTaggedNumberClass
&& _CFAllocatorIsSystemDefault(allocator
) && (__CFNumberCaching
!= kCFNumberCachingFullyDisabled
)) {
1067 switch (__CFNumberTypeTable
[type
].canonicalType
) { // canonicalized client-desired type
1068 case kCFNumberSInt8Type
: {
1069 int8_t value
= *(int8_t *)valuePtr
;
1070 return (CFNumberRef
)((uintptr_t)((intptr_t)value
<< 8) | (0 << 6) | kCFTaggedObjectID_Integer
);
1072 case kCFNumberSInt16Type
: {
1073 int16_t value
= *(int16_t *)valuePtr
;
1074 return (CFNumberRef
)((uintptr_t)((intptr_t)value
<< 8) | (1 << 6) | kCFTaggedObjectID_Integer
);
1076 case kCFNumberSInt32Type
: {
1077 int32_t value
= *(int32_t *)valuePtr
;
1079 // We don't bother allowing the min 24-bit integer -2^24 to also be fast-pathed;
1080 // tell anybody that complains about that to go ... hang.
1081 if ((1L << 23) <= -value
|| (1L << 23) <= value
) break;
1083 return (CFNumberRef
)((uintptr_t)((intptr_t)value
<< 8) | (2 << 6) | kCFTaggedObjectID_Integer
);
1086 case kCFNumberSInt64Type
: {
1087 int64_t value
= *(int64_t *)valuePtr
;
1088 // We don't bother allowing the min 56-bit integer -2^56 to also be fast-pathed;
1089 // tell anybody that complains about that to go ... hang.
1090 if ((1L << 55) <= -value
|| (1L << 55) <= value
) break;
1091 uintptr_t ptr_val
= ((uintptr_t)(value
<< 8) | (3 << 6) | kCFTaggedObjectID_Integer
);
1092 return (CFNumberRef
)ptr_val
;
1098 // Look for cases where we can return a cached instance.
1099 // We only use cached objects if the allocator is the system
1100 // default allocator, except for the special floating point
1101 // constant objects, where we return the cached object
1102 // regardless of allocator, since that is what has always
1103 // been done (and now must for compatibility).
1104 int64_t valToBeCached
= NotToBeCached
;
1106 if (__CFNumberTypeTable
[type
].floatBit
) {
1107 CFNumberRef cached
= NULL
;
1108 if (0 == __CFNumberTypeTable
[type
].storageBit
) {
1109 Float32 f
= *(Float32
*)valuePtr
;
1110 if (isnan(f
)) cached
= kCFNumberNaN
;
1111 if (isinf(f
)) cached
= (f
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1113 Float64 d
= *(Float64
*)valuePtr
;
1114 if (isnan(d
)) cached
= kCFNumberNaN
;
1115 if (isinf(d
)) cached
= (d
< 0.0) ? kCFNumberNegativeInfinity
: kCFNumberPositiveInfinity
;
1117 if (cached
) return (CFNumberRef
)CFRetain(cached
);
1118 } else if (_CFAllocatorIsSystemDefault(allocator
) && (__CFNumberCaching
== kCFNumberCachingEnabled
)) {
1119 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1120 case kCFNumberSInt8Type
: {int8_t val
= *(int8_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1121 case kCFNumberSInt16Type
: {int16_t val
= *(int16_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1122 case kCFNumberSInt32Type
: {int32_t val
= *(int32_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1123 case kCFNumberSInt64Type
: {int64_t val
= *(int64_t *)valuePtr
; if (MinCachedInt
<= val
&& val
<= MaxCachedInt
) valToBeCached
= (int64_t)val
; break;}
1125 if (NotToBeCached
!= valToBeCached
) {
1126 CFNumberRef cached
= __CFNumberCache
[valToBeCached
- MinCachedInt
]; // Atomic to access the value in the cache
1127 if (NULL
!= cached
) return (CFNumberRef
)CFRetain(cached
);
1131 CFIndex size
= 8 + ((!__CFNumberTypeTable
[type
].floatBit
&& __CFNumberTypeTable
[type
].storageBit
) ? 8 : 0);
1133 size
+= 2 * sizeof(void *);
1135 CFNumberRef result
= (CFNumberRef
)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, size
, NULL
);
1136 if (NULL
== result
) {
1139 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)__CFNumberTypeTable
[type
].canonicalType
);
1142 ((struct __CFNumber
*)result
)->__old__
= CFNumberCreate_old(allocator
, type
, valuePtr
);
1143 CFLog(kCFLogLevelWarning
, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result
->__old__
));
1147 // for a value to be cached, we already have the value handy
1148 if (NotToBeCached
!= valToBeCached
) {
1149 memmove((void *)&result
->_pad
, &valToBeCached
, 8);
1150 // 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.
1151 // 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.
1152 // Barrier assures that the number that is placed in the cache is properly formed.
1153 CFNumberType origType
= __CFNumberGetType(result
);
1154 // Force all cached numbers to have the same type, so that the type does not
1155 // depend on the order and original type in/with which the numbers are created.
1156 // Forcing the type AFTER it was cached would cause a race condition with other
1157 // threads pulling the number object out of the cache and using it.
1158 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)kCFNumberSInt32Type
);
1159 if (OSAtomicCompareAndSwapPtrBarrier(NULL
, (void *)result
, (void *volatile *)&__CFNumberCache
[valToBeCached
- MinCachedInt
])) {
1162 // Did not cache the number object, put original type back.
1163 __CFBitfieldSetValue(((struct __CFNumber
*)result
)->_base
._cfinfo
[CF_INFO_BITS
], 4, 0, (uint8_t)origType
);
1169 switch (__CFNumberTypeTable
[type
].canonicalType
) {
1170 case kCFNumberSInt8Type
: value
= (uint64_t)(int64_t)*(int8_t *)valuePtr
; goto smallVal
;
1171 case kCFNumberSInt16Type
: value
= (uint64_t)(int64_t)*(int16_t *)valuePtr
; goto smallVal
;
1172 case kCFNumberSInt32Type
: value
= (uint64_t)(int64_t)*(int32_t *)valuePtr
; goto smallVal
;
1173 smallVal
: memmove((void *)&result
->_pad
, &value
, 8); break;
1174 case kCFNumberSInt64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1175 case kCFNumberSInt128Type
: memmove((void *)&result
->_pad
, valuePtr
, 16); break;
1176 case kCFNumberFloat32Type
: memmove((void *)&result
->_pad
, valuePtr
, 4); break;
1177 case kCFNumberFloat64Type
: memmove((void *)&result
->_pad
, valuePtr
, 8); break;
1179 //printf(" => %p\n", result);
1183 CFNumberType
CFNumberGetType(CFNumberRef number
) {
1184 //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
1185 if (CF_IS_TAGGED_INT(number
)) {
1186 return __CFNumberGetType(number
);
1188 CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID
, CFNumberType
, number
, "_cfNumberType");
1189 __CFAssertIsNumber(number
);
1190 CFNumberType type
= __CFNumberGetType(number
);
1191 if (kCFNumberSInt128Type
== type
) type
= kCFNumberSInt64Type
; // must hide this type, since it is not public
1192 //printf(" => %d\n", type);
1194 if (! number
->__old__
) {
1195 printf("*** Test skipped in CFNumberGetType for number %p\n", number
);
1197 CFNumberType t2
= CFNumberGetType_old(number
->__old__
);
1199 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2
, type
); FAIL();
1206 CF_EXPORT CFNumberType
_CFNumberGetType2(CFNumberRef number
) {
1207 __CFAssertIsNumber(number
);
1208 return __CFNumberGetType(number
);
1211 CFIndex
CFNumberGetByteSize(CFNumberRef number
) {
1212 //printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
1213 __CFAssertIsNumber(number
);
1214 CFIndex r
= 1 << __CFNumberTypeTable
[CFNumberGetType(number
)].lgByteSize
;
1215 //printf(" => %d\n", r);
1217 if (! number
->__old__
) {
1218 printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number
);
1220 CFIndex r2
= CFNumberGetByteSize_old(number
->__old__
);
1222 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2
, r
); FAIL();
1229 Boolean
CFNumberIsFloatType(CFNumberRef number
) {
1230 //printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1231 __CFAssertIsNumber(number
);
1232 Boolean r
= __CFNumberTypeTable
[CFNumberGetType(number
)].floatBit
;
1233 //printf(" => %d\n", r);
1235 if (! number
->__old__
) {
1236 printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number
);
1238 Boolean r2
= CFNumberIsFloatType_old(number
->__old__
);
1240 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2
, r
); FAIL();
1247 Boolean
CFNumberGetValue(CFNumberRef number
, CFNumberType type
, void *valuePtr
) {
1248 //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1249 if (CF_IS_TAGGED_INT(number
)) {
1250 __CFAssertIsValidNumberType(type
);
1251 uint8_t localMemory
[128];
1252 if (!valuePtr
) valuePtr
= localMemory
;
1253 intptr_t taggedInteger
= (intptr_t)number
;
1254 taggedInteger
= taggedInteger
>> 8;
1255 switch (__CFNumberTypeTable
[type
].canonicalType
) { // canonicalized client-desired type
1256 case kCFNumberSInt8Type
:
1258 if (taggedInteger
< INT8_MIN
) {
1259 *(int8_t *)valuePtr
= INT8_MIN
;
1262 if (INT8_MAX
< taggedInteger
) {
1263 *(int8_t *)valuePtr
= INT8_MAX
;
1267 *(int8_t *)valuePtr
= (int8_t)taggedInteger
;
1269 case kCFNumberSInt16Type
:
1271 if (taggedInteger
< INT16_MIN
) {
1272 *(int16_t *)valuePtr
= INT16_MIN
;
1275 if (INT16_MAX
< taggedInteger
) {
1276 *(int16_t *)valuePtr
= INT16_MAX
;
1280 *(int16_t *)valuePtr
= (int16_t)taggedInteger
;
1282 case kCFNumberSInt32Type
:
1284 if (taggedInteger
< INT32_MIN
) {
1285 *(int32_t *)valuePtr
= INT32_MIN
;
1288 if (INT32_MAX
< taggedInteger
) {
1289 *(int32_t *)valuePtr
= INT32_MAX
;
1293 *(int32_t *)valuePtr
= (int32_t)taggedInteger
;
1296 case kCFNumberSInt64Type
:
1297 *(int64_t *)valuePtr
= (int64_t)taggedInteger
;
1301 Boolean r
= __CFNumberGetValueCompat(number
, type
, valuePtr
);
1304 CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID
, Boolean
, number
, "_getValue:forType:", valuePtr
, __CFNumberTypeTable
[type
].canonicalType
);
1305 __CFAssertIsNumber(number
);
1306 __CFAssertIsValidNumberType(type
);
1307 uint8_t localMemory
[128];
1308 Boolean r
= __CFNumberGetValueCompat(number
, type
, valuePtr
? valuePtr
: localMemory
);
1309 //printf(" => %d\n", r);
1311 if (! number
->__old__
) {
1312 printf("*** Test skipped in CFNumberGetValue for number %p\n", number
);
1314 uint8_t localMemory2
[128];
1315 Boolean r2
= CFNumberGetValue_old(number
->__old__
, type
, localMemory2
);
1317 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2
, r
); FAIL();
1319 if (0 != memcmp(localMemory2
, valuePtr
, CFNumberGetByteSize(number
))) {
1320 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME")); FAIL();
1327 static CFComparisonResult
CFNumberCompare_new(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1328 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number1
, "compare:", number2
);
1329 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID
, CFComparisonResult
, number2
, "_reverseCompare:", number1
);
1330 __CFAssertIsNumber(number1
);
1331 __CFAssertIsNumber(number2
);
1333 CFNumberType type1
= __CFNumberGetType(number1
);
1334 CFNumberType type2
= __CFNumberGetType(number2
);
1335 // Both numbers are integers
1336 if (!__CFNumberTypeTable
[type1
].floatBit
&& !__CFNumberTypeTable
[type2
].floatBit
) {
1337 CFSInt128Struct i1
, i2
;
1338 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1339 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1340 return cmp128(&i1
, &i2
);
1342 // Both numbers are floats
1343 if (__CFNumberTypeTable
[type1
].floatBit
&& __CFNumberTypeTable
[type2
].floatBit
) {
1345 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1346 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1347 double s1
= copysign(1.0, d1
);
1348 double s2
= copysign(1.0, d2
);
1349 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1350 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1351 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1352 // at this point, we know we don't have any NaNs
1353 if (s1
< s2
) return kCFCompareLessThan
;
1354 if (s2
< s1
) return kCFCompareGreaterThan
;
1355 // at this point, we know the signs are the same; do not combine these tests
1356 if (d1
< d2
) return kCFCompareLessThan
;
1357 if (d2
< d1
) return kCFCompareGreaterThan
;
1358 return kCFCompareEqualTo
;
1360 // One float, one integer; swap if necessary so number1 is the float
1361 Boolean swapResult
= false;
1362 if (__CFNumberTypeTable
[type2
].floatBit
) {
1363 CFNumberRef tmp
= number1
;
1368 // At large integer values, the precision of double is quite low
1369 // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1370 // If we just used double compare, that would make the 2^73 largest 128-bit
1371 // integers look equal, so we have to use integer comparison when possible.
1373 __CFNumberGetValue(number1
, kCFNumberFloat64Type
, &d1
);
1374 // if the double value is really big, cannot be equal to integer
1375 // nan d1 will not compare true here
1376 if (d1
< FLOAT_NEGATIVE_2_TO_THE_127
) {
1377 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1379 if (FLOAT_POSITIVE_2_TO_THE_127
<= d1
) {
1380 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1382 CFSInt128Struct i1
, i2
;
1383 __CFNumberGetValue(number1
, kCFNumberSInt128Type
, &i1
);
1384 __CFNumberGetValue(number2
, kCFNumberSInt128Type
, &i2
);
1385 CFComparisonResult res
= cmp128(&i1
, &i2
);
1386 if (kCFCompareEqualTo
!= res
) {
1387 return !swapResult
? res
: -res
;
1389 // now things are equal, but perhaps due to rounding or nan
1391 if (isNeg128(&i2
)) {
1392 return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1394 // nan compares less than positive 0 too
1395 return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1397 // at this point, we know we don't have NaN
1398 double s1
= copysign(1.0, d1
);
1399 double s2
= isNeg128(&i2
) ? -1.0 : 1.0;
1400 if (s1
< s2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1401 if (s2
< s1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1402 // at this point, we know the signs are the same; do not combine these tests
1403 __CFNumberGetValue(number2
, kCFNumberFloat64Type
, &d2
);
1404 if (d1
< d2
) return !swapResult
? kCFCompareLessThan
: kCFCompareGreaterThan
;
1405 if (d2
< d1
) return !swapResult
? kCFCompareGreaterThan
: kCFCompareLessThan
;
1406 return kCFCompareEqualTo
;
1409 CFComparisonResult
CFNumberCompare(CFNumberRef number1
, CFNumberRef number2
, void *context
) {
1410 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1411 CFComparisonResult r
= CFNumberCompare_new(number1
, number2
, context
);
1412 //printf(" => %d\n", r);
1414 if (! number1
->__old__
|| !number2
->__old__
) {
1415 printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1
, number2
);
1417 CFComparisonResult r2
= CFNumberCompare_old(number1
->__old__
, number2
->__old__
, context
);
1419 CFLog(kCFLogLevelWarning
, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2
, r
); FAIL();
1428 static const unsigned char __CFNumberCanonicalType
[kCFNumberMaxType
+ 1] = {
1429 0, kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1430 kCFNumberSInt8Type
, kCFNumberSInt16Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1431 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1434 static const unsigned char __CFNumberStorageType
[kCFNumberMaxType
+ 1] = {
1435 0, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1436 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberSInt64Type
, kCFNumberFloat32Type
, kCFNumberFloat64Type
,
1437 kCFNumberSInt32Type
, kCFNumberSInt32Type
, kCFNumberFloat32Type
1442 // Returns the type that is used to store the specified type
1443 static CFNumberType
__CFNumberGetStorageTypeForType_old(CFNumberType type
) {
1444 return __CFNumberStorageType
[type
];
1447 // Returns the canonical type used to represent the specified type
1448 static CFNumberType
__CFNumberGetCanonicalTypeForType_old(CFNumberType type
) {
1449 return __CFNumberCanonicalType
[type
];
1452 // Extracts and returns the type out of the CFNumber
1453 static CFNumberType
__CFNumberGetType_old(struct __CFNumber_old
* num
) {
1454 return __CFBitfieldGetValue(num
->_base
._cfinfo
[CF_INFO_BITS
], 4, 0);
1457 // Returns true if the argument type is float or double
1458 static Boolean
__CFNumberTypeIsFloat_old(CFNumberType type
) {
1459 return (type
== kCFNumberFloat64Type
) || (type
== kCFNumberFloat32Type
) || (type
== kCFNumberDoubleType
) || (type
== kCFNumberFloatType
);
1462 // Returns the number of bytes necessary to store the specified type
1463 // Needs to handle all canonical types
1464 static CFIndex
__CFNumberSizeOfType_old(CFNumberType type
) {
1466 case kCFNumberSInt8Type
: return sizeof(int8_t);
1467 case kCFNumberSInt16Type
: return sizeof(int16_t);
1468 case kCFNumberSInt32Type
: return sizeof(SInt32
);
1469 case kCFNumberSInt64Type
: return sizeof(int64_t);
1470 case kCFNumberFloat32Type
: return sizeof(Float32
);
1471 case kCFNumberFloat64Type
: return sizeof(Float64
);
1472 default: printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
1476 // Copies an external value of a given type into the appropriate slot in the union (does no type conversion)
1477 // Needs to handle all canonical types
1478 #define SET_VALUE(valueUnion, type, valuePtr) \
1480 case kCFNumberSInt8Type: (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
1481 case kCFNumberSInt16Type: (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break; \
1482 case kCFNumberSInt32Type: (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
1483 case kCFNumberSInt64Type: (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break; \
1484 case kCFNumberFloat32Type: (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break; \
1485 case kCFNumberFloat64Type: (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break; \
1486 default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
1489 // Casts the specified value into the specified type and copies it into the provided memory
1490 // Needs to handle all canonical types
1491 #define GET_VALUE(value, type, resultPtr) \
1493 case kCFNumberSInt8Type: *(int8_t *)(resultPtr) = (int8_t)value; break; \
1494 case kCFNumberSInt16Type: *(int16_t *)(resultPtr) = (int16_t)value; break; \
1495 case kCFNumberSInt32Type: *(SInt32 *)(resultPtr) = (SInt32)value; break; \
1496 case kCFNumberSInt64Type: *(int64_t *)(resultPtr) = (int64_t)value; break; \
1497 case kCFNumberFloat32Type: *(Float32 *)(resultPtr) = (Float32)value; break; \
1498 case kCFNumberFloat64Type: *(Float64 *)(resultPtr) = (Float64)value; break; \
1499 default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
1502 // Extracts the stored type out of the union and copies it in the desired type into the provided memory
1503 // Needs to handle all storage types
1504 static void __CFNumberGetValue_old(const __CFNumberValue_old
*value
, CFNumberType numberType
, CFNumberType typeToGet
, void *valuePtr
) {
1505 switch (numberType
) {
1506 case kCFNumberSInt32Type
: GET_VALUE(value
->valSInt32
, typeToGet
, valuePtr
); break;
1507 case kCFNumberSInt64Type
: GET_VALUE(value
->valSInt64
, typeToGet
, valuePtr
); break;
1508 case kCFNumberFloat32Type
: GET_VALUE(value
->valFloat32
, typeToGet
, valuePtr
); break;
1509 case kCFNumberFloat64Type
: GET_VALUE(value
->valFloat64
, typeToGet
, valuePtr
); break;
1510 default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
1514 // Sees if two value union structs have the same value (will do type conversion)
1515 static Boolean
__CFNumberEqualValue_old(const __CFNumberValue_old
*value1
, CFNumberType type1
, const __CFNumberValue_old
*value2
, CFNumberType type2
) {
1516 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1518 __CFNumberGetValue_old(value1
, type1
, kCFNumberFloat64Type
, &d1
);
1519 __CFNumberGetValue_old(value2
, type2
, kCFNumberFloat64Type
, &d2
);
1520 if (isnan(d1
) && isnan(d2
)) return true; // Not mathematically sound, but required
1524 __CFNumberGetValue_old(value1
, type1
, kCFNumberSInt64Type
, &i1
);
1525 __CFNumberGetValue_old(value2
, type2
, kCFNumberSInt64Type
, &i2
);
1530 static Boolean
__CFNumberEqual_old(CFTypeRef cf1
, CFTypeRef cf2
) {
1531 struct __CFNumber_old
* number1
= (struct __CFNumber_old
*)cf1
;
1532 struct __CFNumber_old
* number2
= (struct __CFNumber_old
*)cf2
;
1533 return __CFNumberEqualValue_old(&(number1
->value
), __CFNumberGetType_old(number1
), &(number2
->value
), __CFNumberGetType_old(number2
));
1536 static CFHashCode
__CFNumberHash_old(CFTypeRef cf
) {
1537 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1538 switch (__CFNumberGetType_old((struct __CFNumber_old
*)cf
)) {
1539 case kCFNumberSInt32Type
: return _CFHashInt(number
->value
.valSInt32
);
1540 case kCFNumberSInt64Type
: return _CFHashDouble((double)(number
->value
.valSInt64
));
1541 case kCFNumberFloat32Type
: return _CFHashDouble((double)(number
->value
.valFloat32
));
1542 case kCFNumberFloat64Type
: return _CFHashDouble((double)(number
->value
.valFloat64
));
1543 default: printf("*** WARNING default case in __CFNumberHash_old\n");
1548 #define BUFFER_SIZE 100
1549 #define emitChar(ch) \
1550 {if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
1552 static void __CFNumberEmitInt64_old(CFMutableStringRef mstr
, int64_t value
, int32_t width
, UniChar pad
, bool explicitPlus
) {
1553 UniChar stackBuf
[BUFFER_SIZE
], *buf
= stackBuf
;
1554 uint64_t uvalue
, factor
, tmp
;
1558 neg
= (value
< 0) ? true : false;
1559 uvalue
= (neg
) ? -value
: value
;
1560 if (neg
|| explicitPlus
) width
--;
1569 for (w
= 0; w
< width
; w
++) emitChar(pad
);
1572 } else if (explicitPlus
) {
1575 while (0 < factor
) {
1576 UniChar ch
= '0' + (UniChar
)(uvalue
/ factor
);
1581 if (buf
> stackBuf
) CFStringAppendCharacters(mstr
, stackBuf
, buf
- stackBuf
);
1584 static CFStringRef
__CFNumberCopyDescription_old(CFTypeRef cf
) {
1585 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1586 CFMutableStringRef mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1587 CFStringAppendFormat(mstr
, NULL
, CFSTR("<CFNumber %p [%p]>{value = "), cf
, CFGetAllocator(cf
));
1588 switch (__CFNumberGetType_old(number
)) {
1589 case kCFNumberSInt32Type
:
1590 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt32
, 0, ' ', true);
1591 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt32Type}"));
1593 case kCFNumberSInt64Type
:
1594 __CFNumberEmitInt64_old(mstr
, number
->value
.valSInt64
, 0, ' ', true);
1595 CFStringAppendFormat(mstr
, NULL
, CFSTR(", type = kCFNumberSInt64Type}"));
1597 case kCFNumberFloat32Type
:
1598 // debugging formatting is intentionally more verbose and explicit about the value of the number
1599 if (isnan(number
->value
.valFloat32
)) {
1600 CFStringAppend(mstr
, CFSTR("nan"));
1601 } else if (isinf(number
->value
.valFloat32
)) {
1602 CFStringAppend(mstr
, (0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1603 } else if (0.0f
== number
->value
.valFloat32
) {
1604 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat32
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1606 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.10f"), number
->value
.valFloat32
);
1608 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat32Type}"));
1610 case kCFNumberFloat64Type
:
1611 // debugging formatting is intentionally more verbose and explicit about the value of the number
1612 if (isnan(number
->value
.valFloat64
)) {
1613 CFStringAppend(mstr
, CFSTR("nan"));
1614 } else if (isinf(number
->value
.valFloat64
)) {
1615 CFStringAppend(mstr
, (0.0 < number
->value
.valFloat64
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1616 } else if (0.0 == number
->value
.valFloat64
) {
1617 CFStringAppend(mstr
, (copysign(1.0, number
->value
.valFloat64
) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1619 CFStringAppendFormat(mstr
, NULL
, CFSTR("%+.20f"), number
->value
.valFloat64
);
1621 CFStringAppend(mstr
, CFSTR(", type = kCFNumberFloat64Type}"));
1630 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
1632 __private_extern__ CFStringRef
__CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf
) {
1634 CFNumberGetValue_old((struct __CFNumber_old
*)cf
, kCFNumberFloat64Type
, &d
);
1636 return (CFStringRef
)CFRetain(CFSTR("nan"));
1639 return (CFStringRef
)CFRetain((0.0 < d
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1642 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1644 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
1645 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), DBL_DIG
+ 2, d
);
1648 static CFStringRef
__CFNumberCopyFormattingDescription_old(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
1649 struct __CFNumber_old
* number
= (struct __CFNumber_old
*)cf
;
1650 CFMutableStringRef mstr
;
1652 switch (__CFNumberGetType_old(number
)) {
1653 case kCFNumberSInt32Type
:
1654 case kCFNumberSInt64Type
:
1655 value
= (__CFNumberGetType_old(number
) == kCFNumberSInt32Type
) ? number
->value
.valSInt32
: number
->value
.valSInt64
;
1656 mstr
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
1657 __CFNumberEmitInt64_old(mstr
, value
, 0, ' ', false);
1659 case kCFNumberFloat32Type
:
1660 if (isnan(number
->value
.valFloat32
)) {
1661 return (CFStringRef
)CFRetain(CFSTR("nan"));
1663 if (isinf(number
->value
.valFloat32
)) {
1664 return (CFStringRef
)CFRetain((0.0f
< number
->value
.valFloat32
) ? CFSTR("+infinity") : CFSTR("-infinity"));
1666 if (0.0f
== number
->value
.valFloat32
) {
1667 return (CFStringRef
)CFRetain(CFSTR("0.0"));
1669 // if %g is used here, need to use FLT_DIG + 2 on Mac OS X, but %f needs +1
1670 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%.*g"), FLT_DIG
+ 2, number
->value
.valFloat32
);
1671 case kCFNumberFloat64Type
:
1672 return __CFNumberCopyFormattingDescriptionAsFloat64_old(number
);
1681 static struct __CFNumber_old
* CFNumberCreate_old(CFAllocatorRef allocator
, CFNumberType type
, const void *valuePtr
) {
1682 struct __CFNumber_old
* num
;
1683 CFNumberType equivType
, storageType
;
1686 CFSInt128Struct
*s
= valuePtr
;
1687 s
->high
= (int64_t)s
->low
;
1688 type
= kCFNumberSInt64Type
;
1692 equivType
= __CFNumberGetCanonicalTypeForType_old(type
);
1694 storageType
= __CFNumberGetStorageTypeForType_old(type
);
1696 num
= (struct __CFNumber_old
*)_CFRuntimeCreateInstance(allocator
, __kCFNumberTypeID
, __CFNumberSizeOfType_old(storageType
), NULL
);
1700 SET_VALUE((__CFNumberValue_old
*)&(num
->value
), equivType
, valuePtr
);
1701 __CFBitfieldSetValue(((struct __CFNumber_old
*)num
)->_base
._cfinfo
[CF_INFO_BITS
], 6, 0, (uint8_t)storageType
);
1703 if (__CFNumberGetType_old(num
) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num
, storageType
);
1707 static CFNumberType
CFNumberGetType_old(struct __CFNumber_old
* number
) {
1709 return __CFNumberGetType_old(number
);
1712 static CFIndex
CFNumberGetByteSize_old(struct __CFNumber_old
* number
) {
1713 return __CFNumberSizeOfType_old(CFNumberGetType_old(number
));
1716 static Boolean
CFNumberIsFloatType_old(struct __CFNumber_old
* number
) {
1717 return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number
));
1720 static Boolean
CFNumberGetValue_old(struct __CFNumber_old
* number
, CFNumberType type
, void *valuePtr
) {
1721 uint8_t localMemory
[sizeof(__CFNumberValue_old
)];
1722 __CFNumberValue_old localValue
;
1723 CFNumberType numType
;
1724 CFNumberType storageTypeForType
;
1726 if (type
== 17) type
= kCFNumberSInt64Type
;
1728 storageTypeForType
= __CFNumberGetStorageTypeForType_old(type
);
1729 type
= __CFNumberGetCanonicalTypeForType_old(type
);
1730 if (!valuePtr
) valuePtr
= &localMemory
;
1732 numType
= __CFNumberGetType_old(number
);
1733 __CFNumberGetValue_old((__CFNumberValue_old
*)&(number
->value
), numType
, type
, valuePtr
);
1735 // If the types match, then we're fine!
1736 if (numType
== storageTypeForType
) return true;
1738 // Test to see if the returned value is intact...
1739 SET_VALUE(&localValue
, type
, valuePtr
);
1740 return __CFNumberEqualValue_old(&localValue
, storageTypeForType
, &(number
->value
), numType
);
1743 static CFComparisonResult
CFNumberCompare_old(struct __CFNumber_old
* number1
, struct __CFNumber_old
* number2
, void *context
) {
1744 CFNumberType type1
, type2
;
1747 type1
= __CFNumberGetType_old(number1
);
1748 type2
= __CFNumberGetType_old(number2
);
1750 if (__CFNumberTypeIsFloat_old(type1
) || __CFNumberTypeIsFloat_old(type2
)) {
1753 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberFloat64Type
, &d1
);
1754 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberFloat64Type
, &d2
);
1755 s1
= copysign(1.0, d1
);
1756 s2
= copysign(1.0, d2
);
1757 if (isnan(d1
) && isnan(d2
)) return kCFCompareEqualTo
;
1758 if (isnan(d1
)) return (s2
< 0.0) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
1759 if (isnan(d2
)) return (s1
< 0.0) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
1760 // at this point, we know we don't have any NaNs
1761 if (s1
< s2
) return kCFCompareLessThan
;
1762 if (s2
< s1
) return kCFCompareGreaterThan
;
1763 // at this point, we know the signs are the same; do not combine these tests
1764 if (d1
< d2
) return kCFCompareLessThan
;
1765 if (d2
< d1
) return kCFCompareGreaterThan
;
1766 return kCFCompareEqualTo
;
1769 __CFNumberGetValue_old(&(number1
->value
), type1
, kCFNumberSInt64Type
, &i1
);
1770 __CFNumberGetValue_old(&(number2
->value
), type2
, kCFNumberSInt64Type
, &i2
);
1771 return (i1
> i2
) ? kCFCompareGreaterThan
: ((i1
< i2
) ? kCFCompareLessThan
: kCFCompareEqualTo
);
1778 #undef __CFAssertIsBoolean
1779 #undef __CFAssertIsNumber
1780 #undef __CFAssertIsValidNumberType
1781 #undef BITSFORDOUBLENAN
1782 #undef BITSFORDOUBLEPOSINF
1783 #undef BITSFORDOUBLENEGINF
1786 #undef NotToBeCached