2 * Copyright (c) 2005 Apple Computer, 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-2005, 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>
33 #if defined(__cplusplus)
37 // GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging
38 extern bool kCFUseCollectableAllocator
;
39 extern bool (*__CFObjCIsCollectable
)(void *);
40 extern const void* (*__CFObjCAssignIvar
)(const void *value
, const void *base
, const void **slot
);
41 extern const void* (*__CFObjCStrongAssign
)(const void *value
, const void **slot
);
42 extern void* (*__CFObjCMemmoveCollectable
)(void *dest
, const void *src
, unsigned);
43 extern void (*__CFObjCWriteBarrierRange
)(void *, unsigned);
47 #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator)
48 // is GC on and is this the GC allocator?
49 #define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (CF_USING_COLLECTABLE_MEMORY && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
50 // is this allocated by the collector?
51 #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false)
53 // XXX_PCB for generational GC support.
55 CF_INLINE
const void* __CFAssignIvar(CFAllocatorRef allocator
, const void *rvalue
, const void *base
, const void **lvalue
) {
56 if (rvalue
&& CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
57 return __CFObjCAssignIvar(rvalue
, base
, lvalue
);
59 return (*lvalue
= rvalue
);
62 CF_INLINE
const void* __CFStrongAssign(CFAllocatorRef allocator
, const void *rvalue
, const void **lvalue
) {
63 if (rvalue
&& CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
64 return __CFObjCStrongAssign(rvalue
, lvalue
);
66 return (*lvalue
= rvalue
);
69 // Use this form when the base pointer to the object is known.
70 #define CF_WRITE_BARRIER_BASE_ASSIGN(allocator, base, lvalue, rvalue) __CFAssignIvar(allocator, (const void*)rvalue, (const void*)base, (const void**)&(lvalue))
72 // Use this form when the base pointer to the object isn't known.
73 #define CF_WRITE_BARRIER_ASSIGN(allocator, lvalue, rvalue) __CFStrongAssign(allocator, (const void*)rvalue, (const void**)&(lvalue))
75 // Write-barrier memory move.
76 #define CF_WRITE_BARRIER_MEMMOVE(dst, src, size) __CFObjCMemmoveCollectable(dst, src, size)
78 // Used by frameworks to assert they "KNOW WHAT THEY'RE DOING under GC."
79 CF_EXPORT CFAllocatorRef
_CFAllocatorCreateGC(CFAllocatorRef allocator
, CFAllocatorContext
*context
);
81 // Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
82 CF_EXPORT
void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
);
83 CF_EXPORT
void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
);
84 CF_EXPORT
void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
);
87 _kCFRuntimeNotATypeID
= 0,
88 _kCFRuntimeScannedObject
= (1 << 0)
91 typedef struct __CFRuntimeClass
{ // Version 0 struct
93 const char *className
;
94 void (*init
)(CFTypeRef cf
);
95 CFTypeRef (*copy
)(CFAllocatorRef allocator
, CFTypeRef cf
);
96 #if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
97 void (*finalize
)(CFTypeRef cf
);
99 void (*dealloc
)(CFTypeRef cf
);
101 Boolean (*equal
)(CFTypeRef cf1
, CFTypeRef cf2
);
102 CFHashCode (*hash
)(CFTypeRef cf
);
103 CFStringRef (*copyFormattingDesc
)(CFTypeRef cf
, CFDictionaryRef formatOptions
); // str with retain
104 CFStringRef (*copyDebugDesc
)(CFTypeRef cf
); // str with retain
107 /* Note that CF runtime class registration and unregistration is not currently
108 * thread-safe, which should not currently be a problem, as long as unregistration
109 * is done only when valid to do so.
112 CF_EXPORT CFTypeID
_CFRuntimeRegisterClass(const CFRuntimeClass
* const cls
);
113 /* Registers a new class with the CF runtime. Pass in a
114 * pointer to a CFRuntimeClass structure. The pointer is
115 * remembered by the CF runtime -- the structure is NOT
118 * - version field must be zero currently.
119 * - className field points to a null-terminated C string
120 * containing only ASCII (0 - 127) characters; this field
122 * - init field points to a function which classes can use to
123 * apply some generic initialization to instances as they
124 * are created; this function is called by both
125 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if
126 * this field is NULL, no function is called; the instance
127 * has been initialized enough that the polymorphic funcs
128 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(),
129 * and CFGetAllocator() are valid on it when the init
130 * function if any is called.
131 * - finalize field points to a function which destroys an
132 * instance when the retain count has fallen to zero; if
133 * this is NULL, finalization does nothing. Note that if
134 * the class-specific functions which create or initialize
135 * instances more fully decide that a half-initialized
136 * instance must be destroyed, the finalize function for
137 * that class has to be able to deal with half-initialized
138 * instances. The finalize function should NOT destroy the
139 * memory for the instance itself; that is done by the
140 * CF runtime after this finalize callout returns.
141 * - equal field points to an equality-testing function; this
142 * field may be NULL, in which case only pointer/reference
143 * equality is performed on instances of this class.
144 * Pointer equality is tested, and the type IDs are checked
145 * for equality, before this function is called (so, the
146 * two instances are not pointer-equal but are of the same
147 * class before this function is called).
148 * NOTE: the equal function must implement an immutable
149 * equality relation, satisfying the reflexive, symmetric,
150 * and transitive properties, and remains the same across
151 * time and immutable operations (that is, if equal(A,B) at
152 * some point, then later equal(A,B) provided neither
153 * A or B has been mutated).
154 * - hash field points to a hash-code-computing function for
155 * instances of this class; this field may be NULL in which
156 * case the pointer value of an instance is converted into
158 * NOTE: the hash function and equal function must satisfy
159 * the relationship "equal(A,B) implies hash(A) == hash(B)";
160 * that is, if two instances are equal, their hash codes must
161 * be equal too. (However, the converse is not true!)
162 * - copyFormattingDesc field points to a function returning a
163 * CFStringRef with a human-readable description of the
164 * instance; if this is NULL, the type does not have special
165 * human-readable string-formats.
166 * - copyDebugDesc field points to a function returning a
167 * CFStringRef with a debugging description of the instance;
168 * if this is NULL, a simple description is generated.
170 * This function returns _kCFRuntimeNotATypeID on failure, or
171 * on success, returns the CFTypeID for the new class. This
172 * CFTypeID is what the class uses to allocate or initialize
173 * instances of the class. It is also returned from the
174 * conventional *GetTypeID() function, which returns the
175 * class's CFTypeID so that clients can compare the
176 * CFTypeID of instances with that of a class.
178 * The function to compute a human-readable string is very
179 * optional, and is really only interesting for classes,
180 * like strings or numbers, where it makes sense to format
181 * the instance using just its contents.
184 CF_EXPORT
const CFRuntimeClass
* _CFRuntimeGetClassWithTypeID(CFTypeID typeID
);
185 /* Returns the pointer to the CFRuntimeClass which was
186 * assigned the specified CFTypeID.
189 CF_EXPORT
void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID
);
190 /* Unregisters the class with the given type ID. It is
191 * undefined whether type IDs are reused or not (expect
192 * that they will be).
194 * Whether or not unregistering the class is a good idea or
195 * not is not CF's responsibility. In particular you must
196 * be quite sure all instances are gone, and there are no
197 * valid weak refs to such in other threads.
200 /* All CF "instances" start with this structure. Never refer to
201 * these fields directly -- they are for CF's use and may be added
202 * to or removed or change format without warning. Binary
203 * compatibility for uses of this struct is not guaranteed from
204 * release to release.
206 typedef struct __CFRuntimeBase
{
208 #if defined(__ppc__) || defined(__ppc64__)
211 #elif defined(__i386__)
215 #error unknown architecture
219 #if defined(__ppc__) || defined(__ppc64__)
220 #define INIT_CFRUNTIME_BASE(isa, info, rc) { isa, info, rc }
221 #elif defined(__i386__)
222 #define INIT_CFRUNTIME_BASE(isa, info, rc) { isa, rc, info }
224 #error unknown architecture
227 CF_EXPORT CFTypeRef
_CFRuntimeCreateInstance(CFAllocatorRef allocator
, CFTypeID typeID
, uint32_t 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
254 // ========================= EXAMPLE =========================
256 // Example: EXRange -- a "range" object, which keeps the starting
257 // location and length of the range. ("EX" as in "EXample").
261 typedef const struct __EXRange
* EXRangeRef
;
263 CFTypeID
EXRangeGetTypeID(void);
265 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
);
267 uint32_t EXRangeGetLocation(EXRangeRef rangeref
);
268 uint32_t EXRangeGetLength(EXRangeRef rangeref
);
271 // ---- implementation ----
273 #include <CoreFoundation/CFBase.h>
274 #include <CoreFoundation/CFString.h>
282 static Boolean
__EXRangeEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
283 EXRangeRef rangeref1
= (EXRangeRef
)cf1
;
284 EXRangeRef rangeref2
= (EXRangeRef
)cf2
;
285 if (rangeref1
->_location
!= rangeref2
->_location
) return false;
286 if (rangeref1
->_length
!= rangeref2
->_length
) return false;
290 static CFHashCode
__EXRangeHash(CFTypeRef cf
) {
291 EXRangeRef rangeref
= (EXRangeRef
)cf
;
292 return (CFHashCode
)(rangeref
->_location
+ rangeref
->_length
);
295 static CFStringRef
__EXRangeCopyFormattingDesc(CFTypeRef cf
, CFDictionaryRef formatOpts
) {
296 EXRangeRef rangeref
= (EXRangeRef
)cf
;
297 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), formatOpts
,
300 rangeref
->_location
+ rangeref
->_length
);
303 static CFStringRef
__EXRangeCopyDebugDesc(CFTypeRef cf
) {
304 EXRangeRef rangeref
= (EXRangeRef
)cf
;
305 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), NULL
,
306 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
308 CFGetAllocator(rangeref
),
313 static void __EXRangeEXRangeFinalize(CFTypeRef cf
) {
314 EXRangeRef rangeref
= (EXRangeRef
)cf
;
315 // nothing to finalize
318 static CFTypeID _kEXRangeID
= _kCFRuntimeNotATypeID
;
320 static CFRuntimeClass _kEXRangeClass
= {0};
322 /* Something external to this file is assumed to call this
323 * before the EXRange class is used.
325 void __EXRangeClassInitialize(void) {
326 _kEXRangeClass
.version
= 0;
327 _kEXRangeClass
.className
= "EXRange";
328 _kEXRangeClass
.init
= NULL
;
329 _kEXRangeClass
.copy
= NULL
;
330 _kEXRangeClass
.finalize
= __EXRangeEXRangeFinalize
;
331 _kEXRangeClass
.equal
= __EXRangeEqual
;
332 _kEXRangeClass
.hash
= __EXRangeHash
;
333 _kEXRangeClass
.copyFormattingDesc
= __EXRangeCopyFormattingDesc
;
334 _kEXRangeClass
.copyDebugDesc
= __EXRangeCopyDebugDesc
;
335 _kEXRangeID
= _CFRuntimeRegisterClass((const CFRuntimeClass
* const)&_kEXRangeClass
);
338 CFTypeID
EXRangeGetTypeID(void) {
342 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
) {
343 struct __EXRange
*newrange
;
344 uint32_t extra
= sizeof(struct __EXRange
) - sizeof(CFRuntimeBase
);
345 newrange
= (struct __EXRange
*)_CFRuntimeCreateInstance(allocator
, _kEXRangeID
, extra
, NULL
);
346 if (NULL
== newrange
) {
349 newrange
->_location
= location
;
350 newrange
->_length
= length
;
351 return (EXRangeRef
)newrange
;
354 uint32_t EXRangeGetLocation(EXRangeRef rangeref
) {
355 return rangeref
->_location
;
358 uint32_t EXRangeGetLength(EXRangeRef rangeref
) {
359 return rangeref
->_length
;
364 #if defined(__cplusplus)
368 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */