1/* 2 * Copyright (c) 2014 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 44struct __CFBoolean { 45 CFRuntimeBase _base; 46}; 47 48static struct __CFBoolean __kCFBooleanTrue = { 49 INIT_CFRUNTIME_BASE() 50}; 51const CFBooleanRef kCFBooleanTrue = &__kCFBooleanTrue; 52 53static struct __CFBoolean __kCFBooleanFalse = { 54 INIT_CFRUNTIME_BASE() 55}; 56const CFBooleanRef kCFBooleanFalse = &__kCFBooleanFalse; 57 58static 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 63CF_PRIVATE CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { 64 CFBooleanRef boolean = (CFBooleanRef)cf; 65 return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false")); 66} 67 68static CFHashCode __CFBooleanHash(CFTypeRef cf) { 69 CFBooleanRef boolean = (CFBooleanRef)cf; 70 return (boolean == kCFBooleanTrue) ? _CFHashInt(1) : _CFHashInt(0); 71} 72 73static void __CFBooleanDeallocate(CFTypeRef cf) { 74 CFAssert(false, __kCFLogAssertion, "Deallocated CFBoolean!"); 75} 76 77static CFTypeID __kCFBooleanTypeID = _kCFRuntimeNotATypeID; 78 79static 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 91CF_PRIVATE void __CFBooleanInitialize(void) { 92 __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass); 93 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue, __kCFBooleanTypeID); 94 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse, __kCFBooleanTypeID); 95} 96 97CFTypeID CFBooleanGetTypeID(void) { 98 return __kCFBooleanTypeID; 99} 100 101Boolean 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 115typedef union { 116 SInt32 valSInt32; 117 int64_t valSInt64; 118 Float32 valFloat32; 119 Float64 valFloat64; 120} __CFNumberValue_old; 121 122struct __CFNumber_old { /* Only as many bytes as necessary are allocated */ 123 CFRuntimeBase _base; 124 __CFNumberValue_old value; 125}; 126 127static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2); 128static CFHashCode __CFNumberHash_old(CFTypeRef cf); 129static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf); 130CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf); 131static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions); 132static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr); 133static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number); 134static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number); 135static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number); 136static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr); 137static 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: 1460x7f800000 float +Inf 1470x7fc00000 float NaN 1480xff800000 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 166typedef 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 171enum { 172 kCFNumberSInt128Type = 17 173}; 174 175static uint8_t isNeg128(const CFSInt128Struct *in) { 176 return in->high < 0; 177} 178 179static 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 188static 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 199static 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 208static 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 250static 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 292static 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 319static 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 334static 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 355struct __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 370static struct __CFNumber __kCFNumberNaN = { 371 INIT_CFRUNTIME_BASE(), 0ULL 372}; 373const CFNumberRef kCFNumberNaN = &__kCFNumberNaN; 374 375static struct __CFNumber __kCFNumberNegativeInfinity = { 376 INIT_CFRUNTIME_BASE(), 0ULL 377}; 378const CFNumberRef kCFNumberNegativeInfinity = &__kCFNumberNegativeInfinity; 379 380static struct __CFNumber __kCFNumberPositiveInfinity = { 381 INIT_CFRUNTIME_BASE(), 0ULL 382}; 383const CFNumberRef kCFNumberPositiveInfinity = &__kCFNumberPositiveInfinity; 384 385static 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 426CF_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 454static 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 644static 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 806static void FAIL(void) {} 807#endif 808 809static 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 848if (! number->__old__) { 849 850printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf); 851} else { 852CFStringRef test = __CFNumberCopyDescription_old(number->__old__); 853if (!CFEqual(test, mstr)) { 854CFLog(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 863static 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 879CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) { 880 CFStringRef result = __CFNumberCreateFormattingDescriptionAsFloat64(kCFAllocatorSystemDefault, cf); 881#if OLD_CRAP_TOO 882CFNumberRef number = (CFNumberRef)cf; 883if (! number->__old__) { 884printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf); 885} else { 886CFStringRef test = __CFNumberCopyFormattingDescriptionAsFloat64_old(number->__old__); 887if (!CFEqual(test, result)) { 888CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test, result); FAIL(); 889} 890} 891#endif 892 return result; 893} 894 895CF_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 908static 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 921CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { 922 CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions); 923#if OLD_CRAP_TOO 924CFNumberRef number = (CFNumberRef)cf; 925if (! number->__old__) { 926printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf); 927} else { 928CFStringRef test = __CFNumberCopyFormattingDescription_old(number->__old__, formatOptions); 929if (!CFEqual(test, result)) { 930CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test, result); FAIL(); 931} 932} 933#endif 934 return result; 935} 936 937 938static Boolean __CFNumberEqual(CFTypeRef cf1, CFTypeRef cf2) { 939 Boolean b = CFNumberCompare((CFNumberRef)cf1, (CFNumberRef)cf2, 0) == kCFCompareEqualTo; 940#if OLD_CRAP_TOO 941CFNumberRef number1 = (CFNumberRef)cf1; 942CFNumberRef number2 = (CFNumberRef)cf2; 943if (! number1->__old__ || !number2->__old__) { 944printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1, cf2); 945} else { 946Boolean b2 = __CFNumberEqual_old(number1->__old__, number2->__old__); 947if (b2 != b) { 948CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2, b); FAIL(); 949} 950} 951#endif 952 return b; 953} 954 955static 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 975CFNumberRef number1 = (CFNumberRef)cf; 976if (! number1->__old__) { 977printf("*** Test skipped in __CFNumberHash for number %p\n", cf); 978} else { 979CFHashCode h2 = __CFNumberHash_old(number1->__old__); 980if (h2 != h) { 981CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2, h); FAIL(); 982} 983} 984#endif 985 return h; 986} 987 988static CFTypeID __kCFNumberTypeID = _kCFRuntimeNotATypeID; 989 990enum { 991 kCFNumberCachingEnabled = 0, 992 kCFNumberCachingDisabled = 1, 993 kCFNumberCachingFullyDisabled = 2 994}; 995static char __CFNumberCaching = kCFNumberCachingEnabled; 996 997static 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 1010CF_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 1030CFTypeID CFNumberGetTypeID(void) { 1031 return __kCFNumberTypeID; 1032} 1033 1034#define MinCachedInt (-1) 1035#define MaxCachedInt (12) 1036#define NotToBeCached (MinCachedInt - 1) 1037static CFNumberRef __CFNumberCache[MaxCachedInt - MinCachedInt + 1] = {NULL}; // Storing CFNumberRefs for range MinCachedInt..MaxCachedInt 1038 1039CFNumberRef 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); 1091CFLog(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 1131CFNumberType 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 1139if (! number->__old__) { 1140printf("*** Test skipped in CFNumberGetType for number %p\n", number); 1141} else { 1142CFNumberType t2 = CFNumberGetType_old(number->__old__); 1143if (t2 != type) { 1144CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2, type); FAIL(); 1145} 1146} 1147#endif 1148 return type; 1149} 1150 1151CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) { 1152 CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType); 1153 __CFAssertIsNumber(number); 1154 return __CFNumberGetType(number); 1155} 1156 1157CFIndex 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 1163if (! number->__old__) { 1164printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number); 1165} else { 1166CFIndex r2 = CFNumberGetByteSize_old(number->__old__); 1167if (r2 != r) { 1168CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2, r); FAIL(); 1169} 1170} 1171#endif 1172 return r; 1173} 1174 1175Boolean 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 1181if (! number->__old__) { 1182printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number); 1183} else { 1184Boolean r2 = CFNumberIsFloatType_old(number->__old__); 1185if (r2 != r) { 1186CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2, r); FAIL(); 1187} 1188} 1189#endif 1190 return r; 1191} 1192 1193Boolean 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 1203if (! number->__old__) { 1204printf("*** Test skipped in CFNumberGetValue for number %p\n", number); 1205} else { 1206 uint8_t localMemory2[128]; 1207Boolean r2 = CFNumberGetValue_old(number->__old__, type, localMemory2); 1208if (r2 != r) { 1209CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2, r); FAIL(); 1210} 1211if (0 != memcmp(localMemory2, valuePtr, CFNumberGetByteSize(number))) { 1212CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME")); FAIL(); 1213} 1214} 1215#endif 1216 return r; 1217} 1218 1219static 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 1301CFComparisonResult 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 1306if (! number1->__old__ || !number2->__old__) { 1307printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1, number2); 1308} else { 1309CFComparisonResult r2 = CFNumberCompare_old(number1->__old__, number2->__old__, context); 1310if (r2 != r) { 1311CFLog(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 1320static 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 1326static 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 1335static CFNumberType __CFNumberGetStorageTypeForType_old(CFNumberType type) { 1336 return __CFNumberStorageType[type]; 1337} 1338 1339// Returns the canonical type used to represent the specified type 1340static CFNumberType __CFNumberGetCanonicalTypeForType_old(CFNumberType type) { 1341 return __CFNumberCanonicalType[type]; 1342} 1343 1344// Extracts and returns the type out of the CFNumber 1345static 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 1350static 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 1356static 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 1396static 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) 1407static 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 1422static 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 1428static 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 1444static 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 1476static 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 1524CF_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 1540static 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 1573static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) { 1574 struct __CFNumber_old * num; 1575 CFNumberType equivType, storageType; 1576 1577if (type == 17) { 1578CFSInt128Struct *s = valuePtr; 1579s->high = (int64_t)s->low; 1580type = 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 1595if (__CFNumberGetType_old(num) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num, storageType); 1596 return num; 1597} 1598 1599static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number) { 1600 1601 return __CFNumberGetType_old(number); 1602} 1603 1604static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number) { 1605 return __CFNumberSizeOfType_old(CFNumberGetType_old(number)); 1606} 1607 1608static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number) { 1609 return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number)); 1610} 1611 1612static 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 1618if (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 1635static 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 1680