2 * Copyright (c) 2010 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@
25 Copyright (c) 1999-2009, Apple Inc. All rights reserved.
28 #if !defined(__COREFOUNDATION_CFRUNTIME__)
29 #define __COREFOUNDATION_CFRUNTIME__ 1
31 #include <CoreFoundation/CFBase.h>
32 #include <CoreFoundation/CFDictionary.h>
37 // GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging
38 CF_EXPORT
bool kCFUseCollectableAllocator
;
39 CF_EXPORT
bool (*__CFObjCIsCollectable
)(void *);
43 #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator)
44 // is GC on and is this the GC allocator?
45 #define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (kCFUseCollectableAllocator && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
46 // is this allocated by the collector?
47 #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false)
51 _kCFRuntimeNotATypeID
= 0,
52 _kCFRuntimeScannedObject
= (1UL << 0),
53 /* _kCFRuntimeUncollectableObject = (1UL << 1), No longer used; obsolete. */
54 _kCFRuntimeResourcefulObject
= (1UL << 2)
57 typedef struct __CFRuntimeClass
{ // Version 0 struct
59 const char *className
;
60 void (*init
)(CFTypeRef cf
);
61 CFTypeRef (*copy
)(CFAllocatorRef allocator
, CFTypeRef cf
);
62 #if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
63 void (*finalize
)(CFTypeRef cf
);
65 void (*dealloc
)(CFTypeRef cf
);
67 Boolean (*equal
)(CFTypeRef cf1
, CFTypeRef cf2
);
68 CFHashCode (*hash
)(CFTypeRef cf
);
69 CFStringRef (*copyFormattingDesc
)(CFTypeRef cf
, CFDictionaryRef formatOptions
); // str with retain
70 CFStringRef (*copyDebugDesc
)(CFTypeRef cf
); // str with retain
71 #if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
72 #define CF_RECLAIM_AVAILABLE 1
73 void (*reclaim
)(CFTypeRef cf
);
77 #define RADAR_5115468_FIXED 1
79 /* Note that CF runtime class registration and unregistration is not currently
80 * thread-safe, which should not currently be a problem, as long as unregistration
81 * is done only when valid to do so.
84 CF_EXPORT CFTypeID
_CFRuntimeRegisterClass(const CFRuntimeClass
* const cls
);
85 /* Registers a new class with the CF runtime. Pass in a
86 * pointer to a CFRuntimeClass structure. The pointer is
87 * remembered by the CF runtime -- the structure is NOT
90 * - version field must be zero currently.
91 * - className field points to a null-terminated C string
92 * containing only ASCII (0 - 127) characters; this field
94 * - init field points to a function which classes can use to
95 * apply some generic initialization to instances as they
96 * are created; this function is called by both
97 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if
98 * this field is NULL, no function is called; the instance
99 * has been initialized enough that the polymorphic funcs
100 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(),
101 * and CFGetAllocator() are valid on it when the init
102 * function if any is called.
103 * - finalize field points to a function which destroys an
104 * instance when the retain count has fallen to zero; if
105 * this is NULL, finalization does nothing. Note that if
106 * the class-specific functions which create or initialize
107 * instances more fully decide that a half-initialized
108 * instance must be destroyed, the finalize function for
109 * that class has to be able to deal with half-initialized
110 * instances. The finalize function should NOT destroy the
111 * memory for the instance itself; that is done by the
112 * CF runtime after this finalize callout returns.
113 * - equal field points to an equality-testing function; this
114 * field may be NULL, in which case only pointer/reference
115 * equality is performed on instances of this class.
116 * Pointer equality is tested, and the type IDs are checked
117 * for equality, before this function is called (so, the
118 * two instances are not pointer-equal but are of the same
119 * class before this function is called).
120 * NOTE: the equal function must implement an immutable
121 * equality relation, satisfying the reflexive, symmetric,
122 * and transitive properties, and remains the same across
123 * time and immutable operations (that is, if equal(A,B) at
124 * some point, then later equal(A,B) provided neither
125 * A or B has been mutated).
126 * - hash field points to a hash-code-computing function for
127 * instances of this class; this field may be NULL in which
128 * case the pointer value of an instance is converted into
130 * NOTE: the hash function and equal function must satisfy
131 * the relationship "equal(A,B) implies hash(A) == hash(B)";
132 * that is, if two instances are equal, their hash codes must
133 * be equal too. (However, the converse is not true!)
134 * - copyFormattingDesc field points to a function returning a
135 * CFStringRef with a human-readable description of the
136 * instance; if this is NULL, the type does not have special
137 * human-readable string-formats.
138 * - copyDebugDesc field points to a function returning a
139 * CFStringRef with a debugging description of the instance;
140 * if this is NULL, a simple description is generated.
142 * This function returns _kCFRuntimeNotATypeID on failure, or
143 * on success, returns the CFTypeID for the new class. This
144 * CFTypeID is what the class uses to allocate or initialize
145 * instances of the class. It is also returned from the
146 * conventional *GetTypeID() function, which returns the
147 * class's CFTypeID so that clients can compare the
148 * CFTypeID of instances with that of a class.
150 * The function to compute a human-readable string is very
151 * optional, and is really only interesting for classes,
152 * like strings or numbers, where it makes sense to format
153 * the instance using just its contents.
156 CF_EXPORT
const CFRuntimeClass
* _CFRuntimeGetClassWithTypeID(CFTypeID typeID
);
157 /* Returns the pointer to the CFRuntimeClass which was
158 * assigned the specified CFTypeID.
161 CF_EXPORT
void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID
);
162 /* Unregisters the class with the given type ID. It is
163 * undefined whether type IDs are reused or not (expect
164 * that they will be).
166 * Whether or not unregistering the class is a good idea or
167 * not is not CF's responsibility. In particular you must
168 * be quite sure all instances are gone, and there are no
169 * valid weak refs to such in other threads.
172 /* All CF "instances" start with this structure. Never refer to
173 * these fields directly -- they are for CF's use and may be added
174 * to or removed or change format without warning. Binary
175 * compatibility for uses of this struct is not guaranteed from
176 * release to release.
178 typedef struct __CFRuntimeBase
{
187 #define INIT_CFRUNTIME_BASE(...) {0, {0, 0, 0, 0x80}}
189 #define INIT_CFRUNTIME_BASE(...) {0, {0x80, 0, 0, 0}}
192 CF_EXPORT CFTypeRef
_CFRuntimeCreateInstance(CFAllocatorRef allocator
, CFTypeID typeID
, CFIndex extraBytes
, unsigned char *category
);
193 /* Creates a new CF instance of the class specified by the
194 * given CFTypeID, using the given allocator, and returns it.
195 * If the allocator returns NULL, this function returns NULL.
196 * A CFRuntimeBase structure is initialized at the beginning
197 * of the returned instance. extraBytes is the additional
198 * number of bytes to allocate for the instance (BEYOND that
199 * needed for the CFRuntimeBase). If the specified CFTypeID
200 * is unknown to the CF runtime, this function returns NULL.
201 * No part of the new memory other than base header is
202 * initialized (the extra bytes are not zeroed, for example).
203 * All instances created with this function must be destroyed
204 * only through use of the CFRelease() function -- instances
205 * must not be destroyed by using CFAllocatorDeallocate()
206 * directly, even in the initialization or creation functions
207 * of a class. Pass NULL for the category parameter.
210 CF_EXPORT
void _CFRuntimeSetInstanceTypeID(CFTypeRef cf
, CFTypeID typeID
);
211 /* This function changes the typeID of the given instance.
212 * If the specified CFTypeID is unknown to the CF runtime,
213 * this function does nothing. This function CANNOT be used
214 * to initialize an instance. It is for advanced usages such
218 CF_EXPORT
void _CFRuntimeInitStaticInstance(void *memory
, CFTypeID typeID
);
219 /* This function initializes a memory block to be a constant
220 * (unreleaseable) CF object of the given typeID.
221 * If the specified CFTypeID is unknown to the CF runtime,
222 * this function does nothing. The memory block should
223 * be a chunk of in-binary writeable static memory, and at
224 * least as large as sizeof(CFRuntimeBase) on the platform
225 * the code is being compiled for. The init function of the
226 * CFRuntimeClass is invoked on the memory as well, if the
229 #define CF_HAS_INIT_STATIC_INSTANCE 1
232 // ========================= EXAMPLE =========================
234 // Example: EXRange -- a "range" object, which keeps the starting
235 // location and length of the range. ("EX" as in "EXample").
239 typedef const struct __EXRange
* EXRangeRef
;
241 CFTypeID
EXRangeGetTypeID(void);
243 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
);
245 uint32_t EXRangeGetLocation(EXRangeRef rangeref
);
246 uint32_t EXRangeGetLength(EXRangeRef rangeref
);
249 // ---- implementation ----
251 #include <CoreFoundation/CFBase.h>
252 #include <CoreFoundation/CFString.h>
260 static Boolean
__EXRangeEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
261 EXRangeRef rangeref1
= (EXRangeRef
)cf1
;
262 EXRangeRef rangeref2
= (EXRangeRef
)cf2
;
263 if (rangeref1
->_location
!= rangeref2
->_location
) return false;
264 if (rangeref1
->_length
!= rangeref2
->_length
) return false;
268 static CFHashCode
__EXRangeHash(CFTypeRef cf
) {
269 EXRangeRef rangeref
= (EXRangeRef
)cf
;
270 return (CFHashCode
)(rangeref
->_location
+ rangeref
->_length
);
273 static CFStringRef
__EXRangeCopyFormattingDesc(CFTypeRef cf
, CFDictionaryRef formatOpts
) {
274 EXRangeRef rangeref
= (EXRangeRef
)cf
;
275 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), formatOpts
,
278 rangeref
->_location
+ rangeref
->_length
);
281 static CFStringRef
__EXRangeCopyDebugDesc(CFTypeRef cf
) {
282 EXRangeRef rangeref
= (EXRangeRef
)cf
;
283 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), NULL
,
284 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
286 CFGetAllocator(rangeref
),
291 static void __EXRangeEXRangeFinalize(CFTypeRef cf
) {
292 EXRangeRef rangeref
= (EXRangeRef
)cf
;
293 // nothing to finalize
296 static CFTypeID _kEXRangeID
= _kCFRuntimeNotATypeID
;
298 static CFRuntimeClass _kEXRangeClass
= {0};
300 /* Something external to this file is assumed to call this
301 * before the EXRange class is used.
303 void __EXRangeClassInitialize(void) {
304 _kEXRangeClass
.version
= 0;
305 _kEXRangeClass
.className
= "EXRange";
306 _kEXRangeClass
.init
= NULL
;
307 _kEXRangeClass
.copy
= NULL
;
308 _kEXRangeClass
.finalize
= __EXRangeEXRangeFinalize
;
309 _kEXRangeClass
.equal
= __EXRangeEqual
;
310 _kEXRangeClass
.hash
= __EXRangeHash
;
311 _kEXRangeClass
.copyFormattingDesc
= __EXRangeCopyFormattingDesc
;
312 _kEXRangeClass
.copyDebugDesc
= __EXRangeCopyDebugDesc
;
313 _kEXRangeID
= _CFRuntimeRegisterClass((const CFRuntimeClass
* const)&_kEXRangeClass
);
316 CFTypeID
EXRangeGetTypeID(void) {
320 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
) {
321 struct __EXRange
*newrange
;
322 uint32_t extra
= sizeof(struct __EXRange
) - sizeof(CFRuntimeBase
);
323 newrange
= (struct __EXRange
*)_CFRuntimeCreateInstance(allocator
, _kEXRangeID
, extra
, NULL
);
324 if (NULL
== newrange
) {
327 newrange
->_location
= location
;
328 newrange
->_length
= length
;
329 return (EXRangeRef
)newrange
;
332 uint32_t EXRangeGetLocation(EXRangeRef rangeref
) {
333 return rangeref
->_location
;
336 uint32_t EXRangeGetLength(EXRangeRef rangeref
) {
337 return rangeref
->_length
;
344 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */