]> git.saurik.com Git - apple/cf.git/blob - Base.subproj/CFRuntime.h
CF-299.tar.gz
[apple/cf.git] / Base.subproj / CFRuntime.h
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* CFRuntime.h
26 Copyright (c) 1999-2003, Apple, Inc. All rights reserved.
27 */
28
29 #if !defined(__COREFOUNDATION_CFRUNTIME__)
30 #define __COREFOUNDATION_CFRUNTIME__ 1
31
32 #include <CoreFoundation/CFBase.h>
33 #include <CoreFoundation/CFDictionary.h>
34
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38
39 enum {
40 _kCFRuntimeNotATypeID = 0
41 };
42
43 typedef struct __CFRuntimeClass { // Version 0 struct
44 CFIndex version;
45 const char *className;
46 void (*init)(CFTypeRef cf);
47 CFTypeRef (*copy)(CFAllocatorRef allocator, CFTypeRef cf);
48 #if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
49 void (*finalize)(CFTypeRef cf);
50 #else
51 void (*dealloc)(CFTypeRef cf);
52 #endif
53 Boolean (*equal)(CFTypeRef cf1, CFTypeRef cf2);
54 CFHashCode (*hash)(CFTypeRef cf);
55 CFStringRef (*copyFormattingDesc)(CFTypeRef cf, CFDictionaryRef formatOptions); // str with retain
56 CFStringRef (*copyDebugDesc)(CFTypeRef cf); // str with retain
57 } CFRuntimeClass;
58
59 /* Note that CF runtime class registration and unregistration is not currently
60 * thread-safe, which should not currently be a problem, as long as unregistration
61 * is done only when valid to do so.
62 */
63
64 CF_EXPORT CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls);
65 /* Registers a new class with the CF runtime. Pass in a
66 * pointer to a CFRuntimeClass structure. The pointer is
67 * remembered by the CF runtime -- the structure is NOT
68 * copied.
69 *
70 * - version field must be zero currently.
71 * - className field points to a null-terminated C string
72 * containing only ASCII (0 - 127) characters; this field
73 * may NOT be NULL.
74 * - init field points to a function which classes can use to
75 * apply some generic initialization to instances as they
76 * are created; this function is called by both
77 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if
78 * this field is NULL, no function is called; the instance
79 * has been initialized enough that the polymorphic funcs
80 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(),
81 * and CFGetAllocator() are valid on it when the init
82 * function if any is called.
83 * - finalize field points to a function which destroys an
84 * instance when the retain count has fallen to zero; if
85 * this is NULL, finalization does nothing. Note that if
86 * the class-specific functions which create or initialize
87 * instances more fully decide that a half-initialized
88 * instance must be destroyed, the finalize function for
89 * that class has to be able to deal with half-initialized
90 * instances. The finalize function should NOT destroy the
91 * memory for the instance itself; that is done by the
92 * CF runtime after this finalize callout returns.
93 * - equal field points to an equality-testing function; this
94 * field may be NULL, in which case only pointer/reference
95 * equality is performed on instances of this class.
96 * Pointer equality is tested, and the type IDs are checked
97 * for equality, before this function is called (so, the
98 * two instances are not pointer-equal but are of the same
99 * class before this function is called).
100 * NOTE: the equal function must implement an immutable
101 * equality relation, satisfying the reflexive, symmetric,
102 * and transitive properties, and remains the same across
103 * time and immutable operations (that is, if equal(A,B) at
104 * some point, then later equal(A,B) provided neither
105 * A or B has been mutated).
106 * - hash field points to a hash-code-computing function for
107 * instances of this class; this field may be NULL in which
108 * case the pointer value of an instance is converted into
109 * a hash.
110 * NOTE: the hash function and equal function must satisfy
111 * the relationship "equal(A,B) implies hash(A) == hash(B)";
112 * that is, if two instances are equal, their hash codes must
113 * be equal too. (However, the converse is not true!)
114 * - copyFormattingDesc field points to a function returning a
115 * CFStringRef with a human-readable description of the
116 * instance; if this is NULL, the type does not have special
117 * human-readable string-formats.
118 * - copyDebugDesc field points to a function returning a
119 * CFStringRef with a debugging description of the instance;
120 * if this is NULL, a simple description is generated.
121 *
122 * This function returns _kCFRuntimeNotATypeID on failure, or
123 * on success, returns the CFTypeID for the new class. This
124 * CFTypeID is what the class uses to allocate or initialize
125 * instances of the class. It is also returned from the
126 * conventional *GetTypeID() function, which returns the
127 * class's CFTypeID so that clients can compare the
128 * CFTypeID of instances with that of a class.
129 *
130 * The function to compute a human-readable string is very
131 * optional, and is really only interesting for classes,
132 * like strings or numbers, where it makes sense to format
133 * the instance using just its contents.
134 */
135
136 CF_EXPORT const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID);
137 /* Returns the pointer to the CFRuntimeClass which was
138 * assigned the specified CFTypeID.
139 */
140
141 CF_EXPORT void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID);
142 /* Unregisters the class with the given type ID. It is
143 * undefined whether type IDs are reused or not (expect
144 * that they will be).
145 *
146 * Whether or not unregistering the class is a good idea or
147 * not is not CF's responsibility. In particular you must
148 * be quite sure all instances are gone, and there are no
149 * valid weak refs to such in other threads.
150 */
151
152 /* All CF "instances" start with this structure. Never refer to
153 * these fields directly -- they are for CF's use and may be added
154 * to or removed or change format without warning. Binary
155 * compatibility for uses of this struct is not guaranteed from
156 * release to release.
157 */
158 typedef struct __CFRuntimeBase {
159 void *_isa;
160 #if defined(__ppc__)
161 uint16_t _rc;
162 uint16_t _info;
163 #elif defined(__i386__)
164 uint16_t _info;
165 uint16_t _rc;
166 #else
167 #error unknown architecture
168 #endif
169 } CFRuntimeBase;
170
171 #if defined(__ppc__)
172 #define INIT_CFRUNTIME_BASE(isa, info, rc) { isa, info, rc }
173 #elif defined(__i386__)
174 #define INIT_CFRUNTIME_BASE(isa, info, rc) { isa, rc, info }
175 #elif
176 #error unknown architecture
177 #endif
178
179 CF_EXPORT CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, uint32_t extraBytes, unsigned char *category);
180 /* Creates a new CF instance of the class specified by the
181 * given CFTypeID, using the given allocator, and returns it.
182 * If the allocator returns NULL, this function returns NULL.
183 * A CFRuntimeBase structure is initialized at the beginning
184 * of the returned instance. extraBytes is the additional
185 * number of bytes to allocate for the instance (BEYOND that
186 * needed for the CFRuntimeBase). If the specified CFTypeID
187 * is unknown to the CF runtime, this function returns NULL.
188 * No part of the new memory other than base header is
189 * initialized (the extra bytes are not zeroed, for example).
190 * All instances created with this function must be destroyed
191 * only through use of the CFRelease() function -- instances
192 * must not be destroyed by using CFAllocatorDeallocate()
193 * directly, even in the initialization or creation functions
194 * of a class. Pass NULL for the category parameter.
195 */
196
197 CF_EXPORT void _CFRuntimeSetInstanceTypeID(CFTypeRef cf, CFTypeID typeID);
198 /* This function changes the typeID of the given instance.
199 * If the specified CFTypeID is unknown to the CF runtime,
200 * this function does nothing. This function CANNOT be used
201 * to initialize an instance. It is for advanced usages such
202 * as faulting.
203 */
204
205 #if 0
206 // ========================= EXAMPLE =========================
207
208 // Example: EXRange -- a "range" object, which keeps the starting
209 // location and length of the range. ("EX" as in "EXample").
210
211 // ---- API ----
212
213 typedef const struct __EXRange * EXRangeRef;
214
215 CFTypeID EXRangeGetTypeID(void);
216
217 EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length);
218
219 uint32_t EXRangeGetLocation(EXRangeRef rangeref);
220 uint32_t EXRangeGetLength(EXRangeRef rangeref);
221
222
223 // ---- implementation ----
224
225 #include <CoreFoundation/CFBase.h>
226 #include <CoreFoundation/CFString.h>
227
228 struct __EXRange {
229 CFRuntimeBase _base;
230 uint32_t _location;
231 uint32_t _length;
232 };
233
234 static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) {
235 EXRangeRef rangeref1 = (EXRangeRef)cf1;
236 EXRangeRef rangeref2 = (EXRangeRef)cf2;
237 if (rangeref1->_location != rangeref2->_location) return false;
238 if (rangeref1->_length != rangeref2->_length) return false;
239 return true;
240 }
241
242 static CFHashCode __EXRangeHash(CFTypeRef cf) {
243 EXRangeRef rangeref = (EXRangeRef)cf;
244 return (CFHashCode)(rangeref->_location + rangeref->_length);
245 }
246
247 static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) {
248 EXRangeRef rangeref = (EXRangeRef)cf;
249 return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts,
250 CFSTR("[%u, %u)"),
251 rangeref->_location,
252 rangeref->_location + rangeref->_length);
253 }
254
255 static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) {
256 EXRangeRef rangeref = (EXRangeRef)cf;
257 return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL,
258 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
259 rangeref,
260 CFGetAllocator(rangeref),
261 rangeref->_location,
262 rangeref->_length);
263 }
264
265 static void __EXRangeEXRangeFinalize(CFTypeRef cf) {
266 EXRangeRef rangeref = (EXRangeRef)cf;
267 // nothing to finalize
268 }
269
270 static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID;
271
272 static CFRuntimeClass _kEXRangeClass = {0};
273
274 /* Something external to this file is assumed to call this
275 * before the EXRange class is used.
276 */
277 void __EXRangeClassInitialize(void) {
278 _kEXRangeClass.version = 0;
279 _kEXRangeClass.className = "EXRange";
280 _kEXRangeClass.init = NULL;
281 _kEXRangeClass.copy = NULL;
282 _kEXRangeClass.finalize = __EXRangeEXRangeFinalize;
283 _kEXRangeClass.equal = __EXRangeEqual;
284 _kEXRangeClass.hash = __EXRangeHash;
285 _kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc;
286 _kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc;
287 _kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass);
288 }
289
290 CFTypeID EXRangeGetTypeID(void) {
291 return _kEXRangeID;
292 }
293
294 EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) {
295 struct __EXRange *newrange;
296 uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase);
297 newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra);
298 if (NULL == newrange) {
299 return NULL;
300 }
301 newrange->_location = location;
302 newrange->_length = length;
303 return (EXRangeRef)newrange;
304 }
305
306 uint32_t EXRangeGetLocation(EXRangeRef rangeref) {
307 return rangeref->_location;
308 }
309
310 uint32_t EXRangeGetLength(EXRangeRef rangeref) {
311 return rangeref->_length;
312 }
313
314 #endif
315
316 #if defined(__cplusplus)
317 }
318 #endif
319
320 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */