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