1/*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*	CFNumber.c
25	Copyright (c) 1999-2013, Apple Inc. All rights reserved.
26	Responsibility: Ali Ozer
27*/
28
29#include <CoreFoundation/CFNumber.h>
30#include "CFInternal.h"
31#include <CoreFoundation/CFPriv.h>
32#include <math.h>
33#include <float.h>
34
35
36#if DEPLOYMENT_TARGET_WINDOWS
37#define isnan(A) _isnan(A)
38#define isinf(A) !_finite(A)
39#define copysign(A, B) _copysign(A, B)
40#endif
41
42#define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
43
44struct __CFBoolean {
45    CFRuntimeBase _base;
46};
47
48static struct __CFBoolean __kCFBooleanTrue = {
49    INIT_CFRUNTIME_BASE()
50};
51const CFBooleanRef kCFBooleanTrue = &__kCFBooleanTrue;
52
53static struct __CFBoolean __kCFBooleanFalse = {
54    INIT_CFRUNTIME_BASE()
55};
56const CFBooleanRef kCFBooleanFalse = &__kCFBooleanFalse;
57
58static CFStringRef __CFBooleanCopyDescription(CFTypeRef cf) {
59    CFBooleanRef boolean = (CFBooleanRef)cf;
60    return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf, CFGetAllocator(cf), (boolean == kCFBooleanTrue) ? "true" : "false");
61}
62
63CF_PRIVATE CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
64    CFBooleanRef boolean = (CFBooleanRef)cf;
65    return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false"));
66}
67
68static CFHashCode __CFBooleanHash(CFTypeRef cf) {
69    CFBooleanRef boolean = (CFBooleanRef)cf;
70    return (boolean == kCFBooleanTrue) ? _CFHashInt(1) : _CFHashInt(0);
71}
72
73static void __CFBooleanDeallocate(CFTypeRef cf) {
74    CFAssert(false, __kCFLogAssertion, "Deallocated CFBoolean!");
75}
76
77static CFTypeID __kCFBooleanTypeID = _kCFRuntimeNotATypeID;
78
79static const CFRuntimeClass __CFBooleanClass = {
80    0,
81    "CFBoolean",
82    NULL,      // init
83    NULL,      // copy
84    __CFBooleanDeallocate,
85    NULL,
86    __CFBooleanHash,
87    __CFBooleanCopyFormattingDescription,
88    __CFBooleanCopyDescription
89};
90
91CF_PRIVATE void __CFBooleanInitialize(void) {
92    __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass);
93    _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue, __kCFBooleanTypeID);
94    _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse, __kCFBooleanTypeID);
95}
96
97CFTypeID CFBooleanGetTypeID(void) {
98    return __kCFBooleanTypeID;
99}
100
101Boolean CFBooleanGetValue(CFBooleanRef boolean) {
102    CF_OBJC_FUNCDISPATCHV(__kCFBooleanTypeID, Boolean, (NSNumber *)boolean, boolValue);
103    return (boolean == kCFBooleanTrue) ? true : false;
104}
105
106
107/*** CFNumber ***/
108
109#define OLD_CRAP_TOO 0
110
111#if OLD_CRAP_TOO
112
113// old implementation, for runtime comparison purposes
114
115typedef union {
116    SInt32 valSInt32;
117    int64_t valSInt64;
118    Float32 valFloat32;
119    Float64 valFloat64;
120} __CFNumberValue_old;
121
122struct __CFNumber_old {             /* Only as many bytes as necessary are allocated */
123    CFRuntimeBase _base;
124    __CFNumberValue_old value;
125};
126
127static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2);
128static CFHashCode __CFNumberHash_old(CFTypeRef cf);
129static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf);
130CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf);
131static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions);
132static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr);
133static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number);
134static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number);
135static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number);
136static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr);
137static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context);
138
139#endif
140
141
142#define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
143#define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
144
145/* The IEEE bit patterns... Also have:
1460x7f800000		float +Inf
1470x7fc00000		float NaN
1480xff800000		float -Inf
149*/
150#define BITSFORDOUBLENAN	((uint64_t)0x7ff8000000000000ULL)
151#define BITSFORDOUBLEPOSINF	((uint64_t)0x7ff0000000000000ULL)
152#define BITSFORDOUBLENEGINF	((uint64_t)0xfff0000000000000ULL)
153
154#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
155#define FLOAT_POSITIVE_2_TO_THE_64	0x1.0p+64L
156#define FLOAT_NEGATIVE_2_TO_THE_127	-0x1.0p+127L
157#define FLOAT_POSITIVE_2_TO_THE_127	0x1.0p+127L
158#elif DEPLOYMENT_TARGET_WINDOWS
159#define FLOAT_POSITIVE_2_TO_THE_64	18446744073709551616.0
160#define FLOAT_NEGATIVE_2_TO_THE_127	-170141183460469231731687303715884105728.0
161#define FLOAT_POSITIVE_2_TO_THE_127	170141183460469231731687303715884105728.0
162#else
163#error Unknown or unspecified DEPLOYMENT_TARGET
164#endif
165
166typedef struct {	// NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
167    int64_t high;
168    uint64_t low;
169} CFSInt128Struct;
170
171enum {
172    kCFNumberSInt128Type = 17
173};
174
175static uint8_t isNeg128(const CFSInt128Struct *in) {
176    return in->high < 0;
177}
178
179static CFComparisonResult cmp128(const CFSInt128Struct *in1, const CFSInt128Struct *in2) {
180    if (in1->high < in2->high) return kCFCompareLessThan;
181    if (in1->high > in2->high) return kCFCompareGreaterThan;
182    if (in1->low < in2->low) return kCFCompareLessThan;
183    if (in1->low > in2->low) return kCFCompareGreaterThan;
184    return kCFCompareEqualTo;
185}
186
187// allows out to be the same as in1 or in2
188static void add128(CFSInt128Struct *out, CFSInt128Struct *in1, CFSInt128Struct *in2) {
189    CFSInt128Struct tmp;
190    tmp.low = in1->low + in2->low;
191    tmp.high = in1->high + in2->high;
192    if (UINT64_MAX - in1->low < in2->low) {
193        tmp.high++;
194    }
195    *out = tmp;
196}
197
198// allows out to be the same as in
199static void neg128(CFSInt128Struct *out, CFSInt128Struct *in) {
200    uint64_t tmplow = ~in->low;
201    out->low = tmplow + 1;
202    out->high = ~in->high;
203    if (UINT64_MAX == tmplow) {
204	out->high++;
205    }
206}
207
208static const CFSInt128Struct powersOf10[] = {
209    { 0x4B3B4CA85A86C47ALL, 0x098A224000000000ULL },
210    { 0x0785EE10D5DA46D9LL, 0x00F436A000000000ULL },
211    { 0x00C097CE7BC90715LL, 0xB34B9F1000000000ULL },
212    { 0x0013426172C74D82LL, 0x2B878FE800000000ULL },
213    { 0x0001ED09BEAD87C0LL, 0x378D8E6400000000ULL },
214    { 0x0000314DC6448D93LL, 0x38C15B0A00000000ULL },
215    { 0x000004EE2D6D415BLL, 0x85ACEF8100000000ULL },
216    { 0x0000007E37BE2022LL, 0xC0914B2680000000ULL },
217    { 0x0000000C9F2C9CD0LL, 0x4674EDEA40000000ULL },
218    { 0x00000001431E0FAELL, 0x6D7217CAA0000000ULL },
219    { 0x00000000204FCE5ELL, 0x3E25026110000000ULL },
220    { 0x00000000033B2E3CLL, 0x9FD0803CE8000000ULL },
221    { 0x000000000052B7D2LL, 0xDCC80CD2E4000000ULL },
222    { 0x0000000000084595LL, 0x161401484A000000ULL },
223    { 0x000000000000D3C2LL, 0x1BCECCEDA1000000ULL },
224    { 0x000000000000152DLL, 0x02C7E14AF6800000ULL },
225    { 0x000000000000021ELL, 0x19E0C9BAB2400000ULL },
226    { 0x0000000000000036LL, 0x35C9ADC5DEA00000ULL },
227    { 0x0000000000000005LL, 0x6BC75E2D63100000ULL },
228    { 0x0000000000000000LL, 0x8AC7230489E80000ULL },
229    { 0x0000000000000000LL, 0x0DE0B6B3A7640000ULL },
230    { 0x0000000000000000LL, 0x016345785D8A0000ULL },
231    { 0x0000000000000000LL, 0x002386F26FC10000ULL },
232    { 0x0000000000000000LL, 0x00038D7EA4C68000ULL },
233    { 0x0000000000000000LL, 0x00005AF3107A4000ULL },
234    { 0x0000000000000000LL, 0x000009184E72A000ULL },
235    { 0x0000000000000000LL, 0x000000E8D4A51000ULL },
236    { 0x0000000000000000LL, 0x000000174876E800ULL },
237    { 0x0000000000000000LL, 0x00000002540BE400ULL },
238    { 0x0000000000000000LL, 0x000000003B9ACA00ULL },
239    { 0x0000000000000000LL, 0x0000000005F5E100ULL },
240    { 0x0000000000000000LL, 0x0000000000989680ULL },
241    { 0x0000000000000000LL, 0x00000000000F4240ULL },
242    { 0x0000000000000000LL, 0x00000000000186A0ULL },
243    { 0x0000000000000000LL, 0x0000000000002710ULL },
244    { 0x0000000000000000LL, 0x00000000000003E8ULL },
245    { 0x0000000000000000LL, 0x0000000000000064ULL },
246    { 0x0000000000000000LL, 0x000000000000000AULL },
247    { 0x0000000000000000LL, 0x0000000000000001ULL },
248};
249
250static const CFSInt128Struct neg_powersOf10[] = {
251    { 0xB4C4B357A5793B85LL, 0xF675DDC000000000ULL },
252    { 0xF87A11EF2A25B926LL, 0xFF0BC96000000000ULL },
253    { 0xFF3F68318436F8EALL, 0x4CB460F000000000ULL },
254    { 0xFFECBD9E8D38B27DLL, 0xD478701800000000ULL },
255    { 0xFFFE12F64152783FLL, 0xC872719C00000000ULL },
256    { 0xFFFFCEB239BB726CLL, 0xC73EA4F600000000ULL },
257    { 0xFFFFFB11D292BEA4LL, 0x7A53107F00000000ULL },
258    { 0xFFFFFF81C841DFDDLL, 0x3F6EB4D980000000ULL },
259    { 0xFFFFFFF360D3632FLL, 0xB98B1215C0000000ULL },
260    { 0xFFFFFFFEBCE1F051LL, 0x928DE83560000000ULL },
261    { 0xFFFFFFFFDFB031A1LL, 0xC1DAFD9EF0000000ULL },
262    { 0xFFFFFFFFFCC4D1C3LL, 0x602F7FC318000000ULL },
263    { 0xFFFFFFFFFFAD482DLL, 0x2337F32D1C000000ULL },
264    { 0xFFFFFFFFFFF7BA6ALL, 0xE9EBFEB7B6000000ULL },
265    { 0xFFFFFFFFFFFF2C3DLL, 0xE43133125F000000ULL },
266    { 0xFFFFFFFFFFFFEAD2LL, 0xFD381EB509800000ULL },
267    { 0xFFFFFFFFFFFFFDE1LL, 0xE61F36454DC00000ULL },
268    { 0xFFFFFFFFFFFFFFC9LL, 0xCA36523A21600000ULL },
269    { 0xFFFFFFFFFFFFFFFALL, 0x9438A1D29CF00000ULL },
270    { 0xFFFFFFFFFFFFFFFFLL, 0x7538DCFB76180000ULL },
271    { 0xFFFFFFFFFFFFFFFFLL, 0xF21F494C589C0000ULL },
272    { 0xFFFFFFFFFFFFFFFFLL, 0xFE9CBA87A2760000ULL },
273    { 0xFFFFFFFFFFFFFFFFLL, 0xFFDC790D903F0000ULL },
274    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFC72815B398000ULL },
275    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFA50CEF85C000ULL },
276    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFF6E7B18D6000ULL },
277    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFF172B5AF000ULL },
278    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFE8B7891800ULL },
279    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFDABF41C00ULL },
280    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFC4653600ULL },
281    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFA0A1F00ULL },
282    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFF676980ULL },
283    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFF0BDC0ULL },
284    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFE7960ULL },
285    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFD8F0ULL },
286    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFC18ULL },
287    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFF9CULL },
288    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFF6ULL },
289    { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFULL },
290};
291
292static void emit128(char *buffer, const CFSInt128Struct *in, Boolean forcePlus) {
293    CFSInt128Struct tmp = *in;
294    if (isNeg128(&tmp)) {
295	neg128(&tmp, &tmp);
296	*buffer++ = '-';
297    } else if (forcePlus) {
298	*buffer++ = '+';
299    }
300    Boolean doneOne = false;
301    int idx;
302    for (idx = 0; idx < sizeof(powersOf10) / sizeof(powersOf10[0]); idx++) {
303	int count = 0;
304        while (cmp128(&powersOf10[idx], &tmp) <= 0) {
305	    add128(&tmp, &tmp, (CFSInt128Struct *)&neg_powersOf10[idx]);
306	    count++;
307	}
308	if (0 != count || doneOne) {
309	    *buffer++ = '0' + count;
310	    doneOne = true;
311	}
312    }
313    if (!doneOne) {
314	*buffer++ = '0';
315    }
316    *buffer = '\0';
317}
318
319static void cvtSInt128ToFloat64(Float64 *out, const CFSInt128Struct *in) {
320    // switching to a positive number results in better accuracy
321    // for negative numbers close to zero, because the multiply
322    // of -1 by 2^64 (scaling the Float64 high) is avoided
323    Boolean wasNeg = false;
324    CFSInt128Struct tmp = *in;
325    if (isNeg128(&tmp)) {
326	neg128(&tmp, &tmp);
327	wasNeg = true;
328    }
329    Float64 d = (Float64)tmp.high * FLOAT_POSITIVE_2_TO_THE_64 + (Float64)tmp.low;
330    if (wasNeg) d = -d;
331    *out = d;
332}
333
334static void cvtFloat64ToSInt128(CFSInt128Struct *out, const Float64 *in) {
335    CFSInt128Struct i;
336    Float64 d = *in;
337    if (d < FLOAT_NEGATIVE_2_TO_THE_127) {
338	i.high = 0x8000000000000000LL;
339	i.low = 0x0000000000000000ULL;
340	*out = i;
341	return;
342    }
343    if (FLOAT_POSITIVE_2_TO_THE_127<= d) {
344	i.high = 0x7fffffffffffffffLL;
345	i.low = 0xffffffffffffffffULL;
346	*out = i;
347	return;
348    }
349    Float64 t = floor(d / FLOAT_POSITIVE_2_TO_THE_64);
350    i.high = (int64_t)t;
351    i.low = (uint64_t)(d - t * FLOAT_POSITIVE_2_TO_THE_64);
352    *out = i;
353}
354
355struct __CFNumber {
356    CFRuntimeBase _base;
357#if OLD_CRAP_TOO
358    struct __CFNumber_old *__old__;
359    void * __dummy__;
360#endif
361    uint64_t _pad; // need this space here for the constant objects
362    /* 0 or 8 more bytes allocated here */
363};
364
365/* Seven bits in base:
366    Bits 6..5: unused
367    Bits 4..0: CFNumber type
368*/
369
370static struct __CFNumber __kCFNumberNaN = {
371    INIT_CFRUNTIME_BASE(), 0ULL
372};
373const CFNumberRef kCFNumberNaN = &__kCFNumberNaN;
374
375static struct __CFNumber __kCFNumberNegativeInfinity = {
376    INIT_CFRUNTIME_BASE(), 0ULL
377};
378const CFNumberRef kCFNumberNegativeInfinity = &__kCFNumberNegativeInfinity;
379
380static struct __CFNumber __kCFNumberPositiveInfinity = {
381    INIT_CFRUNTIME_BASE(), 0ULL
382};
383const CFNumberRef kCFNumberPositiveInfinity = &__kCFNumberPositiveInfinity;
384
385static const struct {
386    uint16_t canonicalType:5;	// canonical fixed-width type
387    uint16_t floatBit:1;	// is float
388    uint16_t storageBit:1;	// storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
389    uint16_t lgByteSize:3;	// base-2 log byte size of public type
390    uint16_t unused:6;
391} __CFNumberTypeTable[] = {
392    /* 0 */			{0, 0, 0, 0},
393
394    /* kCFNumberSInt8Type */	{kCFNumberSInt8Type, 0, 0, 0, 0},
395    /* kCFNumberSInt16Type */	{kCFNumberSInt16Type, 0, 0, 1, 0},
396    /* kCFNumberSInt32Type */	{kCFNumberSInt32Type, 0, 0, 2, 0},
397    /* kCFNumberSInt64Type */	{kCFNumberSInt64Type, 0, 0, 3, 0},
398    /* kCFNumberFloat32Type */	{kCFNumberFloat32Type, 1, 0, 2, 0},
399    /* kCFNumberFloat64Type */	{kCFNumberFloat64Type, 1, 1, 3, 0},
400
401    /* kCFNumberCharType */	{kCFNumberSInt8Type, 0, 0, 0, 0},
402    /* kCFNumberShortType */	{kCFNumberSInt16Type, 0, 0, 1, 0},
403    /* kCFNumberIntType */	{kCFNumberSInt32Type, 0, 0, 2, 0},
404#if __LP64__
405    /* kCFNumberLongType */	{kCFNumberSInt64Type, 0, 0, 3, 0},
406#else
407    /* kCFNumberLongType */	{kCFNumberSInt32Type, 0, 0, 2, 0},
408#endif
409    /* kCFNumberLongLongType */	{kCFNumberSInt64Type, 0, 0, 3, 0},
410    /* kCFNumberFloatType */	{kCFNumberFloat32Type, 1, 0, 2, 0},
411    /* kCFNumberDoubleType */	{kCFNumberFloat64Type, 1, 1, 3, 0},
412
413#if __LP64__
414    /* kCFNumberCFIndexType */	{kCFNumberSInt64Type, 0, 0, 3, 0},
415    /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type, 0, 0, 3, 0},
416    /* kCFNumberCGFloatType */	{kCFNumberFloat64Type, 1, 1, 3, 0},
417#else
418    /* kCFNumberCFIndexType */	{kCFNumberSInt32Type, 0, 0, 2, 0},
419    /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type, 0, 0, 2, 0},
420    /* kCFNumberCGFloatType */	{kCFNumberFloat32Type, 1, 0, 2, 0},
421#endif
422
423    /* kCFNumberSInt128Type */	{kCFNumberSInt128Type, 0, 1, 4, 0},
424};
425
426CF_INLINE CFNumberType __CFNumberGetType(CFNumberRef num) {
427    return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
428}
429
430#define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
431	SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
432	DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
433	memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
434	SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
435	} while (0)
436
437#define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
438        SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
439	DST_TYPE dv; Boolean noLoss = false; \
440	if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
441	    dv = DST_MAX; \
442	} else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
443	    dv = DST_MIN; \
444	} else { \
445	    dv = (DST_TYPE)sv.low; \
446	    noLoss = true; \
447	} \
448        memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
449        return noLoss; \
450        } while (0)
451
452// returns false if the output value is not the same as the number's value, which
453// can occur due to accuracy loss and the value not being within the target range
454static Boolean __CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
455    type = __CFNumberTypeTable[type].canonicalType;
456    CFNumberType ntype = __CFNumberGetType(number);
457    const void *data = &(number->_pad);
458    switch (type) {
459    case kCFNumberSInt8Type:
460	if (__CFNumberTypeTable[ntype].floatBit) {
461	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
462		CVT(Float32, int8_t, INT8_MIN, INT8_MAX);
463	    } else {
464		CVT(Float64, int8_t, INT8_MIN, INT8_MAX);
465	    }
466	} else {
467	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
468		CVT(int64_t, int8_t, INT8_MIN, INT8_MAX);
469	    } else {
470		CVT128ToInt(CFSInt128Struct, int8_t, INT8_MIN, INT8_MAX);
471	    }
472	}
473	return true;
474    case kCFNumberSInt16Type:
475	if (__CFNumberTypeTable[ntype].floatBit) {
476	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
477                CVT(Float32, int16_t, INT16_MIN, INT16_MAX);
478	    } else {
479                CVT(Float64, int16_t, INT16_MIN, INT16_MAX);
480	    }
481	} else {
482	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
483                CVT(int64_t, int16_t, INT16_MIN, INT16_MAX);
484	    } else {
485		CVT128ToInt(CFSInt128Struct, int16_t, INT16_MIN, INT16_MAX);
486	    }
487	}
488	return true;
489    case kCFNumberSInt32Type:
490	if (__CFNumberTypeTable[ntype].floatBit) {
491	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
492                CVT(Float32, int32_t, INT32_MIN, INT32_MAX);
493	    } else {
494                CVT(Float64, int32_t, INT32_MIN, INT32_MAX);
495	    }
496	} else {
497	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
498                CVT(int64_t, int32_t, INT32_MIN, INT32_MAX);
499	    } else {
500		CVT128ToInt(CFSInt128Struct, int32_t, INT32_MIN, INT32_MAX);
501	    }
502	}
503	return true;
504    case kCFNumberSInt64Type:
505	if (__CFNumberTypeTable[ntype].floatBit) {
506	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
507                CVT(Float32, int64_t, INT64_MIN, INT64_MAX);
508	    } else {
509                CVT(Float64, int64_t, INT64_MIN, INT64_MAX);
510	    }
511	} else {
512	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
513		memmove(valuePtr, data, 8);
514	    } else {
515		CVT128ToInt(CFSInt128Struct, int64_t, INT64_MIN, INT64_MAX);
516	    }
517	}
518	return true;
519    case kCFNumberSInt128Type:
520	if (__CFNumberTypeTable[ntype].floatBit) {
521	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
522		Float32 f;
523		memmove(&f, data, 4);
524		Float64 d = f;
525		CFSInt128Struct i;
526		cvtFloat64ToSInt128(&i, &d);
527		memmove(valuePtr, &i, 16);
528		Float64 d2;
529		cvtSInt128ToFloat64(&d2, &i);
530		Float32 f2 = (Float32)d2;
531		return (f2 == f);
532	    } else {
533		Float64 d;
534		memmove(&d, data, 8);
535		CFSInt128Struct i;
536		cvtFloat64ToSInt128(&i, &d);
537		memmove(valuePtr, &i, 16);
538		Float64 d2;
539		cvtSInt128ToFloat64(&d2, &i);
540		return (d2 == d);
541	    }
542	} else {
543	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
544		int64_t j;
545		memmove(&j, data, 8);
546		CFSInt128Struct i;
547		i.low = j;
548		i.high = (j < 0) ? -1LL : 0LL;
549		memmove(valuePtr, &i, 16);
550	    } else {
551		memmove(valuePtr, data, 16);
552	    }
553	}
554	return true;
555    case kCFNumberFloat32Type:
556	if (__CFNumberTypeTable[ntype].floatBit) {
557	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
558		memmove(valuePtr, data, 4);
559	    } else {
560		double d;
561		memmove(&d, data, 8);
562		if (isnan(d)) {
563		    uint32_t l = 0x7fc00000;
564		    memmove(valuePtr, &l, 4);
565		    return true;
566		} else if (isinf(d)) {
567		    uint32_t l = 0x7f800000;
568		    if (d < 0.0) l += 0x80000000UL;
569		    memmove(valuePtr, &l, 4);
570		    return true;
571		}
572		CVT(Float64, Float32, -FLT_MAX, FLT_MAX);
573	    }
574	} else {
575	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
576		CVT(int64_t, Float32, -FLT_MAX, FLT_MAX);
577	    } else {
578		CFSInt128Struct i;
579		memmove(&i, data, 16);
580		Float64 d;
581		cvtSInt128ToFloat64(&d, &i);
582		Float32 f = (Float32)d;
583		memmove(valuePtr, &f, 4);
584		d = f;
585		CFSInt128Struct i2;
586		cvtFloat64ToSInt128(&i2, &d);
587		return cmp128(&i2, &i) == kCFCompareEqualTo;
588	    }
589	}
590	return true;
591    case kCFNumberFloat64Type:
592	if (__CFNumberTypeTable[ntype].floatBit) {
593	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
594		float f;
595		memmove(&f, data, 4);
596		if (isnan(f)) {
597		    uint64_t l = BITSFORDOUBLENAN;
598		    memmove(valuePtr, &l, 8);
599		    return true;
600		} else if (isinf(f)) {
601		    uint64_t l = BITSFORDOUBLEPOSINF;
602		    if (f < 0.0) l += 0x8000000000000000ULL;
603		    memmove(valuePtr, &l, 8);
604		    return true;
605		}
606		CVT(Float32, Float64, -DBL_MAX, DBL_MAX);
607	    } else {
608		memmove(valuePtr, data, 8);
609	    }
610	} else {
611	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
612		CVT(int64_t, Float64, -DBL_MAX, DBL_MAX);
613	    } else {
614                CFSInt128Struct i;
615                memmove(&i, data, 16);
616                Float64 d;
617                cvtSInt128ToFloat64(&d, &i);
618                memmove(valuePtr, &d, 8);
619                CFSInt128Struct i2;
620                cvtFloat64ToSInt128(&i2, &d);
621                return cmp128(&i2, &i) == kCFCompareEqualTo;
622	    }
623	}
624	return true;
625    }
626    return false;
627}
628
629#define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
630	SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
631	DST_TYPE dv = (DST_TYPE)(sv); \
632	memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
633	SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
634	} while (0)
635
636#define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
637        SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
638	DST_TYPE dv; dv = (DST_TYPE)sv.low; \
639        memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
640	uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
641        } while (0)
642
643// this has the old cast-style behavior
644static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, void *valuePtr) {
645    type = __CFNumberTypeTable[type].canonicalType;
646    CFNumberType ntype = __CFNumberGetType(number);
647    const void *data = &(number->_pad);
648    switch (type) {
649    case kCFNumberSInt8Type:
650	if (__CFNumberTypeTable[ntype].floatBit) {
651	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
652		CVT_COMPAT(Float32, int8_t, 0);
653	    } else {
654		CVT_COMPAT(Float64, int8_t, 0);
655	    }
656	} else {
657	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
658		// Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
659		// This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
660		int64_t sv; memmove(&sv, data, sizeof(int64_t));
661		int8_t dv = (int8_t)(sv);
662		memmove(valuePtr, &dv, sizeof(int8_t));
663		int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 8LL) == 0LL) || (vv == sv);
664	    } else {
665		CVT128ToInt_COMPAT(CFSInt128Struct, int8_t);
666	    }
667	}
668	return true;
669    case kCFNumberSInt16Type:
670	if (__CFNumberTypeTable[ntype].floatBit) {
671	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
672		CVT_COMPAT(Float32, int16_t, 0);
673	    } else {
674		CVT_COMPAT(Float64, int16_t, 0);
675	    }
676	} else {
677	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
678		// Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
679		// This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
680		int64_t sv; memmove(&sv, data, sizeof(int64_t));
681		int16_t dv = (int16_t)(sv);
682		memmove(valuePtr, &dv, sizeof(int16_t));
683		int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 16LL) == 0LL) || (vv == sv);
684	    } else {
685		CVT128ToInt_COMPAT(CFSInt128Struct, int16_t);
686	    }
687	}
688	return true;
689    case kCFNumberSInt32Type:
690	if (__CFNumberTypeTable[ntype].floatBit) {
691	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
692		CVT_COMPAT(Float32, int32_t, 0);
693	    } else {
694		CVT_COMPAT(Float64, int32_t, 0);
695	    }
696	} else {
697	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
698                CVT_COMPAT(int64_t, int32_t, 0);
699	    } else {
700		CVT128ToInt_COMPAT(CFSInt128Struct, int32_t);
701	    }
702	}
703	return true;
704    case kCFNumberSInt64Type:
705	if (__CFNumberTypeTable[ntype].floatBit) {
706	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
707		CVT_COMPAT(Float32, int64_t, 0);
708	    } else {
709		CVT_COMPAT(Float64, int64_t, 0);
710	    }
711	} else {
712	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
713                CVT_COMPAT(int64_t, int64_t, 0);
714	    } else {
715		CVT128ToInt_COMPAT(CFSInt128Struct, int64_t);
716	    }
717	}
718	return true;
719    case kCFNumberSInt128Type:
720	if (__CFNumberTypeTable[ntype].floatBit) {
721	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
722		Float32 f;
723		memmove(&f, data, 4);
724		Float64 d = f;
725		CFSInt128Struct i;
726		cvtFloat64ToSInt128(&i, &d);
727		memmove(valuePtr, &i, 16);
728		Float64 d2;
729		cvtSInt128ToFloat64(&d2, &i);
730		Float32 f2 = (Float32)d2;
731		return (f2 == f);
732	    } else {
733		Float64 d;
734		memmove(&d, data, 8);
735		CFSInt128Struct i;
736		cvtFloat64ToSInt128(&i, &d);
737		memmove(valuePtr, &i, 16);
738		Float64 d2;
739		cvtSInt128ToFloat64(&d2, &i);
740		return (d2 == d);
741	    }
742	} else {
743	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
744		int64_t j;
745		memmove(&j, data, 8);
746		CFSInt128Struct i;
747		i.low = j;
748		i.high = (j < 0) ? -1LL : 0LL;
749		memmove(valuePtr, &i, 16);
750	    } else {
751		memmove(valuePtr, data, 16);
752	    }
753	}
754	return true;
755    case kCFNumberFloat32Type:
756	if (__CFNumberTypeTable[ntype].floatBit) {
757	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
758		memmove(valuePtr, data, 4);
759	    } else {
760		CVT_COMPAT(Float64, Float32, 0);
761	    }
762	} else {
763	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
764		CVT_COMPAT(int64_t, Float32, 0);
765	    } else {
766		CFSInt128Struct i;
767		memmove(&i, data, 16);
768		Float64 d;
769		cvtSInt128ToFloat64(&d, &i);
770		Float32 f = (Float32)d;
771		memmove(valuePtr, &f, 4);
772		d = f;
773		CFSInt128Struct i2;
774		cvtFloat64ToSInt128(&i2, &d);
775		return cmp128(&i2, &i) == kCFCompareEqualTo;
776	    }
777	}
778	return true;
779    case kCFNumberFloat64Type:
780	if (__CFNumberTypeTable[ntype].floatBit) {
781	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
782		CVT_COMPAT(Float32, Float64, 0);
783	    } else {
784		memmove(valuePtr, data, 8);
785	    }
786	} else {
787	    if (0 == __CFNumberTypeTable[ntype].storageBit) {
788		CVT_COMPAT(int64_t, Float64, 0);
789	    } else {
790		CFSInt128Struct i;
791		memmove(&i, data, 16);
792		Float64 d;
793		cvtSInt128ToFloat64(&d, &i);
794		memmove(valuePtr, &d, 8);
795		CFSInt128Struct i2;
796		cvtFloat64ToSInt128(&i2, &d);
797		return cmp128(&i2, &i) == kCFCompareEqualTo;
798	    }
799	}
800	return true;
801    }
802    return false;
803}
804
805#if OLD_CRAP_TOO
806static void FAIL(void) {}
807#endif
808
809static CFStringRef __CFNumberCopyDescription(CFTypeRef cf) {
810    CFNumberRef number = (CFNumberRef)cf;
811    CFNumberType type = __CFNumberGetType(number);
812    CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
813    CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
814    if (__CFNumberTypeTable[type].floatBit) {
815	Float64 d;
816        __CFNumberGetValue(number, kCFNumberFloat64Type, &d);
817	if (isnan(d)) {
818	    CFStringAppend(mstr, CFSTR("nan"));
819	} else if (isinf(d)) {
820	    CFStringAppend(mstr, (0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
821	} else if (0.0 == d) {
822	    CFStringAppend(mstr, (copysign(1.0, d) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
823	} else {
824	    CFStringAppendFormat(mstr, NULL, CFSTR("%+.*f"), (__CFNumberTypeTable[type].storageBit ? 20 : 10), d);
825	}
826	const char *typeName = "unknown float";
827	switch (type) {
828	case kCFNumberFloat32Type: typeName = "kCFNumberFloat32Type"; break;
829	case kCFNumberFloat64Type: typeName = "kCFNumberFloat64Type"; break;
830	}
831	CFStringAppendFormat(mstr, NULL, CFSTR(", type = %s}"), typeName);
832    } else {
833	CFSInt128Struct i;
834	__CFNumberGetValue(number, kCFNumberSInt128Type, &i);
835	char buffer[128];
836	emit128(buffer, &i, true);
837	const char *typeName = "unknown integer";
838	switch (type) {
839	case kCFNumberSInt8Type: typeName = "kCFNumberSInt8Type"; break;
840	case kCFNumberSInt16Type: typeName = "kCFNumberSInt16Type"; break;
841	case kCFNumberSInt32Type: typeName = "kCFNumberSInt32Type"; break;
842	case kCFNumberSInt64Type: typeName = "kCFNumberSInt64Type"; break;
843	case kCFNumberSInt128Type: typeName = "kCFNumberSInt128Type"; break;
844	}
845	CFStringAppendFormat(mstr, NULL, CFSTR("%s, type = %s}"), buffer, typeName);
846    }
847#if OLD_CRAP_TOO
848if (! number->__old__) {
849
850printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf);
851} else {
852CFStringRef test = __CFNumberCopyDescription_old(number->__old__);
853if (!CFEqual(test, mstr)) {
854CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test, mstr);  FAIL();
855}
856}
857#endif
858    return mstr;
859}
860
861// This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
862
863static CFStringRef __CFNumberCreateFormattingDescriptionAsFloat64(CFAllocatorRef allocator, CFTypeRef cf) {
864    Float64 d;
865    CFNumberGetValue((CFNumberRef)cf, kCFNumberFloat64Type, &d);
866    if (isnan(d)) {
867	return (CFStringRef)CFRetain(CFSTR("nan"));
868    }
869    if (isinf(d)) {
870	return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
871    }
872    if (0.0 == d) {
873	return (CFStringRef)CFRetain(CFSTR("0.0"));
874    }
875    // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
876    return CFStringCreateWithFormat(allocator, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
877}
878
879CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) {
880    CFStringRef result = __CFNumberCreateFormattingDescriptionAsFloat64(kCFAllocatorSystemDefault, cf);
881#if OLD_CRAP_TOO
882CFNumberRef number = (CFNumberRef)cf;
883if (! number->__old__) {
884printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf);
885} else {
886CFStringRef test = __CFNumberCopyFormattingDescriptionAsFloat64_old(number->__old__);
887if (!CFEqual(test, result)) {
888CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test, result);  FAIL();
889}
890}
891#endif
892    return result;
893}
894
895CF_PRIVATE CFStringRef __CFNumberCreateFormattingDescription(CFAllocatorRef allocator, CFTypeRef cf, CFDictionaryRef formatOptions) {
896    CFNumberRef number = (CFNumberRef)cf;
897    CFNumberType type = __CFNumberGetType(number);
898    if (__CFNumberTypeTable[type].floatBit) {
899        return __CFNumberCreateFormattingDescriptionAsFloat64(allocator, number);
900    }
901    CFSInt128Struct i;
902    __CFNumberGetValue(number, kCFNumberSInt128Type, &i);
903    char buffer[128];
904    emit128(buffer, &i, false);
905    return CFStringCreateWithFormat(allocator, NULL, CFSTR("%s"), buffer);
906}
907
908static CFStringRef __CFNumberCopyFormattingDescription_new(CFTypeRef cf, CFDictionaryRef formatOptions) {
909    CFNumberRef number = (CFNumberRef)cf;
910    CFNumberType type = __CFNumberGetType(number);
911    if (__CFNumberTypeTable[type].floatBit) {
912        return __CFNumberCopyFormattingDescriptionAsFloat64(number);
913    }
914    CFSInt128Struct i;
915    __CFNumberGetValue(number, kCFNumberSInt128Type, &i);
916    char buffer[128];
917    emit128(buffer, &i, false);
918    return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%s"), buffer);
919}
920
921CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
922    CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions);
923#if OLD_CRAP_TOO
924CFNumberRef number = (CFNumberRef)cf;
925if (! number->__old__) {
926printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf);
927} else {
928CFStringRef test = __CFNumberCopyFormattingDescription_old(number->__old__, formatOptions);
929if (!CFEqual(test, result)) {
930CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test, result);  FAIL();
931}
932}
933#endif
934    return result;
935}
936
937
938static Boolean __CFNumberEqual(CFTypeRef cf1, CFTypeRef cf2) {
939    Boolean b = CFNumberCompare((CFNumberRef)cf1, (CFNumberRef)cf2, 0) == kCFCompareEqualTo;
940#if OLD_CRAP_TOO
941CFNumberRef number1 = (CFNumberRef)cf1;
942CFNumberRef number2 = (CFNumberRef)cf2;
943if (! number1->__old__ || !number2->__old__) {
944printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1, cf2);
945} else {
946Boolean b2 = __CFNumberEqual_old(number1->__old__, number2->__old__);
947if (b2 != b) {
948CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2, b);  FAIL();
949}
950}
951#endif
952    return b;
953}
954
955static CFHashCode __CFNumberHash(CFTypeRef cf) {
956    CFHashCode h;
957    CFNumberRef number = (CFNumberRef)cf;
958    switch (__CFNumberGetType(number)) {
959	case kCFNumberSInt8Type:
960	case kCFNumberSInt16Type:
961	case kCFNumberSInt32Type: {
962	    SInt32 i;
963	    __CFNumberGetValue(number, kCFNumberSInt32Type, &i);
964	    h = _CFHashInt(i);
965	    break;
966	}
967	default: {
968	    Float64 d;
969	    __CFNumberGetValue(number, kCFNumberFloat64Type, &d);
970	    h = _CFHashDouble((double)d);
971	    break;
972	}
973    }
974#if OLD_CRAP_TOO
975CFNumberRef number1 = (CFNumberRef)cf;
976if (! number1->__old__) {
977printf("*** Test skipped in __CFNumberHash for number %p\n", cf);
978} else {
979CFHashCode h2 = __CFNumberHash_old(number1->__old__);
980if (h2 != h) {
981CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2, h);  FAIL();
982}
983}
984#endif
985    return h;
986}
987
988static CFTypeID __kCFNumberTypeID = _kCFRuntimeNotATypeID;
989
990enum {
991  kCFNumberCachingEnabled = 0,
992  kCFNumberCachingDisabled = 1,
993  kCFNumberCachingFullyDisabled = 2
994};
995static char __CFNumberCaching = kCFNumberCachingEnabled;
996
997static const CFRuntimeClass __CFNumberClass = {
998    0,
999    "CFNumber",
1000    NULL,      // init
1001    NULL,      // copy
1002    NULL,
1003    __CFNumberEqual,
1004    __CFNumberHash,
1005    __CFNumberCopyFormattingDescription,
1006    __CFNumberCopyDescription
1007};
1008
1009
1010CF_PRIVATE void __CFNumberInitialize(void) {
1011    __kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass);
1012
1013    _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID);
1014    __CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
1015    __kCFNumberNaN._pad = BITSFORDOUBLENAN;
1016
1017    _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID);
1018    __CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
1019    __kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF;
1020
1021    _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID);
1022    __CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
1023    __kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF;
1024
1025
1026    const char *caching = __CFgetenv("CFNumberDisableCache");	// "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled
1027    if (caching) __CFNumberCaching = (!strcmp(caching, "all")) ? kCFNumberCachingFullyDisabled : kCFNumberCachingDisabled;	// initial state above is kCFNumberCachingEnabled
1028}
1029
1030CFTypeID CFNumberGetTypeID(void) {
1031    return __kCFNumberTypeID;
1032}
1033
1034#define MinCachedInt (-1)
1035#define MaxCachedInt (12)
1036#define NotToBeCached (MinCachedInt - 1)
1037static CFNumberRef __CFNumberCache[MaxCachedInt - MinCachedInt + 1] = {NULL};	// Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
1038
1039CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
1040    __CFAssertIsValidNumberType(type);
1041//printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
1042
1043    if (!allocator) allocator = __CFGetDefaultAllocator();
1044
1045
1046    // Look for cases where we can return a cached instance.
1047    // We only use cached objects if the allocator is the system
1048    // default allocator, except for the special floating point
1049    // constant objects, where we return the cached object
1050    // regardless of allocator, since that is what has always
1051    // been done (and now must for compatibility).
1052    int64_t valToBeCached = NotToBeCached;
1053
1054    if (__CFNumberTypeTable[type].floatBit) {
1055	CFNumberRef cached = NULL;
1056	if (0 == __CFNumberTypeTable[type].storageBit) {
1057	    Float32 f = *(Float32 *)valuePtr;
1058	    if (isnan(f)) cached = kCFNumberNaN;
1059	    if (isinf(f)) cached = (f < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
1060	} else {
1061            Float64 d = *(Float64 *)valuePtr;
1062	    if (isnan(d)) cached = kCFNumberNaN;
1063	    if (isinf(d)) cached = (d < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
1064	}
1065	if (cached) return (CFNumberRef)CFRetain(cached);
1066    } else if (_CFAllocatorIsSystemDefault(allocator) && (__CFNumberCaching == kCFNumberCachingEnabled)) {
1067	switch (__CFNumberTypeTable[type].canonicalType) {
1068	case kCFNumberSInt8Type:   {int8_t  val = *(int8_t *)valuePtr;  if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
1069	case kCFNumberSInt16Type:  {int16_t val = *(int16_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
1070	case kCFNumberSInt32Type:  {int32_t val = *(int32_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
1071	case kCFNumberSInt64Type:  {int64_t val = *(int64_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
1072	}
1073	if (NotToBeCached != valToBeCached) {
1074	    CFNumberRef cached = __CFNumberCache[valToBeCached - MinCachedInt];	    // Atomic to access the value in the cache
1075	    if (NULL != cached) return (CFNumberRef)CFRetain(cached);
1076	}
1077    }
1078
1079    CFIndex size = 8 + ((!__CFNumberTypeTable[type].floatBit && __CFNumberTypeTable[type].storageBit) ? 8 : 0);
1080#if OLD_CRAP_TOO
1081    size += 2 * sizeof(void *);
1082#endif
1083    CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, size, NULL);
1084    if (NULL == result) {
1085	return NULL;
1086    }
1087    __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)__CFNumberTypeTable[type].canonicalType);
1088
1089#if OLD_CRAP_TOO
1090    ((struct __CFNumber *)result)->__old__ = CFNumberCreate_old(allocator, type, valuePtr);
1091CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result->__old__));
1092
1093#endif
1094
1095    // for a value to be cached, we already have the value handy
1096    if (NotToBeCached != valToBeCached) {
1097	memmove((void *)&result->_pad, &valToBeCached, 8);
1098	// Put this in the cache unless the cache is already filled (by another thread).  If we do put it in the cache, retain it an extra time for the cache.
1099	// Note that we don't bother freeing this result and returning the cached value if the cache was filled, since cached CFNumbers are not guaranteed unique.
1100	// Barrier assures that the number that is placed in the cache is properly formed.
1101	CFNumberType origType = __CFNumberGetType(result);
1102	// Force all cached numbers to have the same type, so that the type does not
1103	// depend on the order and original type in/with which the numbers are created.
1104	// Forcing the type AFTER it was cached would cause a race condition with other
1105	// threads pulling the number object out of the cache and using it.
1106	__CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)kCFNumberSInt32Type);
1107	if (OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)result, (void *volatile *)&__CFNumberCache[valToBeCached - MinCachedInt])) {
1108	    CFRetain(result);
1109	} else {
1110	    // Did not cache the number object, put original type back.
1111	    __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)origType);
1112	}
1113	return result;
1114    }
1115
1116    uint64_t value;
1117    switch (__CFNumberTypeTable[type].canonicalType) {
1118    case kCFNumberSInt8Type:   value = (uint64_t)(int64_t)*(int8_t *)valuePtr; goto smallVal;
1119    case kCFNumberSInt16Type:  value = (uint64_t)(int64_t)*(int16_t *)valuePtr; goto smallVal;
1120    case kCFNumberSInt32Type:  value = (uint64_t)(int64_t)*(int32_t *)valuePtr; goto smallVal;
1121			smallVal: memmove((void *)&result->_pad, &value, 8); break;
1122    case kCFNumberSInt64Type:  memmove((void *)&result->_pad, valuePtr, 8); break;
1123    case kCFNumberSInt128Type: memmove((void *)&result->_pad, valuePtr, 16); break;
1124    case kCFNumberFloat32Type: memmove((void *)&result->_pad, valuePtr, 4); break;
1125    case kCFNumberFloat64Type: memmove((void *)&result->_pad, valuePtr, 8); break;
1126    }
1127//printf("  => %p\n", result);
1128    return result;
1129}
1130
1131CFNumberType CFNumberGetType(CFNumberRef number) {
1132//printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
1133    CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType);
1134    __CFAssertIsNumber(number);
1135    CFNumberType type = __CFNumberGetType(number);
1136    if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public
1137//printf("  => %d\n", type);
1138#if OLD_CRAP_TOO
1139if (! number->__old__) {
1140printf("*** Test skipped in CFNumberGetType for number %p\n", number);
1141} else {
1142CFNumberType t2 = CFNumberGetType_old(number->__old__);
1143if (t2 != type) {
1144CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2, type);  FAIL();
1145}
1146}
1147#endif
1148    return type;
1149}
1150
1151CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) {
1152    CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType);
1153    __CFAssertIsNumber(number);
1154    return __CFNumberGetType(number);
1155}
1156
1157CFIndex CFNumberGetByteSize(CFNumberRef number) {
1158//printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
1159    __CFAssertIsNumber(number);
1160    CFIndex r = 1 << __CFNumberTypeTable[CFNumberGetType(number)].lgByteSize;
1161//printf("  => %d\n", r);
1162#if OLD_CRAP_TOO
1163if (! number->__old__) {
1164printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number);
1165} else {
1166CFIndex r2 = CFNumberGetByteSize_old(number->__old__);
1167if (r2 != r) {
1168CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2, r);  FAIL();
1169}
1170}
1171#endif
1172    return r;
1173}
1174
1175Boolean CFNumberIsFloatType(CFNumberRef number) {
1176//printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1177    __CFAssertIsNumber(number);
1178    Boolean r = __CFNumberTypeTable[CFNumberGetType(number)].floatBit;
1179//printf("  => %d\n", r);
1180#if OLD_CRAP_TOO
1181if (! number->__old__) {
1182printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number);
1183} else {
1184Boolean r2 = CFNumberIsFloatType_old(number->__old__);
1185if (r2 != r) {
1186CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2, r);  FAIL();
1187}
1188}
1189#endif
1190    return r;
1191}
1192
1193Boolean CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
1194//printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1195
1196    CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType);
1197    __CFAssertIsNumber(number);
1198    __CFAssertIsValidNumberType(type);
1199    uint8_t localMemory[128];
1200    Boolean r = __CFNumberGetValueCompat(number, type, valuePtr ? valuePtr : localMemory);
1201//printf("  => %d\n", r);
1202#if OLD_CRAP_TOO
1203if (! number->__old__) {
1204printf("*** Test skipped in CFNumberGetValue for number %p\n", number);
1205} else {
1206    uint8_t localMemory2[128];
1207Boolean r2 = CFNumberGetValue_old(number->__old__, type, localMemory2);
1208if (r2 != r) {
1209CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2, r);  FAIL();
1210}
1211if (0 != memcmp(localMemory2, valuePtr, CFNumberGetByteSize(number))) {
1212CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME"));  FAIL();
1213}
1214}
1215#endif
1216    return r;
1217}
1218
1219static CFComparisonResult CFNumberCompare_new(CFNumberRef number1, CFNumberRef number2, void *context) {
1220    CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number1, compare:(NSNumber *)number2);
1221    CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number2, _reverseCompare:(NSNumber *)number1);
1222    __CFAssertIsNumber(number1);
1223    __CFAssertIsNumber(number2);
1224
1225    CFNumberType type1 = __CFNumberGetType(number1);
1226    CFNumberType type2 = __CFNumberGetType(number2);
1227    // Both numbers are integers
1228    if (!__CFNumberTypeTable[type1].floatBit && !__CFNumberTypeTable[type2].floatBit) {
1229        CFSInt128Struct i1, i2;
1230        __CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
1231        __CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
1232        return cmp128(&i1, &i2);
1233    }
1234    // Both numbers are floats
1235    if (__CFNumberTypeTable[type1].floatBit && __CFNumberTypeTable[type2].floatBit) {
1236	Float64 d1, d2;
1237        __CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
1238        __CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
1239	double s1 = copysign(1.0, d1);
1240	double s2 = copysign(1.0, d2);
1241	if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
1242	if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
1243	if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
1244	// at this point, we know we don't have any NaNs
1245	if (s1 < s2) return kCFCompareLessThan;
1246	if (s2 < s1) return kCFCompareGreaterThan;
1247	// at this point, we know the signs are the same; do not combine these tests
1248	if (d1 < d2) return kCFCompareLessThan;
1249	if (d2 < d1) return kCFCompareGreaterThan;
1250        return kCFCompareEqualTo;
1251    }
1252    // One float, one integer; swap if necessary so number1 is the float
1253    Boolean swapResult = false;
1254    if (__CFNumberTypeTable[type2].floatBit) {
1255        CFNumberRef tmp = number1;
1256	number1 = number2;
1257	number2 = tmp;
1258	swapResult = true;
1259    }
1260    // At large integer values, the precision of double is quite low
1261    // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1262    // If we just used double compare, that would make the 2^73 largest 128-bit
1263    // integers look equal, so we have to use integer comparison when possible.
1264    Float64 d1, d2;
1265    __CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
1266    // if the double value is really big, cannot be equal to integer
1267    // nan d1 will not compare true here
1268    if (d1 < FLOAT_NEGATIVE_2_TO_THE_127) {
1269	return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1270    }
1271    if (FLOAT_POSITIVE_2_TO_THE_127 <= d1) {
1272	return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1273    }
1274    CFSInt128Struct i1, i2;
1275    __CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
1276    __CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
1277    CFComparisonResult res = cmp128(&i1, &i2);
1278    if (kCFCompareEqualTo != res) {
1279	return !swapResult ? res : -res;
1280    }
1281    // now things are equal, but perhaps due to rounding or nan
1282    if (isnan(d1)) {
1283	if (isNeg128(&i2)) {
1284	    return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1285	}
1286	// nan compares less than positive 0 too
1287	return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1288    }
1289    // at this point, we know we don't have NaN
1290    double s1 = copysign(1.0, d1);
1291    double s2 = isNeg128(&i2) ? -1.0 : 1.0;
1292    if (s1 < s2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1293    if (s2 < s1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1294    // at this point, we know the signs are the same; do not combine these tests
1295    __CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
1296    if (d1 < d2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1297    if (d2 < d1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1298    return kCFCompareEqualTo;
1299}
1300
1301CFComparisonResult CFNumberCompare(CFNumberRef number1, CFNumberRef number2, void *context) {
1302//printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1303    CFComparisonResult r = CFNumberCompare_new(number1, number2, context);
1304//printf("  => %d\n", r);
1305#if OLD_CRAP_TOO
1306if (! number1->__old__ || !number2->__old__) {
1307printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1, number2);
1308} else {
1309CFComparisonResult r2 = CFNumberCompare_old(number1->__old__, number2->__old__, context);
1310if (r2 != r) {
1311CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2, r);  FAIL();
1312}
1313}
1314#endif
1315    return r;
1316}
1317
1318#if OLD_CRAP_TOO
1319
1320static const unsigned char __CFNumberCanonicalType[kCFNumberMaxType + 1] = {
1321    0, kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
1322    kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
1323    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
1324};
1325
1326static const unsigned char __CFNumberStorageType[kCFNumberMaxType + 1] = {
1327    0, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
1328    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
1329    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
1330};
1331
1332
1333
1334// Returns the type that is used to store the specified type
1335static CFNumberType __CFNumberGetStorageTypeForType_old(CFNumberType type) {
1336    return __CFNumberStorageType[type];
1337}
1338
1339// Returns the canonical type used to represent the specified type
1340static CFNumberType __CFNumberGetCanonicalTypeForType_old(CFNumberType type) {
1341    return __CFNumberCanonicalType[type];
1342}
1343
1344// Extracts and returns the type out of the CFNumber
1345static CFNumberType __CFNumberGetType_old(struct __CFNumber_old * num) {
1346    return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
1347}
1348
1349// Returns true if the argument type is float or double
1350static Boolean __CFNumberTypeIsFloat_old(CFNumberType type) {
1351    return (type == kCFNumberFloat64Type) || (type == kCFNumberFloat32Type) || (type == kCFNumberDoubleType) || (type == kCFNumberFloatType);
1352}
1353
1354// Returns the number of bytes necessary to store the specified type
1355// Needs to handle all canonical types
1356static CFIndex __CFNumberSizeOfType_old(CFNumberType type) {
1357    switch (type) {
1358        case kCFNumberSInt8Type:        return sizeof(int8_t);
1359        case kCFNumberSInt16Type:       return sizeof(int16_t);
1360        case kCFNumberSInt32Type:       return sizeof(SInt32);
1361        case kCFNumberSInt64Type:       return sizeof(int64_t);
1362        case kCFNumberFloat32Type:      return sizeof(Float32);
1363        case kCFNumberFloat64Type:      return sizeof(Float64);
1364        default:                        printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
1365    }
1366}
1367
1368// Copies an external value of a given type into the appropriate slot in the union (does no type conversion)
1369// Needs to handle all canonical types
1370#define SET_VALUE(valueUnion, type, valuePtr)   \
1371    switch (type) {                             \
1372        case kCFNumberSInt8Type:        (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
1373        case kCFNumberSInt16Type:       (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break;        \
1374        case kCFNumberSInt32Type:       (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
1375        case kCFNumberSInt64Type:       (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break;        \
1376        case kCFNumberFloat32Type:      (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break;       \
1377        case kCFNumberFloat64Type:      (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break;       \
1378        default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
1379    }
1380
1381// Casts the specified value into the specified type and copies it into the provided memory
1382// Needs to handle all canonical types
1383#define GET_VALUE(value, type, resultPtr)       \
1384    switch (type) {                             \
1385        case kCFNumberSInt8Type:        *(int8_t *)(resultPtr) = (int8_t)value; break;  \
1386        case kCFNumberSInt16Type:       *(int16_t *)(resultPtr) = (int16_t)value; break;        \
1387        case kCFNumberSInt32Type:       *(SInt32 *)(resultPtr) = (SInt32)value; break;  \
1388        case kCFNumberSInt64Type:       *(int64_t *)(resultPtr) = (int64_t)value; break;        \
1389        case kCFNumberFloat32Type:      *(Float32 *)(resultPtr) = (Float32)value; break;        \
1390        case kCFNumberFloat64Type:      *(Float64 *)(resultPtr) = (Float64)value; break;        \
1391        default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
1392    }
1393
1394// Extracts the stored type out of the union and copies it in the desired type into the provided memory
1395// Needs to handle all storage types
1396static void __CFNumberGetValue_old(const __CFNumberValue_old *value, CFNumberType numberType, CFNumberType typeToGet, void *valuePtr) {
1397    switch (numberType) {
1398        case kCFNumberSInt32Type:       GET_VALUE(value->valSInt32, typeToGet, valuePtr); break;
1399        case kCFNumberSInt64Type:       GET_VALUE(value->valSInt64, typeToGet, valuePtr); break;
1400        case kCFNumberFloat32Type:      GET_VALUE(value->valFloat32, typeToGet, valuePtr); break;
1401        case kCFNumberFloat64Type:      GET_VALUE(value->valFloat64, typeToGet, valuePtr); break;
1402        default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
1403    }
1404}
1405
1406// Sees if two value union structs have the same value (will do type conversion)
1407static Boolean __CFNumberEqualValue_old(const __CFNumberValue_old *value1, CFNumberType type1, const __CFNumberValue_old *value2, CFNumberType type2) {
1408    if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
1409        Float64 d1, d2;
1410        __CFNumberGetValue_old(value1, type1, kCFNumberFloat64Type, &d1);
1411        __CFNumberGetValue_old(value2, type2, kCFNumberFloat64Type, &d2);
1412            if (isnan(d1) && isnan(d2)) return true;    // Not mathematically sound, but required
1413        return d1 == d2;
1414    } else {
1415        int64_t i1, i2;
1416        __CFNumberGetValue_old(value1, type1, kCFNumberSInt64Type, &i1);
1417        __CFNumberGetValue_old(value2, type2, kCFNumberSInt64Type, &i2);
1418        return i1 == i2;
1419    }
1420}
1421
1422static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2) {
1423    struct __CFNumber_old * number1 = (struct __CFNumber_old *)cf1;
1424    struct __CFNumber_old * number2 = (struct __CFNumber_old *)cf2;
1425    return __CFNumberEqualValue_old(&(number1->value), __CFNumberGetType_old(number1), &(number2->value), __CFNumberGetType_old(number2));
1426}
1427
1428static CFHashCode __CFNumberHash_old(CFTypeRef cf) {
1429    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
1430    switch (__CFNumberGetType_old((struct __CFNumber_old *)cf)) {
1431        case kCFNumberSInt32Type: return _CFHashInt(number->value.valSInt32);
1432        case kCFNumberSInt64Type: return _CFHashDouble((double)(number->value.valSInt64));
1433        case kCFNumberFloat32Type: return _CFHashDouble((double)(number->value.valFloat32));
1434        case kCFNumberFloat64Type: return _CFHashDouble((double)(number->value.valFloat64));
1435        default: printf("*** WARNING default case in __CFNumberHash_old\n");
1436            return 0;
1437    }
1438}
1439
1440#define BUFFER_SIZE 100
1441#define emitChar(ch) \
1442    {if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
1443
1444static void __CFNumberEmitInt64_old(CFMutableStringRef mstr, int64_t value, int32_t width, UniChar pad, bool explicitPlus) {
1445    UniChar stackBuf[BUFFER_SIZE], *buf = stackBuf;
1446    uint64_t uvalue, factor, tmp;
1447    int32_t w;
1448    bool neg;
1449
1450    neg = (value < 0) ? true : false;
1451    uvalue = (neg) ? -value : value;
1452    if (neg || explicitPlus) width--;
1453    width--;
1454    factor = 1;
1455    tmp = uvalue;
1456    while (9 < tmp) {
1457        width--;
1458        factor *= 10;
1459        tmp /= 10;
1460    }
1461    for (w = 0; w < width; w++) emitChar(pad);
1462    if (neg) {
1463        emitChar('-');
1464    } else if (explicitPlus) {
1465        emitChar('+');
1466    }
1467    while (0 < factor) {
1468        UniChar ch = '0' + (UniChar)(uvalue / factor);
1469        uvalue %= factor;
1470        emitChar(ch);
1471        factor /= 10;
1472    }
1473    if (buf > stackBuf) CFStringAppendCharacters(mstr, stackBuf, buf - stackBuf);
1474}
1475
1476static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf) {
1477    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
1478    CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
1479    CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
1480    switch (__CFNumberGetType_old(number)) {
1481    case kCFNumberSInt32Type:
1482        __CFNumberEmitInt64_old(mstr, number->value.valSInt32, 0, ' ', true);
1483        CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt32Type}"));
1484        break;
1485    case kCFNumberSInt64Type:
1486        __CFNumberEmitInt64_old(mstr, number->value.valSInt64, 0, ' ', true);
1487        CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt64Type}"));
1488        break;
1489    case kCFNumberFloat32Type:
1490        // debugging formatting is intentionally more verbose and explicit about the value of the number
1491        if (isnan(number->value.valFloat32)) {
1492            CFStringAppend(mstr, CFSTR("nan"));
1493        } else if (isinf(number->value.valFloat32)) {
1494            CFStringAppend(mstr, (0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
1495        } else if (0.0f == number->value.valFloat32) {
1496            CFStringAppend(mstr, (copysign(1.0, number->value.valFloat32) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1497        } else {
1498            CFStringAppendFormat(mstr, NULL, CFSTR("%+.10f"), number->value.valFloat32);
1499        }
1500        CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat32Type}"));
1501        break;
1502    case kCFNumberFloat64Type:
1503        // debugging formatting is intentionally more verbose and explicit about the value of the number
1504        if (isnan(number->value.valFloat64)) {
1505            CFStringAppend(mstr, CFSTR("nan"));
1506        } else if (isinf(number->value.valFloat64)) {
1507            CFStringAppend(mstr, (0.0 < number->value.valFloat64) ? CFSTR("+infinity") : CFSTR("-infinity"));
1508        } else if (0.0 == number->value.valFloat64) {
1509            CFStringAppend(mstr, (copysign(1.0, number->value.valFloat64) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
1510        } else {
1511            CFStringAppendFormat(mstr, NULL, CFSTR("%+.20f"), number->value.valFloat64);
1512        }
1513        CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat64Type}"));
1514        break;
1515    default:
1516        CFRelease(mstr);
1517        return NULL;
1518    }
1519    return mstr;
1520}
1521
1522// This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
1523
1524CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf) {
1525    double d;
1526    CFNumberGetValue_old((struct __CFNumber_old *)cf, kCFNumberFloat64Type, &d);
1527        if (isnan(d)) {
1528            return (CFStringRef)CFRetain(CFSTR("nan"));
1529        }
1530        if (isinf(d)) {
1531            return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
1532        }
1533        if (0.0 == d) {
1534            return (CFStringRef)CFRetain(CFSTR("0.0"));
1535        }
1536        // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
1537        return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
1538}
1539
1540static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions) {
1541    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
1542    CFMutableStringRef mstr;
1543    int64_t value;
1544    switch (__CFNumberGetType_old(number)) {
1545    case kCFNumberSInt32Type:
1546    case kCFNumberSInt64Type:
1547        value = (__CFNumberGetType_old(number) == kCFNumberSInt32Type) ? number->value.valSInt32 : number->value.valSInt64;
1548        mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
1549        __CFNumberEmitInt64_old(mstr, value, 0, ' ', false);
1550        return mstr;
1551    case kCFNumberFloat32Type:
1552            if (isnan(number->value.valFloat32)) {
1553                return (CFStringRef)CFRetain(CFSTR("nan"));
1554            }
1555            if (isinf(number->value.valFloat32)) {
1556                return (CFStringRef)CFRetain((0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
1557            }
1558            if (0.0f == number->value.valFloat32) {
1559                return (CFStringRef)CFRetain(CFSTR("0.0"));
1560            }
1561            // if %g is used here, need to use FLT_DIG + 2 on Mac OS X, but %f needs +1
1562            return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), FLT_DIG + 2, number->value.valFloat32);
1563    case kCFNumberFloat64Type:
1564        return __CFNumberCopyFormattingDescriptionAsFloat64_old(number);
1565        break;
1566    default:
1567        return NULL;
1568    }
1569}
1570
1571
1572
1573static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
1574    struct __CFNumber_old * num;
1575    CFNumberType equivType, storageType;
1576
1577if (type == 17) {
1578CFSInt128Struct *s = valuePtr;
1579s->high = (int64_t)s->low;
1580type = kCFNumberSInt64Type;
1581}
1582
1583
1584    equivType = __CFNumberGetCanonicalTypeForType_old(type);
1585
1586    storageType = __CFNumberGetStorageTypeForType_old(type);
1587
1588    num = (struct __CFNumber_old *)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, __CFNumberSizeOfType_old(storageType), NULL);
1589    if (NULL == num) {
1590        return NULL;
1591    }
1592    SET_VALUE((__CFNumberValue_old *)&(num->value), equivType, valuePtr);
1593    __CFBitfieldSetValue(((struct __CFNumber_old *)num)->_base._cfinfo[CF_INFO_BITS], 6, 0, (uint8_t)storageType);
1594
1595if (__CFNumberGetType_old(num) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num, storageType);
1596    return num;
1597}
1598
1599static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number) {
1600
1601    return __CFNumberGetType_old(number);
1602}
1603
1604static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number) {
1605    return __CFNumberSizeOfType_old(CFNumberGetType_old(number));
1606}
1607
1608static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number) {
1609    return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number));
1610}
1611
1612static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr) {
1613    uint8_t localMemory[sizeof(__CFNumberValue_old)];
1614    __CFNumberValue_old localValue;
1615    CFNumberType numType;
1616    CFNumberType storageTypeForType;
1617
1618if (type == 17) type = kCFNumberSInt64Type;
1619
1620    storageTypeForType = __CFNumberGetStorageTypeForType_old(type);
1621    type = __CFNumberGetCanonicalTypeForType_old(type);
1622    if (!valuePtr) valuePtr = &localMemory;
1623
1624    numType = __CFNumberGetType_old(number);
1625    __CFNumberGetValue_old((__CFNumberValue_old *)&(number->value), numType, type, valuePtr);
1626
1627    // If the types match, then we're fine!
1628    if (numType == storageTypeForType) return true;
1629
1630    // Test to see if the returned value is intact...
1631    SET_VALUE(&localValue, type, valuePtr);
1632    return __CFNumberEqualValue_old(&localValue, storageTypeForType, &(number->value), numType);
1633}
1634
1635static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context) {
1636    CFNumberType type1, type2;
1637
1638
1639    type1 = __CFNumberGetType_old(number1);
1640    type2 = __CFNumberGetType_old(number2);
1641
1642    if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
1643        Float64 d1, d2;
1644        double s1, s2;
1645        __CFNumberGetValue_old(&(number1->value), type1, kCFNumberFloat64Type, &d1);
1646        __CFNumberGetValue_old(&(number2->value), type2, kCFNumberFloat64Type, &d2);
1647        s1 = copysign(1.0, d1);
1648        s2 = copysign(1.0, d2);
1649        if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
1650        if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
1651        if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
1652        // at this point, we know we don't have any NaNs
1653        if (s1 < s2) return kCFCompareLessThan;
1654        if (s2 < s1) return kCFCompareGreaterThan;
1655        // at this point, we know the signs are the same; do not combine these tests
1656        if (d1 < d2) return kCFCompareLessThan;
1657        if (d2 < d1) return kCFCompareGreaterThan;
1658        return kCFCompareEqualTo;
1659    } else {
1660        int64_t i1, i2;
1661        __CFNumberGetValue_old(&(number1->value), type1, kCFNumberSInt64Type, &i1);
1662        __CFNumberGetValue_old(&(number2->value), type2, kCFNumberSInt64Type, &i2);
1663        return (i1 > i2) ? kCFCompareGreaterThan : ((i1 < i2) ? kCFCompareLessThan : kCFCompareEqualTo);
1664    }
1665}
1666
1667#endif
1668
1669
1670#undef __CFAssertIsBoolean
1671#undef __CFAssertIsNumber
1672#undef __CFAssertIsValidNumberType
1673#undef BITSFORDOUBLENAN
1674#undef BITSFORDOUBLEPOSINF
1675#undef BITSFORDOUBLENEGINF
1676#undef MinCachedInt
1677#undef MaxCachedInt
1678#undef NotToBeCached
1679
1680