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