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