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/* CFRuntime.h 25 Copyright (c) 1999-2013, Apple Inc. All rights reserved. 26*/ 27 28#if !defined(__COREFOUNDATION_CFRUNTIME__) 29#define __COREFOUNDATION_CFRUNTIME__ 1 30 31#include <CoreFoundation/CFBase.h> 32#include <CoreFoundation/CFDictionary.h> 33#include <stddef.h> 34 35CF_EXTERN_C_BEGIN 36 37#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) 38 39// GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging 40CF_EXPORT bool kCFUseCollectableAllocator; 41CF_EXPORT bool (*__CFObjCIsCollectable)(void *); 42 43CF_INLINE Boolean _CFAllocatorIsSystemDefault(CFAllocatorRef allocator) { 44 if (allocator == kCFAllocatorSystemDefault) return true; 45 if (NULL == allocator || kCFAllocatorDefault == allocator) { 46 return (kCFAllocatorSystemDefault == CFAllocatorGetDefault()); 47 } 48 return false; 49} 50 51// is GC on? 52#define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator) 53// is GC on and is this the GC allocator? 54#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (kCFUseCollectableAllocator && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator) || 0)) 55// is this allocated by the collector? 56#define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false) 57 58#else 59 60#define kCFUseCollectableAllocator 0 61#define __CFObjCIsCollectable 0 62 63CF_INLINE Boolean _CFAllocatorIsSystemDefault(CFAllocatorRef allocator) { 64 if (allocator == kCFAllocatorSystemDefault) return true; 65 if (NULL == allocator || kCFAllocatorDefault == allocator) { 66 return (kCFAllocatorSystemDefault == CFAllocatorGetDefault()); 67 } 68 return false; 69} 70 71#define CF_USING_COLLECTABLE_MEMORY 0 72#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) 0 73#define CF_IS_COLLECTABLE(obj) 0 74#endif 75 76enum { 77 _kCFRuntimeNotATypeID = 0 78}; 79 80enum { // Version field constants 81 _kCFRuntimeScannedObject = (1UL << 0), 82 _kCFRuntimeResourcefulObject = (1UL << 2), // tells CFRuntime to make use of the reclaim field 83 _kCFRuntimeCustomRefCount = (1UL << 3), // tells CFRuntime to make use of the refcount field 84}; 85 86typedef struct __CFRuntimeClass { 87 CFIndex version; 88 const char *className; // must be a pure ASCII string, nul-terminated 89 void (*init)(CFTypeRef cf); 90 CFTypeRef (*copy)(CFAllocatorRef allocator, CFTypeRef cf); 91 void (*finalize)(CFTypeRef cf); 92 Boolean (*equal)(CFTypeRef cf1, CFTypeRef cf2); 93 CFHashCode (*hash)(CFTypeRef cf); 94 CFStringRef (*copyFormattingDesc)(CFTypeRef cf, CFDictionaryRef formatOptions); // return str with retain 95 CFStringRef (*copyDebugDesc)(CFTypeRef cf); // return str with retain 96 97#define CF_RECLAIM_AVAILABLE 1 98 void (*reclaim)(CFTypeRef cf); // Set _kCFRuntimeResourcefulObject in the .version to indicate this field should be used 99 100#define CF_REFCOUNT_AVAILABLE 1 101 uint32_t (*refcount)(intptr_t op, CFTypeRef cf); // Set _kCFRuntimeCustomRefCount in the .version to indicate this field should be used 102 // this field must be non-NULL when _kCFRuntimeCustomRefCount is in the .version field 103 // - if the callback is passed 1 in 'op' it should increment the 'cf's reference count and return 0 104 // - if the callback is passed 0 in 'op' it should return the 'cf's reference count, up to 32 bits 105 // - if the callback is passed -1 in 'op' it should decrement the 'cf's reference count; if it is now zero, 'cf' should be cleaned up and deallocated (the finalize callback above will NOT be called unless the process is running under GC, and CF does not deallocate the memory for you; if running under GC, finalize should do the object tear-down and free the object memory); then return 0 106 // remember to use saturation arithmetic logic and stop incrementing and decrementing when the ref count hits UINT32_MAX, or you will have a security bug 107 // remember that reference count incrementing/decrementing must be done thread-safely/atomically 108 // objects should be created/initialized with a custom ref-count of 1 by the class creation functions 109 // do not attempt to use any bits within the CFRuntimeBase for your reference count; store that in some additional field in your CF object 110 111} CFRuntimeClass; 112 113#define RADAR_5115468_FIXED 1 114 115/* Note that CF runtime class registration and unregistration is not currently 116 * thread-safe, which should not currently be a problem, as long as unregistration 117 * is done only when valid to do so. 118 */ 119 120CF_EXPORT CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls); 121 /* Registers a new class with the CF runtime. Pass in a 122 * pointer to a CFRuntimeClass structure. The pointer is 123 * remembered by the CF runtime -- the structure is NOT 124 * copied. 125 * 126 * - version field must be zero currently. 127 * - className field points to a null-terminated C string 128 * containing only ASCII (0 - 127) characters; this field 129 * may NOT be NULL. 130 * - init field points to a function which classes can use to 131 * apply some generic initialization to instances as they 132 * are created; this function is called by both 133 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if 134 * this field is NULL, no function is called; the instance 135 * has been initialized enough that the polymorphic funcs 136 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(), 137 * and CFGetAllocator() are valid on it when the init 138 * function if any is called. 139 * - finalize field points to a function which destroys an 140 * instance when the retain count has fallen to zero; if 141 * this is NULL, finalization does nothing. Note that if 142 * the class-specific functions which create or initialize 143 * instances more fully decide that a half-initialized 144 * instance must be destroyed, the finalize function for 145 * that class has to be able to deal with half-initialized 146 * instances. The finalize function should NOT destroy the 147 * memory for the instance itself; that is done by the 148 * CF runtime after this finalize callout returns. 149 * - equal field points to an equality-testing function; this 150 * field may be NULL, in which case only pointer/reference 151 * equality is performed on instances of this class. 152 * Pointer equality is tested, and the type IDs are checked 153 * for equality, before this function is called (so, the 154 * two instances are not pointer-equal but are of the same 155 * class before this function is called). 156 * NOTE: the equal function must implement an immutable 157 * equality relation, satisfying the reflexive, symmetric, 158 * and transitive properties, and remains the same across 159 * time and immutable operations (that is, if equal(A,B) at 160 * some point, then later equal(A,B) provided neither 161 * A or B has been mutated). 162 * - hash field points to a hash-code-computing function for 163 * instances of this class; this field may be NULL in which 164 * case the pointer value of an instance is converted into 165 * a hash. 166 * NOTE: the hash function and equal function must satisfy 167 * the relationship "equal(A,B) implies hash(A) == hash(B)"; 168 * that is, if two instances are equal, their hash codes must 169 * be equal too. (However, the converse is not true!) 170 * - copyFormattingDesc field points to a function returning a 171 * CFStringRef with a human-readable description of the 172 * instance; if this is NULL, the type does not have special 173 * human-readable string-formats. 174 * - copyDebugDesc field points to a function returning a 175 * CFStringRef with a debugging description of the instance; 176 * if this is NULL, a simple description is generated. 177 * 178 * This function returns _kCFRuntimeNotATypeID on failure, or 179 * on success, returns the CFTypeID for the new class. This 180 * CFTypeID is what the class uses to allocate or initialize 181 * instances of the class. It is also returned from the 182 * conventional *GetTypeID() function, which returns the 183 * class's CFTypeID so that clients can compare the 184 * CFTypeID of instances with that of a class. 185 * 186 * The function to compute a human-readable string is very 187 * optional, and is really only interesting for classes, 188 * like strings or numbers, where it makes sense to format 189 * the instance using just its contents. 190 */ 191 192CF_EXPORT const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID); 193 /* Returns the pointer to the CFRuntimeClass which was 194 * assigned the specified CFTypeID. 195 */ 196 197CF_EXPORT void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID); 198 /* Unregisters the class with the given type ID. It is 199 * undefined whether type IDs are reused or not (expect 200 * that they will be). 201 * 202 * Whether or not unregistering the class is a good idea or 203 * not is not CF's responsibility. In particular you must 204 * be quite sure all instances are gone, and there are no 205 * valid weak refs to such in other threads. 206 */ 207 208/* All CF "instances" start with this structure. Never refer to 209 * these fields directly -- they are for CF's use and may be added 210 * to or removed or change format without warning. Binary 211 * compatibility for uses of this struct is not guaranteed from 212 * release to release. 213 */ 214typedef struct __CFRuntimeBase { 215 uintptr_t _cfisa; 216 uint8_t _cfinfo[4]; 217#if __LP64__ 218 uint32_t _rc; 219#endif 220} CFRuntimeBase; 221 222#if __BIG_ENDIAN__ 223#define INIT_CFRUNTIME_BASE(...) {0, {0, 0, 0, 0x80}} 224#else 225#define INIT_CFRUNTIME_BASE(...) {0, {0x80, 0, 0, 0}} 226#endif 227 228CF_EXPORT CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CFIndex extraBytes, unsigned char *category); 229 /* Creates a new CF instance of the class specified by the 230 * given CFTypeID, using the given allocator, and returns it. 231 * If the allocator returns NULL, this function returns NULL. 232 * A CFRuntimeBase structure is initialized at the beginning 233 * of the returned instance. extraBytes is the additional 234 * number of bytes to allocate for the instance (BEYOND that 235 * needed for the CFRuntimeBase). If the specified CFTypeID 236 * is unknown to the CF runtime, this function returns NULL. 237 * No part of the new memory other than base header is 238 * initialized (the extra bytes are not zeroed, for example). 239 * All instances created with this function must be destroyed 240 * only through use of the CFRelease() function -- instances 241 * must not be destroyed by using CFAllocatorDeallocate() 242 * directly, even in the initialization or creation functions 243 * of a class. Pass NULL for the category parameter. 244 */ 245 246CF_EXPORT void _CFRuntimeSetInstanceTypeID(CFTypeRef cf, CFTypeID typeID); 247 /* This function changes the typeID of the given instance. 248 * If the specified CFTypeID is unknown to the CF runtime, 249 * this function does nothing. This function CANNOT be used 250 * to initialize an instance. It is for advanced usages such 251 * as faulting. You cannot change the CFTypeID of an object 252 * of a _kCFRuntimeCustomRefCount class, or to a 253 * _kCFRuntimeCustomRefCount class. 254 */ 255 256CF_EXPORT void _CFRuntimeInitStaticInstance(void *memory, CFTypeID typeID); 257 /* This function initializes a memory block to be a constant 258 * (unreleaseable) CF object of the given typeID. 259 * If the specified CFTypeID is unknown to the CF runtime, 260 * this function does nothing. The memory block should 261 * be a chunk of in-binary writeable static memory, and at 262 * least as large as sizeof(CFRuntimeBase) on the platform 263 * the code is being compiled for. The init function of the 264 * CFRuntimeClass is invoked on the memory as well, if the 265 * class has one. Static instances cannot be initialized to 266 * _kCFRuntimeCustomRefCount classes. 267 */ 268#define CF_HAS_INIT_STATIC_INSTANCE 1 269 270#if 0 271// ========================= EXAMPLE ========================= 272 273// Example: EXRange -- a "range" object, which keeps the starting 274// location and length of the range. ("EX" as in "EXample"). 275 276// ---- API ---- 277 278typedef const struct __EXRange * EXRangeRef; 279 280CFTypeID EXRangeGetTypeID(void); 281 282EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length); 283 284uint32_t EXRangeGetLocation(EXRangeRef rangeref); 285uint32_t EXRangeGetLength(EXRangeRef rangeref); 286 287 288// ---- implementation ---- 289 290#include <CoreFoundation/CFBase.h> 291#include <CoreFoundation/CFString.h> 292 293struct __EXRange { 294 CFRuntimeBase _base; 295 uint32_t _location; 296 uint32_t _length; 297}; 298 299static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) { 300 EXRangeRef rangeref1 = (EXRangeRef)cf1; 301 EXRangeRef rangeref2 = (EXRangeRef)cf2; 302 if (rangeref1->_location != rangeref2->_location) return false; 303 if (rangeref1->_length != rangeref2->_length) return false; 304 return true; 305} 306 307static CFHashCode __EXRangeHash(CFTypeRef cf) { 308 EXRangeRef rangeref = (EXRangeRef)cf; 309 return (CFHashCode)(rangeref->_location + rangeref->_length); 310} 311 312static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) { 313 EXRangeRef rangeref = (EXRangeRef)cf; 314 return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts, 315 CFSTR("[%u, %u)"), 316 rangeref->_location, 317 rangeref->_location + rangeref->_length); 318} 319 320static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) { 321 EXRangeRef rangeref = (EXRangeRef)cf; 322 return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL, 323 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"), 324 rangeref, 325 CFGetAllocator(rangeref), 326 rangeref->_location, 327 rangeref->_length); 328} 329 330static void __EXRangeEXRangeFinalize(CFTypeRef cf) { 331 EXRangeRef rangeref = (EXRangeRef)cf; 332 // nothing to finalize 333} 334 335static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID; 336 337static CFRuntimeClass _kEXRangeClass = {0}; 338 339/* Something external to this file is assumed to call this 340 * before the EXRange class is used. 341 */ 342void __EXRangeClassInitialize(void) { 343 _kEXRangeClass.version = 0; 344 _kEXRangeClass.className = "EXRange"; 345 _kEXRangeClass.init = NULL; 346 _kEXRangeClass.copy = NULL; 347 _kEXRangeClass.finalize = __EXRangeEXRangeFinalize; 348 _kEXRangeClass.equal = __EXRangeEqual; 349 _kEXRangeClass.hash = __EXRangeHash; 350 _kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc; 351 _kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc; 352 _kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass); 353} 354 355CFTypeID EXRangeGetTypeID(void) { 356 return _kEXRangeID; 357} 358 359EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) { 360 struct __EXRange *newrange; 361 uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase); 362 newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL); 363 if (NULL == newrange) { 364 return NULL; 365 } 366 newrange->_location = location; 367 newrange->_length = length; 368 return (EXRangeRef)newrange; 369} 370 371uint32_t EXRangeGetLocation(EXRangeRef rangeref) { 372 return rangeref->_location; 373} 374 375uint32_t EXRangeGetLength(EXRangeRef rangeref) { 376 return rangeref->_length; 377} 378 379#endif 380 381CF_EXTERN_C_END 382 383#endif /* ! __COREFOUNDATION_CFRUNTIME__ */ 384