]> git.saurik.com Git - apple/cf.git/blob - CFNumber.c
CF-476.17.tar.gz
[apple/cf.git] / CFNumber.c
1 /*
2 * Copyright (c) 2008 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 /* CFNumber.c
24 Copyright 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Ali Ozer
26 */
27
28 #include <CoreFoundation/CFNumber.h>
29 #include "CFInternal.h"
30 #include "CFPriv.h"
31 #include <math.h>
32 #include <float.h>
33
34 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
35
36 struct __CFBoolean {
37 CFRuntimeBase _base;
38 };
39
40 static struct __CFBoolean __kCFBooleanTrue = {
41 INIT_CFRUNTIME_BASE()
42 };
43 const CFBooleanRef kCFBooleanTrue = &__kCFBooleanTrue;
44
45 static struct __CFBoolean __kCFBooleanFalse = {
46 INIT_CFRUNTIME_BASE()
47 };
48 const CFBooleanRef kCFBooleanFalse = &__kCFBooleanFalse;
49
50 static CFStringRef __CFBooleanCopyDescription(CFTypeRef cf) {
51 CFBooleanRef boolean = (CFBooleanRef)cf;
52 return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBoolean %p [%p]>{value = %s}"), cf, CFGetAllocator(cf), (boolean == kCFBooleanTrue) ? "true" : "false");
53 }
54
55 static CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
56 CFBooleanRef boolean = (CFBooleanRef)cf;
57 return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false"));
58 }
59
60 static void __CFBooleanDeallocate(CFTypeRef cf) {
61 CFAssert(false, __kCFLogAssertion, "Deallocated CFBoolean!");
62 }
63
64 static CFTypeID __kCFBooleanTypeID = _kCFRuntimeNotATypeID;
65
66 static const CFRuntimeClass __CFBooleanClass = {
67 0,
68 "CFBoolean",
69 NULL, // init
70 NULL, // copy
71 __CFBooleanDeallocate,
72 NULL,
73 NULL,
74 __CFBooleanCopyFormattingDescription,
75 __CFBooleanCopyDescription
76 };
77
78 __private_extern__ void __CFBooleanInitialize(void) {
79 __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass);
80 _CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue, __kCFBooleanTypeID);
81 __kCFBooleanTrue._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID);
82 _CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse, __kCFBooleanTypeID);
83 __kCFBooleanFalse._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID);
84 }
85
86 CFTypeID CFBooleanGetTypeID(void) {
87 return __kCFBooleanTypeID;
88 }
89
90 Boolean CFBooleanGetValue(CFBooleanRef boolean) {
91 CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID, Boolean, boolean, "boolValue");
92 return (boolean == kCFBooleanTrue) ? true : false;
93 }
94
95
96 /*** CFNumber ***/
97
98 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
99 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
100
101 /* The IEEE bit patterns... Also have:
102 0x7f800000 float +Inf
103 0x7fc00000 float NaN
104 0xff800000 float -Inf
105 */
106 #define BITSFORDOUBLENAN ((uint64_t)0x7ff8000000000000ULL)
107 #define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
108 #define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
109
110 #if DEPLOYMENT_TARGET_MACOSX
111 #define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
112 #define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
113 #define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
114 #endif
115
116 typedef struct { // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
117 int64_t high;
118 uint64_t low;
119 } CFSInt128Struct;
120
121 enum {
122 kCFNumberSInt128Type = 17
123 };
124
125 static uint8_t isNeg128(const CFSInt128Struct *in) {
126 return in->high < 0;
127 }
128
129 static CFComparisonResult cmp128(const CFSInt128Struct *in1, const CFSInt128Struct *in2) {
130 if (in1->high < in2->high) return kCFCompareLessThan;
131 if (in1->high > in2->high) return kCFCompareGreaterThan;
132 if (in1->low < in2->low) return kCFCompareLessThan;
133 if (in1->low > in2->low) return kCFCompareGreaterThan;
134 return kCFCompareEqualTo;
135 }
136
137 // allows out to be the same as in1 or in2
138 static void add128(CFSInt128Struct *out, CFSInt128Struct *in1, CFSInt128Struct *in2) {
139 CFSInt128Struct tmp;
140 tmp.low = in1->low + in2->low;
141 tmp.high = in1->high + in2->high;
142 if (UINT64_MAX - in1->low < in2->low) {
143 tmp.high++;
144 }
145 *out = tmp;
146 }
147
148 // allows out to be the same as in
149 static void neg128(CFSInt128Struct *out, CFSInt128Struct *in) {
150 uint64_t tmplow = ~in->low;
151 out->low = tmplow + 1;
152 out->high = ~in->high;
153 if (UINT64_MAX == tmplow) {
154 out->high++;
155 }
156 }
157
158 static const CFSInt128Struct powersOf10[] = {
159 { 0x4B3B4CA85A86C47ALL, 0x098A224000000000ULL },
160 { 0x0785EE10D5DA46D9LL, 0x00F436A000000000ULL },
161 { 0x00C097CE7BC90715LL, 0xB34B9F1000000000ULL },
162 { 0x0013426172C74D82LL, 0x2B878FE800000000ULL },
163 { 0x0001ED09BEAD87C0LL, 0x378D8E6400000000ULL },
164 { 0x0000314DC6448D93LL, 0x38C15B0A00000000ULL },
165 { 0x000004EE2D6D415BLL, 0x85ACEF8100000000ULL },
166 { 0x0000007E37BE2022LL, 0xC0914B2680000000ULL },
167 { 0x0000000C9F2C9CD0LL, 0x4674EDEA40000000ULL },
168 { 0x00000001431E0FAELL, 0x6D7217CAA0000000ULL },
169 { 0x00000000204FCE5ELL, 0x3E25026110000000ULL },
170 { 0x00000000033B2E3CLL, 0x9FD0803CE8000000ULL },
171 { 0x000000000052B7D2LL, 0xDCC80CD2E4000000ULL },
172 { 0x0000000000084595LL, 0x161401484A000000ULL },
173 { 0x000000000000D3C2LL, 0x1BCECCEDA1000000ULL },
174 { 0x000000000000152DLL, 0x02C7E14AF6800000ULL },
175 { 0x000000000000021ELL, 0x19E0C9BAB2400000ULL },
176 { 0x0000000000000036LL, 0x35C9ADC5DEA00000ULL },
177 { 0x0000000000000005LL, 0x6BC75E2D63100000ULL },
178 { 0x0000000000000000LL, 0x8AC7230489E80000ULL },
179 { 0x0000000000000000LL, 0x0DE0B6B3A7640000ULL },
180 { 0x0000000000000000LL, 0x016345785D8A0000ULL },
181 { 0x0000000000000000LL, 0x002386F26FC10000ULL },
182 { 0x0000000000000000LL, 0x00038D7EA4C68000ULL },
183 { 0x0000000000000000LL, 0x00005AF3107A4000ULL },
184 { 0x0000000000000000LL, 0x000009184E72A000ULL },
185 { 0x0000000000000000LL, 0x000000E8D4A51000ULL },
186 { 0x0000000000000000LL, 0x000000174876E800ULL },
187 { 0x0000000000000000LL, 0x00000002540BE400ULL },
188 { 0x0000000000000000LL, 0x000000003B9ACA00ULL },
189 { 0x0000000000000000LL, 0x0000000005F5E100ULL },
190 { 0x0000000000000000LL, 0x0000000000989680ULL },
191 { 0x0000000000000000LL, 0x00000000000F4240ULL },
192 { 0x0000000000000000LL, 0x00000000000186A0ULL },
193 { 0x0000000000000000LL, 0x0000000000002710ULL },
194 { 0x0000000000000000LL, 0x00000000000003E8ULL },
195 { 0x0000000000000000LL, 0x0000000000000064ULL },
196 { 0x0000000000000000LL, 0x000000000000000AULL },
197 { 0x0000000000000000LL, 0x0000000000000001ULL },
198 };
199
200 static const CFSInt128Struct neg_powersOf10[] = {
201 { 0xB4C4B357A5793B85LL, 0xF675DDC000000000ULL },
202 { 0xF87A11EF2A25B926LL, 0xFF0BC96000000000ULL },
203 { 0xFF3F68318436F8EALL, 0x4CB460F000000000ULL },
204 { 0xFFECBD9E8D38B27DLL, 0xD478701800000000ULL },
205 { 0xFFFE12F64152783FLL, 0xC872719C00000000ULL },
206 { 0xFFFFCEB239BB726CLL, 0xC73EA4F600000000ULL },
207 { 0xFFFFFB11D292BEA4LL, 0x7A53107F00000000ULL },
208 { 0xFFFFFF81C841DFDDLL, 0x3F6EB4D980000000ULL },
209 { 0xFFFFFFF360D3632FLL, 0xB98B1215C0000000ULL },
210 { 0xFFFFFFFEBCE1F051LL, 0x928DE83560000000ULL },
211 { 0xFFFFFFFFDFB031A1LL, 0xC1DAFD9EF0000000ULL },
212 { 0xFFFFFFFFFCC4D1C3LL, 0x602F7FC318000000ULL },
213 { 0xFFFFFFFFFFAD482DLL, 0x2337F32D1C000000ULL },
214 { 0xFFFFFFFFFFF7BA6ALL, 0xE9EBFEB7B6000000ULL },
215 { 0xFFFFFFFFFFFF2C3DLL, 0xE43133125F000000ULL },
216 { 0xFFFFFFFFFFFFEAD2LL, 0xFD381EB509800000ULL },
217 { 0xFFFFFFFFFFFFFDE1LL, 0xE61F36454DC00000ULL },
218 { 0xFFFFFFFFFFFFFFC9LL, 0xCA36523A21600000ULL },
219 { 0xFFFFFFFFFFFFFFFALL, 0x9438A1D29CF00000ULL },
220 { 0xFFFFFFFFFFFFFFFFLL, 0x7538DCFB76180000ULL },
221 { 0xFFFFFFFFFFFFFFFFLL, 0xF21F494C589C0000ULL },
222 { 0xFFFFFFFFFFFFFFFFLL, 0xFE9CBA87A2760000ULL },
223 { 0xFFFFFFFFFFFFFFFFLL, 0xFFDC790D903F0000ULL },
224 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFC72815B398000ULL },
225 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFA50CEF85C000ULL },
226 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFF6E7B18D6000ULL },
227 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFF172B5AF000ULL },
228 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFE8B7891800ULL },
229 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFDABF41C00ULL },
230 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFC4653600ULL },
231 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFA0A1F00ULL },
232 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFF676980ULL },
233 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFF0BDC0ULL },
234 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFE7960ULL },
235 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFD8F0ULL },
236 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFC18ULL },
237 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFF9CULL },
238 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFF6ULL },
239 { 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFULL },
240 };
241
242 static void emit128(char *buffer, const CFSInt128Struct *in, Boolean forcePlus) {
243 CFSInt128Struct tmp = *in;
244 if (isNeg128(&tmp)) {
245 neg128(&tmp, &tmp);
246 *buffer++ = '-';
247 } else if (forcePlus) {
248 *buffer++ = '+';
249 }
250 Boolean doneOne = false;
251 int idx;
252 for (idx = 0; idx < sizeof(powersOf10) / sizeof(powersOf10[0]); idx++) {
253 int count = 0;
254 while (cmp128(&powersOf10[idx], &tmp) <= 0) {
255 add128(&tmp, &tmp, (CFSInt128Struct *)&neg_powersOf10[idx]);
256 count++;
257 }
258 if (0 != count || doneOne) {
259 *buffer++ = '0' + count;
260 doneOne = true;
261 }
262 }
263 if (!doneOne) {
264 *buffer++ = '0';
265 }
266 *buffer = '\0';
267 }
268
269 static void cvtSInt128ToFloat64(Float64 *out, const CFSInt128Struct *in) {
270 // switching to a positive number results in better accuracy
271 // for negative numbers close to zero, because the multiply
272 // of -1 by 2^64 (scaling the Float64 high) is avoided
273 Boolean wasNeg = false;
274 CFSInt128Struct tmp = *in;
275 if (isNeg128(&tmp)) {
276 neg128(&tmp, &tmp);
277 wasNeg = true;
278 }
279 Float64 d = (Float64)tmp.high * FLOAT_POSITIVE_2_TO_THE_64 + (Float64)tmp.low;
280 if (wasNeg) d = -d;
281 *out = d;
282 }
283
284 static void cvtFloat64ToSInt128(CFSInt128Struct *out, const Float64 *in) {
285 CFSInt128Struct i;
286 Float64 d = *in;
287 if (d < FLOAT_NEGATIVE_2_TO_THE_127) {
288 i.high = 0x8000000000000000LL;
289 i.low = 0x0000000000000000ULL;
290 *out = i;
291 return;
292 }
293 if (FLOAT_POSITIVE_2_TO_THE_127<= d) {
294 i.high = 0x7fffffffffffffffLL;
295 i.low = 0xffffffffffffffffULL;
296 *out = i;
297 return;
298 }
299 Float64 t = floor(d / FLOAT_POSITIVE_2_TO_THE_64);
300 i.high = (int64_t)t;
301 i.low = (uint64_t)(d - t * FLOAT_POSITIVE_2_TO_THE_64);
302 *out = i;
303 }
304
305 struct __CFNumber {
306 CFRuntimeBase _base;
307 uint64_t _pad; // need this space here for the constant objects
308 /* 0 or 8 more bytes allocated here */
309 };
310
311 /* Seven bits in base:
312 Bits 6..5: unused
313 Bits 4..0: CFNumber type
314 */
315
316 static struct __CFNumber __kCFNumberNaN = {
317 INIT_CFRUNTIME_BASE(), 0ULL
318 };
319 const CFNumberRef kCFNumberNaN = &__kCFNumberNaN;
320
321 static struct __CFNumber __kCFNumberNegativeInfinity = {
322 INIT_CFRUNTIME_BASE(), 0ULL
323 };
324 const CFNumberRef kCFNumberNegativeInfinity = &__kCFNumberNegativeInfinity;
325
326 static struct __CFNumber __kCFNumberPositiveInfinity = {
327 INIT_CFRUNTIME_BASE(), 0ULL
328 };
329 const CFNumberRef kCFNumberPositiveInfinity = &__kCFNumberPositiveInfinity;
330
331 static const struct {
332 uint16_t canonicalType:5; // canonical fixed-width type
333 uint16_t floatBit:1; // is float
334 uint16_t storageBit:1; // storage size (0: (float ? 4 : 8), 1: (float ? 8 : 16) bits)
335 uint16_t lgByteSize:3; // base-2 log byte size of public type
336 uint16_t unused:6;
337 } __CFNumberTypeTable[] = {
338 /* 0 */ {0, 0, 0, 0},
339
340 /* kCFNumberSInt8Type */ {kCFNumberSInt8Type, 0, 0, 0, 0},
341 /* kCFNumberSInt16Type */ {kCFNumberSInt16Type, 0, 0, 1, 0},
342 /* kCFNumberSInt32Type */ {kCFNumberSInt32Type, 0, 0, 2, 0},
343 /* kCFNumberSInt64Type */ {kCFNumberSInt64Type, 0, 0, 3, 0},
344 /* kCFNumberFloat32Type */ {kCFNumberFloat32Type, 1, 0, 2, 0},
345 /* kCFNumberFloat64Type */ {kCFNumberFloat64Type, 1, 1, 3, 0},
346
347 /* kCFNumberCharType */ {kCFNumberSInt8Type, 0, 0, 0, 0},
348 /* kCFNumberShortType */ {kCFNumberSInt16Type, 0, 0, 1, 0},
349 /* kCFNumberIntType */ {kCFNumberSInt32Type, 0, 0, 2, 0},
350 #if __LP64__
351 /* kCFNumberLongType */ {kCFNumberSInt64Type, 0, 0, 3, 0},
352 #else
353 /* kCFNumberLongType */ {kCFNumberSInt32Type, 0, 0, 2, 0},
354 #endif
355 /* kCFNumberLongLongType */ {kCFNumberSInt64Type, 0, 0, 3, 0},
356 /* kCFNumberFloatType */ {kCFNumberFloat32Type, 1, 0, 2, 0},
357 /* kCFNumberDoubleType */ {kCFNumberFloat64Type, 1, 1, 3, 0},
358
359 #if __LP64__
360 /* kCFNumberCFIndexType */ {kCFNumberSInt64Type, 0, 0, 3, 0},
361 /* kCFNumberNSIntegerType */ {kCFNumberSInt64Type, 0, 0, 3, 0},
362 /* kCFNumberCGFloatType */ {kCFNumberFloat64Type, 1, 1, 3, 0},
363 #else
364 /* kCFNumberCFIndexType */ {kCFNumberSInt32Type, 0, 0, 2, 0},
365 /* kCFNumberNSIntegerType */ {kCFNumberSInt32Type, 0, 0, 2, 0},
366 /* kCFNumberCGFloatType */ {kCFNumberFloat32Type, 1, 0, 2, 0},
367 #endif
368
369 /* kCFNumberSInt128Type */ {kCFNumberSInt128Type, 0, 1, 4, 0},
370 };
371
372 CF_INLINE CFNumberType __CFNumberGetType(CFNumberRef num) {
373 return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
374 }
375
376 #define CVT(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
377 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
378 DST_TYPE dv = (sv < DST_MIN) ? (DST_TYPE)DST_MIN : (DST_TYPE)(((DST_MAX < sv) ? DST_MAX : sv)); \
379 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
380 SRC_TYPE vv = (SRC_TYPE)dv; return (vv == sv); \
381 } while (0)
382
383 #define CVT128ToInt(SRC_TYPE, DST_TYPE, DST_MIN, DST_MAX) do { \
384 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
385 DST_TYPE dv; Boolean noLoss = false; \
386 if (0 < sv.high || (0 == sv.high && (int64_t)DST_MAX < sv.low)) { \
387 dv = DST_MAX; \
388 } else if (sv.high < -1 || (-1 == sv.high && sv.low < (int64_t)DST_MIN)) { \
389 dv = DST_MIN; \
390 } else { \
391 dv = (DST_TYPE)sv.low; \
392 noLoss = true; \
393 } \
394 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
395 return noLoss; \
396 } while (0)
397
398 // returns false if the output value is not the same as the number's value, which
399 // can occur due to accuracy loss and the value not being within the target range
400 static Boolean __CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
401 type = __CFNumberTypeTable[type].canonicalType;
402 CFNumberType ntype = __CFNumberGetType(number);
403 const void *data = &(number->_pad);
404 switch (type) {
405 case kCFNumberSInt8Type:
406 if (__CFNumberTypeTable[ntype].floatBit) {
407 if (0 == __CFNumberTypeTable[ntype].storageBit) {
408 CVT(Float32, int8_t, INT8_MIN, INT8_MAX);
409 } else {
410 CVT(Float64, int8_t, INT8_MIN, INT8_MAX);
411 }
412 } else {
413 if (0 == __CFNumberTypeTable[ntype].storageBit) {
414 CVT(int64_t, int8_t, INT8_MIN, INT8_MAX);
415 } else {
416 CVT128ToInt(CFSInt128Struct, int8_t, INT8_MIN, INT8_MAX);
417 }
418 }
419 return true;
420 case kCFNumberSInt16Type:
421 if (__CFNumberTypeTable[ntype].floatBit) {
422 if (0 == __CFNumberTypeTable[ntype].storageBit) {
423 CVT(Float32, int16_t, INT16_MIN, INT16_MAX);
424 } else {
425 CVT(Float64, int16_t, INT16_MIN, INT16_MAX);
426 }
427 } else {
428 if (0 == __CFNumberTypeTable[ntype].storageBit) {
429 CVT(int64_t, int16_t, INT16_MIN, INT16_MAX);
430 } else {
431 CVT128ToInt(CFSInt128Struct, int16_t, INT16_MIN, INT16_MAX);
432 }
433 }
434 return true;
435 case kCFNumberSInt32Type:
436 if (__CFNumberTypeTable[ntype].floatBit) {
437 if (0 == __CFNumberTypeTable[ntype].storageBit) {
438 CVT(Float32, int32_t, INT32_MIN, INT32_MAX);
439 } else {
440 CVT(Float64, int32_t, INT32_MIN, INT32_MAX);
441 }
442 } else {
443 if (0 == __CFNumberTypeTable[ntype].storageBit) {
444 CVT(int64_t, int32_t, INT32_MIN, INT32_MAX);
445 } else {
446 CVT128ToInt(CFSInt128Struct, int32_t, INT32_MIN, INT32_MAX);
447 }
448 }
449 return true;
450 case kCFNumberSInt64Type:
451 if (__CFNumberTypeTable[ntype].floatBit) {
452 if (0 == __CFNumberTypeTable[ntype].storageBit) {
453 CVT(Float32, int64_t, INT64_MIN, INT64_MAX);
454 } else {
455 CVT(Float64, int64_t, INT64_MIN, INT64_MAX);
456 }
457 } else {
458 if (0 == __CFNumberTypeTable[ntype].storageBit) {
459 memmove(valuePtr, data, 8);
460 } else {
461 CVT128ToInt(CFSInt128Struct, int64_t, INT64_MIN, INT64_MAX);
462 }
463 }
464 return true;
465 case kCFNumberSInt128Type:
466 if (__CFNumberTypeTable[ntype].floatBit) {
467 if (0 == __CFNumberTypeTable[ntype].storageBit) {
468 Float32 f;
469 memmove(&f, data, 4);
470 Float64 d = f;
471 CFSInt128Struct i;
472 cvtFloat64ToSInt128(&i, &d);
473 memmove(valuePtr, &i, 16);
474 Float64 d2;
475 cvtSInt128ToFloat64(&d2, &i);
476 Float32 f2 = (Float32)d2;
477 return (f2 == f);
478 } else {
479 Float64 d;
480 memmove(&d, data, 8);
481 CFSInt128Struct i;
482 cvtFloat64ToSInt128(&i, &d);
483 memmove(valuePtr, &i, 16);
484 Float64 d2;
485 cvtSInt128ToFloat64(&d2, &i);
486 return (d2 == d);
487 }
488 } else {
489 if (0 == __CFNumberTypeTable[ntype].storageBit) {
490 int64_t j;
491 memmove(&j, data, 8);
492 CFSInt128Struct i;
493 i.low = j;
494 i.high = (j < 0) ? -1LL : 0LL;
495 memmove(valuePtr, &i, 16);
496 } else {
497 memmove(valuePtr, data, 16);
498 }
499 }
500 return true;
501 case kCFNumberFloat32Type:
502 if (__CFNumberTypeTable[ntype].floatBit) {
503 if (0 == __CFNumberTypeTable[ntype].storageBit) {
504 memmove(valuePtr, data, 4);
505 } else {
506 double d;
507 memmove(&d, data, 8);
508 if (isnan(d)) {
509 uint32_t l = 0x7fc00000;
510 memmove(valuePtr, &l, 4);
511 return true;
512 } else if (isinf(d)) {
513 uint32_t l = 0x7f800000;
514 if (d < 0.0) l += 0x80000000UL;
515 memmove(valuePtr, &l, 4);
516 return true;
517 }
518 CVT(Float64, Float32, -FLT_MAX, FLT_MAX);
519 }
520 } else {
521 if (0 == __CFNumberTypeTable[ntype].storageBit) {
522 CVT(int64_t, Float32, -FLT_MAX, FLT_MAX);
523 } else {
524 CFSInt128Struct i;
525 memmove(&i, data, 16);
526 Float64 d;
527 cvtSInt128ToFloat64(&d, &i);
528 Float32 f = (Float32)d;
529 memmove(valuePtr, &f, 4);
530 d = f;
531 CFSInt128Struct i2;
532 cvtFloat64ToSInt128(&i2, &d);
533 return cmp128(&i2, &i) == kCFCompareEqualTo;
534 }
535 }
536 return true;
537 case kCFNumberFloat64Type:
538 if (__CFNumberTypeTable[ntype].floatBit) {
539 if (0 == __CFNumberTypeTable[ntype].storageBit) {
540 float f;
541 memmove(&f, data, 4);
542 if (isnan(f)) {
543 uint64_t l = BITSFORDOUBLENAN;
544 memmove(valuePtr, &l, 8);
545 return true;
546 } else if (isinf(f)) {
547 uint64_t l = BITSFORDOUBLEPOSINF;
548 if (f < 0.0) l += 0x8000000000000000ULL;
549 memmove(valuePtr, &l, 8);
550 return true;
551 }
552 CVT(Float32, Float64, -DBL_MAX, DBL_MAX);
553 } else {
554 memmove(valuePtr, data, 8);
555 }
556 } else {
557 if (0 == __CFNumberTypeTable[ntype].storageBit) {
558 CVT(int64_t, Float64, -DBL_MAX, DBL_MAX);
559 } else {
560 CFSInt128Struct i;
561 memmove(&i, data, 16);
562 Float64 d;
563 cvtSInt128ToFloat64(&d, &i);
564 memmove(valuePtr, &d, 8);
565 CFSInt128Struct i2;
566 cvtFloat64ToSInt128(&i2, &d);
567 return cmp128(&i2, &i) == kCFCompareEqualTo;
568 }
569 }
570 return true;
571 }
572 return false;
573 }
574
575 #define CVT_COMPAT(SRC_TYPE, DST_TYPE, FT) do { \
576 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
577 DST_TYPE dv = (DST_TYPE)(sv); \
578 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
579 SRC_TYPE vv = (SRC_TYPE)dv; return (FT) || (vv == sv); \
580 } while (0)
581
582 #define CVT128ToInt_COMPAT(SRC_TYPE, DST_TYPE) do { \
583 SRC_TYPE sv; memmove(&sv, data, sizeof(SRC_TYPE)); \
584 DST_TYPE dv; dv = (DST_TYPE)sv.low; \
585 memmove(valuePtr, &dv, sizeof(DST_TYPE)); \
586 uint64_t vv = (uint64_t)dv; return (vv == sv.low); \
587 } while (0)
588
589 // this has the old cast-style behavior
590 static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, void *valuePtr) {
591 type = __CFNumberTypeTable[type].canonicalType;
592 CFNumberType ntype = __CFNumberGetType(number);
593 const void *data = &(number->_pad);
594 switch (type) {
595 case kCFNumberSInt8Type:
596 if (__CFNumberTypeTable[ntype].floatBit) {
597 if (0 == __CFNumberTypeTable[ntype].storageBit) {
598 CVT_COMPAT(Float32, int8_t, 0);
599 } else {
600 CVT_COMPAT(Float64, int8_t, 0);
601 }
602 } else {
603 if (0 == __CFNumberTypeTable[ntype].storageBit) {
604 CVT_COMPAT(int64_t, int8_t, 1);
605 } else {
606 CVT128ToInt_COMPAT(CFSInt128Struct, int8_t);
607 }
608 }
609 return true;
610 case kCFNumberSInt16Type:
611 if (__CFNumberTypeTable[ntype].floatBit) {
612 if (0 == __CFNumberTypeTable[ntype].storageBit) {
613 CVT_COMPAT(Float32, int16_t, 0);
614 } else {
615 CVT_COMPAT(Float64, int16_t, 0);
616 }
617 } else {
618 if (0 == __CFNumberTypeTable[ntype].storageBit) {
619 CVT_COMPAT(int64_t, int16_t, 1);
620 } else {
621 CVT128ToInt_COMPAT(CFSInt128Struct, int16_t);
622 }
623 }
624 return true;
625 case kCFNumberSInt32Type:
626 if (__CFNumberTypeTable[ntype].floatBit) {
627 if (0 == __CFNumberTypeTable[ntype].storageBit) {
628 CVT_COMPAT(Float32, int32_t, 0);
629 } else {
630 CVT_COMPAT(Float64, int32_t, 0);
631 }
632 } else {
633 if (0 == __CFNumberTypeTable[ntype].storageBit) {
634 CVT_COMPAT(int64_t, int32_t, 0);
635 } else {
636 CVT128ToInt_COMPAT(CFSInt128Struct, int32_t);
637 }
638 }
639 return true;
640 case kCFNumberSInt64Type:
641 if (__CFNumberTypeTable[ntype].floatBit) {
642 if (0 == __CFNumberTypeTable[ntype].storageBit) {
643 CVT_COMPAT(Float32, int64_t, 0);
644 } else {
645 CVT_COMPAT(Float64, int64_t, 0);
646 }
647 } else {
648 if (0 == __CFNumberTypeTable[ntype].storageBit) {
649 CVT_COMPAT(int64_t, int64_t, 0);
650 } else {
651 CVT128ToInt_COMPAT(CFSInt128Struct, int64_t);
652 }
653 }
654 return true;
655 case kCFNumberSInt128Type:
656 if (__CFNumberTypeTable[ntype].floatBit) {
657 if (0 == __CFNumberTypeTable[ntype].storageBit) {
658 Float32 f;
659 memmove(&f, data, 4);
660 Float64 d = f;
661 CFSInt128Struct i;
662 cvtFloat64ToSInt128(&i, &d);
663 memmove(valuePtr, &i, 16);
664 Float64 d2;
665 cvtSInt128ToFloat64(&d2, &i);
666 Float32 f2 = (Float32)d2;
667 return (f2 == f);
668 } else {
669 Float64 d;
670 memmove(&d, data, 8);
671 CFSInt128Struct i;
672 cvtFloat64ToSInt128(&i, &d);
673 memmove(valuePtr, &i, 16);
674 Float64 d2;
675 cvtSInt128ToFloat64(&d2, &i);
676 return (d2 == d);
677 }
678 } else {
679 if (0 == __CFNumberTypeTable[ntype].storageBit) {
680 int64_t j;
681 memmove(&j, data, 8);
682 CFSInt128Struct i;
683 i.low = j;
684 i.high = (j < 0) ? -1LL : 0LL;
685 memmove(valuePtr, &i, 16);
686 } else {
687 memmove(valuePtr, data, 16);
688 }
689 }
690 return true;
691 case kCFNumberFloat32Type:
692 if (__CFNumberTypeTable[ntype].floatBit) {
693 if (0 == __CFNumberTypeTable[ntype].storageBit) {
694 memmove(valuePtr, data, 4);
695 } else {
696 CVT_COMPAT(Float64, Float32, 0);
697 }
698 } else {
699 if (0 == __CFNumberTypeTable[ntype].storageBit) {
700 CVT_COMPAT(int64_t, Float32, 0);
701 } else {
702 CFSInt128Struct i;
703 memmove(&i, data, 16);
704 Float64 d;
705 cvtSInt128ToFloat64(&d, &i);
706 Float32 f = (Float32)d;
707 memmove(valuePtr, &f, 4);
708 d = f;
709 CFSInt128Struct i2;
710 cvtFloat64ToSInt128(&i2, &d);
711 return cmp128(&i2, &i) == kCFCompareEqualTo;
712 }
713 }
714 return true;
715 case kCFNumberFloat64Type:
716 if (__CFNumberTypeTable[ntype].floatBit) {
717 if (0 == __CFNumberTypeTable[ntype].storageBit) {
718 CVT_COMPAT(Float32, Float64, 0);
719 } else {
720 memmove(valuePtr, data, 8);
721 }
722 } else {
723 if (0 == __CFNumberTypeTable[ntype].storageBit) {
724 CVT_COMPAT(int64_t, Float64, 0);
725 } else {
726 CFSInt128Struct i;
727 memmove(&i, data, 16);
728 Float64 d;
729 cvtSInt128ToFloat64(&d, &i);
730 memmove(valuePtr, &d, 8);
731 CFSInt128Struct i2;
732 cvtFloat64ToSInt128(&i2, &d);
733 return cmp128(&i2, &i) == kCFCompareEqualTo;
734 }
735 }
736 return true;
737 }
738 return false;
739 }
740
741 static CFStringRef __CFNumberCopyDescription(CFTypeRef cf) {
742 CFNumberRef number = (CFNumberRef)cf;
743 CFNumberType type = __CFNumberGetType(number);
744 CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
745 CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
746 if (__CFNumberTypeTable[type].floatBit) {
747 Float64 d;
748 __CFNumberGetValue(number, kCFNumberFloat64Type, &d);
749 if (isnan(d)) {
750 CFStringAppend(mstr, CFSTR("nan"));
751 } else if (isinf(d)) {
752 CFStringAppend(mstr, (0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
753 } else if (0.0 == d) {
754 CFStringAppend(mstr, (copysign(1.0, d) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
755 } else {
756 CFStringAppendFormat(mstr, NULL, CFSTR("%+.*f"), (__CFNumberTypeTable[type].storageBit ? 20 : 10), d);
757 }
758 const char *typeName = "unknown float";
759 switch (type) {
760 case kCFNumberFloat32Type: typeName = "kCFNumberFloat32Type"; break;
761 case kCFNumberFloat64Type: typeName = "kCFNumberFloat64Type"; break;
762 }
763 CFStringAppendFormat(mstr, NULL, CFSTR(", type = %s}"), typeName);
764 } else {
765 CFSInt128Struct i;
766 __CFNumberGetValue(number, kCFNumberSInt128Type, &i);
767 char buffer[128];
768 emit128(buffer, &i, true);
769 const char *typeName = "unknown integer";
770 switch (type) {
771 case kCFNumberSInt8Type: typeName = "kCFNumberSInt8Type"; break;
772 case kCFNumberSInt16Type: typeName = "kCFNumberSInt16Type"; break;
773 case kCFNumberSInt32Type: typeName = "kCFNumberSInt32Type"; break;
774 case kCFNumberSInt64Type: typeName = "kCFNumberSInt64Type"; break;
775 case kCFNumberSInt128Type: typeName = "kCFNumberSInt128Type"; break;
776 }
777 CFStringAppendFormat(mstr, NULL, CFSTR("%s, type = %s}"), buffer, typeName);
778 }
779 return mstr;
780 }
781
782 // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
783
784 static CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_new(CFTypeRef cf) {
785 Float64 d;
786 CFNumberGetValue((CFNumberRef)cf, kCFNumberFloat64Type, &d);
787 if (isnan(d)) {
788 return (CFStringRef)CFRetain(CFSTR("nan"));
789 }
790 if (isinf(d)) {
791 return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
792 }
793 if (0.0 == d) {
794 return (CFStringRef)CFRetain(CFSTR("0.0"));
795 }
796 // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
797 return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
798 }
799
800 __private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) {
801 CFStringRef result = __CFNumberCopyFormattingDescriptionAsFloat64_new(cf);
802 return result;
803 }
804
805 static CFStringRef __CFNumberCopyFormattingDescription_new(CFTypeRef cf, CFDictionaryRef formatOptions) {
806 CFNumberRef number = (CFNumberRef)cf;
807 CFNumberType type = __CFNumberGetType(number);
808 if (__CFNumberTypeTable[type].floatBit) {
809 return __CFNumberCopyFormattingDescriptionAsFloat64(number);
810 }
811 CFSInt128Struct i;
812 __CFNumberGetValue(number, kCFNumberSInt128Type, &i);
813 char buffer[128];
814 emit128(buffer, &i, false);
815 return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%s"), buffer);
816 }
817
818 static CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
819 CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions);
820 return result;
821 }
822
823
824 static Boolean __CFNumberEqual(CFTypeRef cf1, CFTypeRef cf2) {
825 Boolean b = CFNumberCompare((CFNumberRef)cf1, (CFNumberRef)cf2, 0) == kCFCompareEqualTo;
826 return b;
827 }
828
829 static CFHashCode __CFNumberHash(CFTypeRef cf) {
830 CFHashCode h;
831 CFNumberRef number = (CFNumberRef)cf;
832 switch (__CFNumberGetType(number)) {
833 case kCFNumberSInt8Type:
834 case kCFNumberSInt16Type:
835 case kCFNumberSInt32Type: {
836 SInt32 i;
837 __CFNumberGetValue(number, kCFNumberSInt32Type, &i);
838 h = _CFHashInt(i);
839 break;
840 }
841 default: {
842 Float64 d;
843 __CFNumberGetValue(number, kCFNumberFloat64Type, &d);
844 h = _CFHashDouble((double)d);
845 break;
846 }
847 }
848 return h;
849 }
850
851 static CFTypeID __kCFNumberTypeID = _kCFRuntimeNotATypeID;
852
853 static const CFRuntimeClass __CFNumberClass = {
854 0,
855 "CFNumber",
856 NULL, // init
857 NULL, // copy
858 NULL,
859 __CFNumberEqual,
860 __CFNumberHash,
861 __CFNumberCopyFormattingDescription,
862 __CFNumberCopyDescription
863 };
864
865 __private_extern__ void __CFNumberInitialize(void) {
866 __kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass);
867
868 _CFRuntimeSetInstanceTypeID(&__kCFNumberNaN, __kCFNumberTypeID);
869 __kCFNumberNaN._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
870 __CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
871 __kCFNumberNaN._pad = BITSFORDOUBLENAN;
872
873 _CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity, __kCFNumberTypeID);
874 __kCFNumberNegativeInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
875 __CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
876 __kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF;
877
878 _CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity, __kCFNumberTypeID);
879 __kCFNumberPositiveInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID);
880 __CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
881 __kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF;
882 }
883
884 CFTypeID CFNumberGetTypeID(void) {
885 return __kCFNumberTypeID;
886 }
887
888 #define MinCachedInt (-1)
889 #define MaxCachedInt (12)
890 #define NotToBeCached (MinCachedInt - 1)
891 static CFNumberRef __CFNumberCache[MaxCachedInt - MinCachedInt + 1] = {NULL}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt
892
893 CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
894 __CFAssertIsValidNumberType(type);
895 //printf("+ [%p] CFNumberCreate(%p, %d, %p)\n", pthread_self(), allocator, type, valuePtr);
896
897 // Look for cases where we can return a cached instance.
898 // We only use cached objects if the allocator is the system
899 // default allocator, except for the special floating point
900 // constant objects, where we return the cached object
901 // regardless of allocator, since that is what has always
902 // been done (and now must for compatibility).
903 if (!allocator) allocator = __CFGetDefaultAllocator();
904 int64_t valToBeCached = NotToBeCached;
905
906 if (__CFNumberTypeTable[type].floatBit) {
907 CFNumberRef cached = NULL;
908 if (0 == __CFNumberTypeTable[type].storageBit) {
909 Float32 f = *(Float32 *)valuePtr;
910 if (isnan(f)) cached = kCFNumberNaN;
911 if (isinf(f)) cached = (f < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
912 } else {
913 Float64 d = *(Float64 *)valuePtr;
914 if (isnan(d)) cached = kCFNumberNaN;
915 if (isinf(d)) cached = (d < 0.0) ? kCFNumberNegativeInfinity : kCFNumberPositiveInfinity;
916 }
917 if (cached) return (CFNumberRef)CFRetain(cached);
918 } else if (kCFAllocatorSystemDefault == allocator) {
919 switch (__CFNumberTypeTable[type].canonicalType) {
920 case kCFNumberSInt8Type: {int8_t val = *(int8_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
921 case kCFNumberSInt16Type: {int16_t val = *(int16_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
922 case kCFNumberSInt32Type: {int32_t val = *(int32_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
923 case kCFNumberSInt64Type: {int64_t val = *(int64_t *)valuePtr; if (MinCachedInt <= val && val <= MaxCachedInt) valToBeCached = (int64_t)val; break;}
924 }
925 if (NotToBeCached != valToBeCached) {
926 CFNumberRef cached = __CFNumberCache[valToBeCached - MinCachedInt]; // Atomic to access the value in the cache
927 if (NULL != cached) return (CFNumberRef)CFRetain(cached);
928 }
929 }
930
931 CFIndex size = 8 + ((!__CFNumberTypeTable[type].floatBit && __CFNumberTypeTable[type].storageBit) ? 8 : 0);
932 CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, size, NULL);
933 if (NULL == result) {
934 return NULL;
935 }
936 __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)__CFNumberTypeTable[type].canonicalType);
937
938
939 // for a value to be cached, we already have the value handy
940 if (NotToBeCached != valToBeCached) {
941 memmove((void *)&result->_pad, &valToBeCached, 8);
942 // 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.
943 // 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.
944 // Barrier assures that the number that is placed in the cache is properly formed.
945 CFNumberType origType = __CFNumberGetType(result);
946 // Force all cached numbers to have the same type, so that the type does not
947 // depend on the order and original type in/with which the numbers are created.
948 // Forcing the type AFTER it was cached would cause a race condition with other
949 // threads pulling the number object out of the cache and using it.
950 __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)kCFNumberSInt32Type);
951 if (OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)result, (void *volatile *)&__CFNumberCache[valToBeCached - MinCachedInt])) {
952 CFRetain(result);
953 } else {
954 // Did not cache the number object, put original type back.
955 __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)origType);
956 }
957 return result;
958 }
959
960 uint64_t value;
961 switch (__CFNumberTypeTable[type].canonicalType) {
962 case kCFNumberSInt8Type: value = (uint64_t)(int64_t)*(int8_t *)valuePtr; goto smallVal;
963 case kCFNumberSInt16Type: value = (uint64_t)(int64_t)*(int16_t *)valuePtr; goto smallVal;
964 case kCFNumberSInt32Type: value = (uint64_t)(int64_t)*(int32_t *)valuePtr; goto smallVal;
965 smallVal: memmove((void *)&result->_pad, &value, 8); break;
966 case kCFNumberSInt64Type: memmove((void *)&result->_pad, valuePtr, 8); break;
967 case kCFNumberSInt128Type: memmove((void *)&result->_pad, valuePtr, 16); break;
968 case kCFNumberFloat32Type: memmove((void *)&result->_pad, valuePtr, 4); break;
969 case kCFNumberFloat64Type: memmove((void *)&result->_pad, valuePtr, 8); break;
970 }
971 //printf(" => %p\n", result);
972 return result;
973 }
974
975 CFNumberType CFNumberGetType(CFNumberRef number) {
976 //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
977 CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID, CFNumberType, number, "_cfNumberType");
978 __CFAssertIsNumber(number);
979 CFNumberType type = __CFNumberGetType(number);
980 if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public
981 //printf(" => %d\n", type);
982 return type;
983 }
984
985 CFNumberType _CFNumberGetType2(CFNumberRef number) {
986 __CFAssertIsNumber(number);
987 return __CFNumberGetType(number);
988 }
989
990 CFIndex CFNumberGetByteSize(CFNumberRef number) {
991 //printf("+ [%p] CFNumberGetByteSize(%p)\n", pthread_self(), number);
992 __CFAssertIsNumber(number);
993 CFIndex r = 1 << __CFNumberTypeTable[CFNumberGetType(number)].lgByteSize;
994 //printf(" => %d\n", r);
995 return r;
996 }
997
998 Boolean CFNumberIsFloatType(CFNumberRef number) {
999 //printf("+ [%p] CFNumberIsFloatType(%p)\n", pthread_self(), number);
1000 __CFAssertIsNumber(number);
1001 Boolean r = __CFNumberTypeTable[CFNumberGetType(number)].floatBit;
1002 //printf(" => %d\n", r);
1003 return r;
1004 }
1005
1006 Boolean CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) {
1007 //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
1008 CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID, Boolean, number, "_getValue:forType:", valuePtr, __CFNumberTypeTable[type].canonicalType);
1009 __CFAssertIsNumber(number);
1010 __CFAssertIsValidNumberType(type);
1011 uint8_t localMemory[128];
1012 Boolean r = __CFNumberGetValueCompat(number, type, valuePtr ? valuePtr : localMemory);
1013 //printf(" => %d\n", r);
1014 return r;
1015 }
1016
1017 static CFComparisonResult CFNumberCompare_new(CFNumberRef number1, CFNumberRef number2, void *context) {
1018 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number1, "compare:", number2);
1019 CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number2, "_reverseCompare:", number1);
1020 __CFAssertIsNumber(number1);
1021 __CFAssertIsNumber(number2);
1022
1023 CFNumberType type1 = __CFNumberGetType(number1);
1024 CFNumberType type2 = __CFNumberGetType(number2);
1025 // Both numbers are integers
1026 if (!__CFNumberTypeTable[type1].floatBit && !__CFNumberTypeTable[type2].floatBit) {
1027 CFSInt128Struct i1, i2;
1028 __CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
1029 __CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
1030 return cmp128(&i1, &i2);
1031 }
1032 // Both numbers are floats
1033 if (__CFNumberTypeTable[type1].floatBit && __CFNumberTypeTable[type2].floatBit) {
1034 Float64 d1, d2;
1035 __CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
1036 __CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
1037 double s1 = copysign(1.0, d1);
1038 double s2 = copysign(1.0, d2);
1039 if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
1040 if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
1041 if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
1042 // at this point, we know we don't have any NaNs
1043 if (s1 < s2) return kCFCompareLessThan;
1044 if (s2 < s1) return kCFCompareGreaterThan;
1045 // at this point, we know the signs are the same; do not combine these tests
1046 if (d1 < d2) return kCFCompareLessThan;
1047 if (d2 < d1) return kCFCompareGreaterThan;
1048 return kCFCompareEqualTo;
1049 }
1050 // One float, one integer; swap if necessary so number1 is the float
1051 Boolean swapResult = false;
1052 if (__CFNumberTypeTable[type2].floatBit) {
1053 CFNumberRef tmp = number1;
1054 number1 = number2;
1055 number2 = tmp;
1056 swapResult = true;
1057 }
1058 // At large integer values, the precision of double is quite low
1059 // e.g. all values roughly 2^127 +- 2^73 are represented by 1 double, 2^127.
1060 // If we just used double compare, that would make the 2^73 largest 128-bit
1061 // integers look equal, so we have to use integer comparison when possible.
1062 Float64 d1, d2;
1063 __CFNumberGetValue(number1, kCFNumberFloat64Type, &d1);
1064 // if the double value is really big, cannot be equal to integer
1065 // nan d1 will not compare true here
1066 if (d1 < FLOAT_NEGATIVE_2_TO_THE_127) {
1067 return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1068 }
1069 if (FLOAT_POSITIVE_2_TO_THE_127 <= d1) {
1070 return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1071 }
1072 CFSInt128Struct i1, i2;
1073 __CFNumberGetValue(number1, kCFNumberSInt128Type, &i1);
1074 __CFNumberGetValue(number2, kCFNumberSInt128Type, &i2);
1075 CFComparisonResult res = cmp128(&i1, &i2);
1076 if (kCFCompareEqualTo != res) {
1077 return !swapResult ? res : -res;
1078 }
1079 // now things are equal, but perhaps due to rounding or nan
1080 if (isnan(d1)) {
1081 if (isNeg128(&i2)) {
1082 return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1083 }
1084 // nan compares less than positive 0 too
1085 return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1086 }
1087 // at this point, we know we don't have NaN
1088 double s1 = copysign(1.0, d1);
1089 double s2 = isNeg128(&i2) ? -1.0 : 1.0;
1090 if (s1 < s2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1091 if (s2 < s1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1092 // at this point, we know the signs are the same; do not combine these tests
1093 __CFNumberGetValue(number2, kCFNumberFloat64Type, &d2);
1094 if (d1 < d2) return !swapResult ? kCFCompareLessThan : kCFCompareGreaterThan;
1095 if (d2 < d1) return !swapResult ? kCFCompareGreaterThan : kCFCompareLessThan;
1096 return kCFCompareEqualTo;
1097 }
1098
1099 CFComparisonResult CFNumberCompare(CFNumberRef number1, CFNumberRef number2, void *context) {
1100 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
1101 CFComparisonResult r = CFNumberCompare_new(number1, number2, context);
1102 //printf(" => %d\n", r);
1103 return r;
1104 }
1105
1106 #undef __CFAssertIsBoolean
1107 #undef __CFAssertIsNumber
1108 #undef __CFAssertIsValidNumberType
1109 #undef BITSFORDOUBLENAN
1110 #undef BITSFORDOUBLEPOSINF
1111 #undef BITSFORDOUBLENEGINF
1112 #undef MinCachedInt
1113 #undef MaxCachedInt
1114 #undef NotToBeCached
1115