2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
26 Copyright (c) 1999-2003, Apple, Inc. All rights reserved.
29 #if !defined(__COREFOUNDATION_CFRUNTIME__)
30 #define __COREFOUNDATION_CFRUNTIME__ 1
32 #include <CoreFoundation/CFBase.h>
33 #include <CoreFoundation/CFDictionary.h>
35 #if defined(__cplusplus)
40 _kCFRuntimeNotATypeID
= 0
43 typedef struct __CFRuntimeClass
{ // Version 0 struct
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
);
51 void (*dealloc
)(CFTypeRef cf
);
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
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.
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
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
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
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.
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.
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.
136 CF_EXPORT
const CFRuntimeClass
* _CFRuntimeGetClassWithTypeID(CFTypeID typeID
);
137 /* Returns the pointer to the CFRuntimeClass which was
138 * assigned the specified CFTypeID.
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).
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.
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.
158 typedef struct __CFRuntimeBase
{
163 #elif defined(__i386__)
167 #error unknown architecture
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 }
176 #error unknown architecture
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.
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
206 // ========================= EXAMPLE =========================
208 // Example: EXRange -- a "range" object, which keeps the starting
209 // location and length of the range. ("EX" as in "EXample").
213 typedef const struct __EXRange
* EXRangeRef
;
215 CFTypeID
EXRangeGetTypeID(void);
217 EXRangeRef
EXRangeCreate(CFAllocatorRef allocator
, uint32_t location
, uint32_t length
);
219 uint32_t EXRangeGetLocation(EXRangeRef rangeref
);
220 uint32_t EXRangeGetLength(EXRangeRef rangeref
);
223 // ---- implementation ----
225 #include <CoreFoundation/CFBase.h>
226 #include <CoreFoundation/CFString.h>
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;
242 static CFHashCode
__EXRangeHash(CFTypeRef cf
) {
243 EXRangeRef rangeref
= (EXRangeRef
)cf
;
244 return (CFHashCode
)(rangeref
->_location
+ rangeref
->_length
);
247 static CFStringRef
__EXRangeCopyFormattingDesc(CFTypeRef cf
, CFDictionaryRef formatOpts
) {
248 EXRangeRef rangeref
= (EXRangeRef
)cf
;
249 return CFStringCreateWithFormat(CFGetAllocator(rangeref
), formatOpts
,
252 rangeref
->_location
+ rangeref
->_length
);
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}"),
260 CFGetAllocator(rangeref
),
265 static void __EXRangeEXRangeFinalize(CFTypeRef cf
) {
266 EXRangeRef rangeref
= (EXRangeRef
)cf
;
267 // nothing to finalize
270 static CFTypeID _kEXRangeID
= _kCFRuntimeNotATypeID
;
272 static CFRuntimeClass _kEXRangeClass
= {0};
274 /* Something external to this file is assumed to call this
275 * before the EXRange class is used.
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
);
290 CFTypeID
EXRangeGetTypeID(void) {
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
) {
301 newrange
->_location
= location
;
302 newrange
->_length
= length
;
303 return (EXRangeRef
)newrange
;
306 uint32_t EXRangeGetLocation(EXRangeRef rangeref
) {
307 return rangeref
->_location
;
310 uint32_t EXRangeGetLength(EXRangeRef rangeref
) {
311 return rangeref
->_length
;
316 #if defined(__cplusplus)
320 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */