]> git.saurik.com Git - apple/cf.git/blob - CFRuntime.h
CF-550.19.tar.gz
[apple/cf.git] / CFRuntime.h
1 /*
2 * Copyright (c) 2010 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-2009, 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
35 CF_EXTERN_C_BEGIN
36
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 *);
40
41 // GC: primitives.
42 // is GC on?
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)
48
49
50 enum {
51 _kCFRuntimeNotATypeID = 0,
52 _kCFRuntimeScannedObject = (1UL << 0),
53 /* _kCFRuntimeUncollectableObject = (1UL << 1), No longer used; obsolete. */
54 _kCFRuntimeResourcefulObject = (1UL << 2)
55 };
56
57 typedef struct __CFRuntimeClass { // Version 0 struct
58 CFIndex version;
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);
64 #else
65 void (*dealloc)(CFTypeRef cf);
66 #endif
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);
74 #endif
75 } CFRuntimeClass;
76
77 #define RADAR_5115468_FIXED 1
78
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.
82 */
83
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
88 * copied.
89 *
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
93 * may NOT be NULL.
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
129 * a hash.
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.
141 *
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.
149 *
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.
154 */
155
156 CF_EXPORT const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID);
157 /* Returns the pointer to the CFRuntimeClass which was
158 * assigned the specified CFTypeID.
159 */
160
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).
165 *
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.
170 */
171
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.
177 */
178 typedef struct __CFRuntimeBase {
179 uintptr_t _cfisa;
180 uint8_t _cfinfo[4];
181 #if __LP64__
182 uint32_t _rc;
183 #endif
184 } CFRuntimeBase;
185
186 #if __BIG_ENDIAN__
187 #define INIT_CFRUNTIME_BASE(...) {0, {0, 0, 0, 0x80}}
188 #else
189 #define INIT_CFRUNTIME_BASE(...) {0, {0x80, 0, 0, 0}}
190 #endif
191
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.
208 */
209
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
215 * as faulting.
216 */
217
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
227 * class has one.
228 */
229 #define CF_HAS_INIT_STATIC_INSTANCE 1
230
231 #if 0
232 // ========================= EXAMPLE =========================
233
234 // Example: EXRange -- a "range" object, which keeps the starting
235 // location and length of the range. ("EX" as in "EXample").
236
237 // ---- API ----
238
239 typedef const struct __EXRange * EXRangeRef;
240
241 CFTypeID EXRangeGetTypeID(void);
242
243 EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length);
244
245 uint32_t EXRangeGetLocation(EXRangeRef rangeref);
246 uint32_t EXRangeGetLength(EXRangeRef rangeref);
247
248
249 // ---- implementation ----
250
251 #include <CoreFoundation/CFBase.h>
252 #include <CoreFoundation/CFString.h>
253
254 struct __EXRange {
255 CFRuntimeBase _base;
256 uint32_t _location;
257 uint32_t _length;
258 };
259
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;
265 return true;
266 }
267
268 static CFHashCode __EXRangeHash(CFTypeRef cf) {
269 EXRangeRef rangeref = (EXRangeRef)cf;
270 return (CFHashCode)(rangeref->_location + rangeref->_length);
271 }
272
273 static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) {
274 EXRangeRef rangeref = (EXRangeRef)cf;
275 return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts,
276 CFSTR("[%u, %u)"),
277 rangeref->_location,
278 rangeref->_location + rangeref->_length);
279 }
280
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}"),
285 rangeref,
286 CFGetAllocator(rangeref),
287 rangeref->_location,
288 rangeref->_length);
289 }
290
291 static void __EXRangeEXRangeFinalize(CFTypeRef cf) {
292 EXRangeRef rangeref = (EXRangeRef)cf;
293 // nothing to finalize
294 }
295
296 static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID;
297
298 static CFRuntimeClass _kEXRangeClass = {0};
299
300 /* Something external to this file is assumed to call this
301 * before the EXRange class is used.
302 */
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);
314 }
315
316 CFTypeID EXRangeGetTypeID(void) {
317 return _kEXRangeID;
318 }
319
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) {
325 return NULL;
326 }
327 newrange->_location = location;
328 newrange->_length = length;
329 return (EXRangeRef)newrange;
330 }
331
332 uint32_t EXRangeGetLocation(EXRangeRef rangeref) {
333 return rangeref->_location;
334 }
335
336 uint32_t EXRangeGetLength(EXRangeRef rangeref) {
337 return rangeref->_length;
338 }
339
340 #endif
341
342 CF_EXTERN_C_END
343
344 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */