]> git.saurik.com Git - apple/cf.git/blame - Base.subproj/CFRuntime.h
CF-368.28.tar.gz
[apple/cf.git] / Base.subproj / CFRuntime.h
CommitLineData
9ce05555 1/*
d8925383 2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
9ce05555
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
9ce05555
A
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/* CFRuntime.h
d8925383 24 Copyright (c) 1999-2005, Apple, Inc. All rights reserved.
9ce05555
A
25*/
26
27#if !defined(__COREFOUNDATION_CFRUNTIME__)
28#define __COREFOUNDATION_CFRUNTIME__ 1
29
30#include <CoreFoundation/CFBase.h>
31#include <CoreFoundation/CFDictionary.h>
32
33#if defined(__cplusplus)
34extern "C" {
35#endif
36
d8925383
A
37// GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging
38extern bool kCFUseCollectableAllocator;
39extern bool (*__CFObjCIsCollectable)(void *);
40extern const void* (*__CFObjCAssignIvar)(const void *value, const void *base, const void **slot);
41extern const void* (*__CFObjCStrongAssign)(const void *value, const void **slot);
42extern void* (*__CFObjCMemmoveCollectable)(void *dest, const void *src, unsigned);
43extern void (*__CFObjCWriteBarrierRange)(void *, unsigned);
44
45// GC: primitives.
46// is GC on?
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)
52
53// XXX_PCB for generational GC support.
54
55CF_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);
58 else
59 return (*lvalue = rvalue);
60}
61
62CF_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);
65 else
66 return (*lvalue = rvalue);
67}
68
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))
71
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))
74
75// Write-barrier memory move.
76#define CF_WRITE_BARRIER_MEMMOVE(dst, src, size) __CFObjCMemmoveCollectable(dst, src, size)
77
78// Used by frameworks to assert they "KNOW WHAT THEY'RE DOING under GC."
79CF_EXPORT CFAllocatorRef _CFAllocatorCreateGC(CFAllocatorRef allocator, CFAllocatorContext *context);
80
81// Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
82CF_EXPORT void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint);
83CF_EXPORT void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint);
84CF_EXPORT void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr);
85
9ce05555 86enum {
d8925383
A
87 _kCFRuntimeNotATypeID = 0,
88 _kCFRuntimeScannedObject = (1 << 0)
9ce05555
A
89};
90
91typedef struct __CFRuntimeClass { // Version 0 struct
92 CFIndex version;
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);
98#else
99 void (*dealloc)(CFTypeRef cf);
100#endif
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
105} CFRuntimeClass;
106
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.
110 */
111
112CF_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
116 * copied.
117 *
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
121 * may NOT be NULL.
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
157 * a hash.
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.
169 *
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.
177 *
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.
182 */
183
184CF_EXPORT const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID);
185 /* Returns the pointer to the CFRuntimeClass which was
186 * assigned the specified CFTypeID.
187 */
188
189CF_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).
193 *
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.
198 */
199
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.
205 */
206typedef struct __CFRuntimeBase {
207 void *_isa;
d8925383 208#if defined(__ppc__) || defined(__ppc64__)
9ce05555
A
209 uint16_t _rc;
210 uint16_t _info;
211#elif defined(__i386__)
212 uint16_t _info;
213 uint16_t _rc;
214#else
215#error unknown architecture
216#endif
217} CFRuntimeBase;
218
d8925383 219#if defined(__ppc__) || defined(__ppc64__)
9ce05555
A
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 }
d8925383 223#else
9ce05555
A
224#error unknown architecture
225#endif
226
227CF_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.
243 */
244
245CF_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
250 * as faulting.
251 */
252
253#if 0
254// ========================= EXAMPLE =========================
255
256// Example: EXRange -- a "range" object, which keeps the starting
257// location and length of the range. ("EX" as in "EXample").
258
259// ---- API ----
260
261typedef const struct __EXRange * EXRangeRef;
262
263CFTypeID EXRangeGetTypeID(void);
264
265EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length);
266
267uint32_t EXRangeGetLocation(EXRangeRef rangeref);
268uint32_t EXRangeGetLength(EXRangeRef rangeref);
269
270
271// ---- implementation ----
272
273#include <CoreFoundation/CFBase.h>
274#include <CoreFoundation/CFString.h>
275
276struct __EXRange {
277 CFRuntimeBase _base;
278 uint32_t _location;
279 uint32_t _length;
280};
281
282static 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;
287 return true;
288}
289
290static CFHashCode __EXRangeHash(CFTypeRef cf) {
291 EXRangeRef rangeref = (EXRangeRef)cf;
292 return (CFHashCode)(rangeref->_location + rangeref->_length);
293}
294
295static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) {
296 EXRangeRef rangeref = (EXRangeRef)cf;
297 return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts,
298 CFSTR("[%u, %u)"),
299 rangeref->_location,
300 rangeref->_location + rangeref->_length);
301}
302
303static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) {
304 EXRangeRef rangeref = (EXRangeRef)cf;
305 return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL,
306 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
307 rangeref,
308 CFGetAllocator(rangeref),
309 rangeref->_location,
310 rangeref->_length);
311}
312
313static void __EXRangeEXRangeFinalize(CFTypeRef cf) {
314 EXRangeRef rangeref = (EXRangeRef)cf;
315 // nothing to finalize
316}
317
318static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID;
319
320static CFRuntimeClass _kEXRangeClass = {0};
321
322/* Something external to this file is assumed to call this
323 * before the EXRange class is used.
324 */
325void __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);
336}
337
338CFTypeID EXRangeGetTypeID(void) {
339 return _kEXRangeID;
340}
341
342EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) {
343 struct __EXRange *newrange;
344 uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase);
d8925383 345 newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL);
9ce05555
A
346 if (NULL == newrange) {
347 return NULL;
348 }
349 newrange->_location = location;
350 newrange->_length = length;
351 return (EXRangeRef)newrange;
352}
353
354uint32_t EXRangeGetLocation(EXRangeRef rangeref) {
355 return rangeref->_location;
356}
357
358uint32_t EXRangeGetLength(EXRangeRef rangeref) {
359 return rangeref->_length;
360}
361
362#endif
363
364#if defined(__cplusplus)
365}
366#endif
367
368#endif /* ! __COREFOUNDATION_CFRUNTIME__ */