2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright (c) 1999-2007, Apple Inc. All rights reserved.
27 #if !defined(__COREFOUNDATION_CFRUNTIME__)
28 #define __COREFOUNDATION_CFRUNTIME__ 1
30 #include <CoreFoundation/CFBase.h>
31 #include <CoreFoundation/CFDictionary.h>
36 // GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging
37 extern bool kCFUseCollectableAllocator
;
38 extern bool (*__CFObjCIsCollectable
)(void *);
39 extern const void* (*__CFObjCAssignIvar
)(const void *value
, const void *base
, const void **slot
);
40 extern const void* (*__CFObjCStrongAssign
)(const void *value
, const void **slot
);
41 extern void* (*__CFObjCMemmoveCollectable
)(void *dest
, const void *src
, size_t);
42 extern void (*__CFObjCWriteBarrierRange
)(void *, size_t);
46 #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator)
47 // is GC on and is this the GC allocator?
48 #define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (CF_USING_COLLECTABLE_MEMORY && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
49 // is this allocated by the collector?
50 #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false)
52 // XXX_PCB for generational GC support.
54 CF_INLINE
const void* __CFAssignIvar(CFAllocatorRef allocator
, const void *rvalue
, const void *base
, const void **lvalue
) {
55 if (rvalue
&& CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
56 return __CFObjCAssignIvar(rvalue
, base
, lvalue
);
58 return (*lvalue
= rvalue
);
61 CF_INLINE
const void* __CFStrongAssign(CFAllocatorRef allocator
, const void *rvalue
, const void **lvalue
) {
62 if (rvalue
&& CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
63 return __CFObjCStrongAssign(rvalue
, lvalue
);
65 return (*lvalue
= rvalue
);
68 // Use this form when the base pointer to the object is known.
69 #define CF_WRITE_BARRIER_BASE_ASSIGN(allocator, base, lvalue, rvalue) __CFAssignIvar(allocator, (const void*)rvalue, (const void*)base, (const void**)&(lvalue))
71 // Use this form when the base pointer to the object isn't known.
72 #define CF_WRITE_BARRIER_ASSIGN(allocator, lvalue, rvalue) __CFStrongAssign(allocator, (const void*)rvalue, (const void**)&(lvalue))
74 // Write-barrier memory move.
75 #define CF_WRITE_BARRIER_MEMMOVE(dst, src, size) __CFObjCMemmoveCollectable(dst, src, size)
77 // Used by frameworks to assert they "KNOW WHAT THEY'RE DOING under GC."
78 CF_EXPORT CFAllocatorRef
_CFAllocatorCreateGC(CFAllocatorRef allocator
, CFAllocatorContext
*context
);
80 // Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
81 CF_EXPORT
void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
);
82 CF_EXPORT
void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
);
83 CF_EXPORT
void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
);
86 _kCFRuntimeNotATypeID
= 0,
87 _kCFRuntimeScannedObject
= (1 << 0),
88 /* _kCFRuntimeUncollectableObject = (1 << 1), No longer used; obsolete. */
89 _kCFRuntimeResourcefulObject
= (1 << 2)
92 typedef struct __CFRuntimeClass
{ // Version 0 struct
94 const char *className
;
95 void (*init
)(CFTypeRef cf
);
96 CFTypeRef (*copy
)(CFAllocatorRef allocator
, CFTypeRef cf
);
97 #if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
98 void (*finalize
)(CFTypeRef cf
);
100 void (*dealloc
)(CFTypeRef cf
);
102 Boolean (*equal
)(CFTypeRef cf1
, CFTypeRef cf2
);
103 CFHashCode (*hash
)(CFTypeRef cf
);
104 CFStringRef (*copyFormattingDesc
)(CFTypeRef cf
, CFDictionaryRef formatOptions
); // str with retain
105 CFStringRef (*copyDebugDesc
)(CFTypeRef cf
); // str with retain
106 #if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
107 #define CF_RECLAIM_AVAILABLE 1
108 void (*reclaim
)(CFTypeRef cf
);
112 #define RADAR_5115468_FIXED 1
114 /* Note that CF runtime class registration and unregistration is not currently
115 * thread-safe, which should not currently be a problem, as long as unregistration
116 * is done only when valid to do so.
119 CF_EXPORT CFTypeID
_CFRuntimeRegisterClass(const CFRuntimeClass
* const cls
);
120 /* Registers a new class with the CF runtime. Pass in a
121 * pointer to a CFRuntimeClass structure. The pointer is
122 * remembered by the CF runtime -- the structure is NOT
125 * - version field must be zero currently.
126 * - className field points to a null-terminated C string
127 * containing only ASCII (0 - 127) characters; this field
129 * - init field points to a function which classes can use to
130 * apply some generic initialization to instances as they
131 * are created; this function is called by both
132 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if
133 * this field is NULL, no function is called; the instance
134 * has been initialized enough that the polymorphic funcs
135 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(),
136 * and CFGetAllocator() are valid on it when the init
137 * function if any is called.
138 * - finalize field points to a function which destroys an
139 * instance when the retain count has fallen to zero; if
140 * this is NULL, finalization does nothing. Note that if
141 * the class-specific functions which create or initialize
142 * instances more fully decide that a half-initialized
143 * instance must be destroyed, the finalize function for
144 * that class has to be able to deal with half-initialized
145 * instances. The finalize function should NOT destroy the
146 * memory for the instance itself; that is done by the
147 * CF runtime after this finalize callout returns.
148 * - equal field points to an equality-testing function; this
149 * field may be NULL, in which case only pointer/reference
150 * equality is performed on instances of this class.
151 * Pointer equality is tested, and the type IDs are checked
152 * for equality, before this function is called (so, the
153 * two instances are not pointer-equal but are of the same
154 * class before this function is called).
155 * NOTE: the equal function must implement an immutable
156 * equality relation, satisfying the reflexive, symmetric,
157 * and transitive properties, and remains the same across
158 * time and immutable operations (that is, if equal(A,B) at
159 * some point, then later equal(A,B) provided neither
160 * A or B has been mutated).
161 * - hash field points to a hash-code-computing function for
162 * instances of this class; this field may be NULL in which
163 * case the pointer value of an instance is converted into
165 * NOTE: the hash function and equal function must satisfy
166 * the relationship "equal(A,B) implies hash(A) == hash(B)";
167 * that is, if two instances are equal, their hash codes must
168 * be equal too. (However, the converse is not true!)
169 * - copyFormattingDesc field points to a function returning a
170 * CFStringRef with a human-readable description of the
171 * instance; if this is NULL, the type does not have special
172 * human-readable string-formats.
173 * - copyDebugDesc field points to a function returning a
174 * CFStringRef with a debugging description of the instance;
175 * if this is NULL, a simple description is generated.
177 * This function returns _kCFRuntimeNotATypeID on failure, or
178 * on success, returns the CFTypeID for the new class. This
179 * CFTypeID is what the class uses to allocate or initialize
180 * instances of the class. It is also returned from the
181 * conventional *GetTypeID() function, which returns the
182 * class's CFTypeID so that clients can compare the
183 * CFTypeID of instances with that of a class.
185 * The function to compute a human-readable string is very
186 * optional, and is really only interesting for classes,
187 * like strings or numbers, where it makes sense to format
188 * the instance using just its contents.
191 CF_EXPORT
const CFRuntimeClass
* _CFRuntimeGetClassWithTypeID(CFTypeID typeID
);
192 /* Returns the pointer to the CFRuntimeClass which was
193 * assigned the specified CFTypeID.
196 CF_EXPORT
void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID
);
197 /* Unregisters the class with the given type ID. It is
198 * undefined whether type IDs are reused or not (expect
199 * that they will be).
201 * Whether or not unregistering the class is a good idea or
202 * not is not CF's responsibility. In particular you must
203 * be quite sure all instances are gone, and there are no
204 * valid weak refs to such in other threads.
207 /* All CF "instances" start with this structure. Never refer to
208 * these fields directly -- they are for CF's use and may be added
209 * to or removed or change format without warning. Binary
210 * compatibility for uses of this struct is not guaranteed from
211 * release to release.
213 typedef struct __CFRuntimeBase
{
222 #define INIT_CFRUNTIME_BASE(...) {0, {0, 0, 0, 0x80}}
224 #define INIT_CFRUNTIME_BASE(...) {0, {0x80, 0, 0, 0}}
227 CF_EXPORT CFTypeRef
_CFRuntimeCreateInstance(CFAllocatorRef allocator
, CFTypeID typeID
, CFIndex extraBytes
, unsigned char *category
);
228 /* Creates a new CF instance of the class specified by the
229 * given CFTypeID, using the given allocator, and returns it.
230 * If the allocator returns NULL, this function returns NULL.
231 * A CFRuntimeBase structure is initialized at the beginning
232 * of the returned instance. extraBytes is the additional
233 * number of bytes to allocate for the instance (BEYOND that
234 * needed for the CFRuntimeBase). If the specified CFTypeID
235 * is unknown to the CF runtime, this function returns NULL.
236 * No part of the new memory other than base header is
237 * initialized (the extra bytes are not zeroed, for example).
238 * All instances created with this function must be destroyed
239 * only through use of the CFRelease() function -- instances
240 * must not be destroyed by using CFAllocatorDeallocate()
241 * directly, even in the initialization or creation functions
242 * of a class. Pass NULL for the category parameter.
245 CF_EXPORT
void _CFRuntimeSetInstanceTypeID(CFTypeRef cf
, CFTypeID typeID
);
246 /* This function changes the typeID of the given instance.
247 * If the specified CFTypeID is unknown to the CF runtime,
248 * this function does nothing. This function CANNOT be used
249 * to initialize an instance. It is for advanced usages such
253 CF_EXPORT
void _CFRuntimeInitStaticInstance(void *memory
, CFTypeID typeID
);
254 /* This function initializes a memory block to be a constant
255 * (unreleaseable) CF object of the given typeID.
256 * If the specified CFTypeID is unknown to the CF runtime,
257 * this function does nothing. The memory block should
258 * be a chunk of in-binary writeable static memory, and at
259 * least as large as sizeof(CFRuntimeBase) on the platform
260 * the code is being compiled for. The init function of the
261 * CFRuntimeClass is invoked on the memory as well, if the
264 #define CF_HAS_INIT_STATIC_INSTANCE 1
267 // ========================= EXAMPLE =========================
269 // Example: EXRange -- a "range" object, which keeps the starting
270 // location and length of the range. ("EX" as in "EXample").
274 typedef const struct __EXRange
* EXRangeRef
;
276 CFTypeID
EXRangeGetTypeID(void);
278 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
);
280 uint32_t EXRangeGetLocation(EXRangeRef rangeref
);
281 uint32_t EXRangeGetLength(EXRangeRef rangeref
);
284 // ---- implementation ----
286 #include <CoreFoundation/CFBase.h>
287 #include <CoreFoundation/CFString.h>
295 static Boolean
__EXRangeEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
296 EXRangeRef rangeref1
= (EXRangeRef
)cf1
;
297 EXRangeRef rangeref2
= (EXRangeRef
)cf2
;
298 if (rangeref1
->_location
!= rangeref2
->_location
) return false;
299 if (rangeref1
->_length
!= rangeref2
->_length
) return false;
303 static CFHashCode
__EXRangeHash(CFTypeRef cf
) {
304 EXRangeRef rangeref
= (EXRangeRef
)cf
;
305 return (CFHashCode
)(rangeref
->_location
+ rangeref
->_length
);
308 static CFStringRef
__EXRangeCopyFormattingDesc(CFTypeRef cf
, CFDictionaryRef formatOpts
) {
309 EXRangeRef rangeref
= (EXRangeRef
)cf
;
310 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), formatOpts
,
313 rangeref
->_location
+ rangeref
->_length
);
316 static CFStringRef
__EXRangeCopyDebugDesc(CFTypeRef cf
) {
317 EXRangeRef rangeref
= (EXRangeRef
)cf
;
318 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), NULL
,
319 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
321 CFGetAllocator(rangeref
),
326 static void __EXRangeEXRangeFinalize(CFTypeRef cf
) {
327 EXRangeRef rangeref
= (EXRangeRef
)cf
;
328 // nothing to finalize
331 static CFTypeID _kEXRangeID
= _kCFRuntimeNotATypeID
;
333 static CFRuntimeClass _kEXRangeClass
= {0};
335 /* Something external to this file is assumed to call this
336 * before the EXRange class is used.
338 void __EXRangeClassInitialize(void) {
339 _kEXRangeClass
.version
= 0;
340 _kEXRangeClass
.className
= "EXRange";
341 _kEXRangeClass
.init
= NULL
;
342 _kEXRangeClass
.copy
= NULL
;
343 _kEXRangeClass
.finalize
= __EXRangeEXRangeFinalize
;
344 _kEXRangeClass
.equal
= __EXRangeEqual
;
345 _kEXRangeClass
.hash
= __EXRangeHash
;
346 _kEXRangeClass
.copyFormattingDesc
= __EXRangeCopyFormattingDesc
;
347 _kEXRangeClass
.copyDebugDesc
= __EXRangeCopyDebugDesc
;
348 _kEXRangeID
= _CFRuntimeRegisterClass((const CFRuntimeClass
* const)&_kEXRangeClass
);
351 CFTypeID
EXRangeGetTypeID(void) {
355 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
) {
356 struct __EXRange
*newrange
;
357 uint32_t extra
= sizeof(struct __EXRange
) - sizeof(CFRuntimeBase
);
358 newrange
= (struct __EXRange
*)_CFRuntimeCreateInstance(allocator
, _kEXRangeID
, extra
, NULL
);
359 if (NULL
== newrange
) {
362 newrange
->_location
= location
;
363 newrange
->_length
= length
;
364 return (EXRangeRef
)newrange
;
367 uint32_t EXRangeGetLocation(EXRangeRef rangeref
) {
368 return rangeref
->_location
;
371 uint32_t EXRangeGetLength(EXRangeRef rangeref
) {
372 return rangeref
->_length
;
379 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */