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