]>
Commit | Line | Data |
---|---|---|
9ce05555 A |
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 | /* CFData.c | |
26 | Copyright 1998-2002, Apple, Inc. All rights reserved. | |
27 | Responsibility: Christopher Kane | |
28 | */ | |
29 | ||
30 | #include <CoreFoundation/CFData.h> | |
31 | #include "CFUtilities.h" | |
32 | #include "CFInternal.h" | |
33 | #include <string.h> | |
34 | ||
35 | struct __CFData { | |
36 | CFRuntimeBase _base; | |
37 | CFIndex _length; /* number of bytes */ | |
38 | CFIndex _capacity; /* maximum number of bytes */ | |
39 | CFAllocatorRef _bytesDeallocator; /* used only for immutable; if NULL, no deallocation */ | |
40 | uint8_t *_bytes; | |
41 | }; | |
42 | ||
43 | /* Bits 3-2 are used for mutability variation */ | |
44 | ||
45 | CF_INLINE UInt32 __CFMutableVariety(const void *cf) { | |
46 | return __CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_info, 3, 2); | |
47 | } | |
48 | ||
49 | CF_INLINE void __CFSetMutableVariety(void *cf, UInt32 v) { | |
50 | __CFBitfieldSetValue(((CFRuntimeBase *)cf)->_info, 3, 2, v); | |
51 | } | |
52 | ||
53 | CF_INLINE UInt32 __CFMutableVarietyFromFlags(UInt32 flags) { | |
54 | return __CFBitfieldGetValue(flags, 1, 0); | |
55 | } | |
56 | ||
57 | #define __CFGenericValidateMutabilityFlags(flags) \ | |
58 | CFAssert2(__CFMutableVarietyFromFlags(flags) != 0x2, __kCFLogAssertion, "%s(): flags 0x%x do not correctly specify the mutable variety", __PRETTY_FUNCTION__, flags); | |
59 | ||
60 | CF_INLINE CFIndex __CFDataLength(CFDataRef data) { | |
61 | return data->_length; | |
62 | } | |
63 | ||
64 | CF_INLINE void __CFDataSetLength(CFMutableDataRef data, CFIndex v) { | |
65 | /* for a CFData, _bytesUsed == _length */ | |
66 | } | |
67 | ||
68 | CF_INLINE CFIndex __CFDataCapacity(CFDataRef data) { | |
69 | return data->_capacity; | |
70 | } | |
71 | ||
72 | CF_INLINE void __CFDataSetCapacity(CFMutableDataRef data, CFIndex v) { | |
73 | /* for a CFData, _bytesNum == _capacity */ | |
74 | } | |
75 | ||
76 | CF_INLINE CFIndex __CFDataNumBytesUsed(CFDataRef data) { | |
77 | return data->_length; | |
78 | } | |
79 | ||
80 | CF_INLINE void __CFDataSetNumBytesUsed(CFMutableDataRef data, CFIndex v) { | |
81 | data->_length = v; | |
82 | } | |
83 | ||
84 | CF_INLINE CFIndex __CFDataNumBytes(CFDataRef data) { | |
85 | return data->_capacity; | |
86 | } | |
87 | ||
88 | CF_INLINE void __CFDataSetNumBytes(CFMutableDataRef data, CFIndex v) { | |
89 | data->_capacity = v; | |
90 | } | |
91 | ||
92 | CF_INLINE CFIndex __CFDataRoundUpCapacity(CFIndex capacity) { | |
93 | if (capacity < 16) return 16; | |
94 | // CF: quite probably, this doubling should slow as the data gets larger and larger; should not use strict doubling | |
95 | return (1 << (CFLog2(capacity) + 1)); | |
96 | } | |
97 | ||
98 | CF_INLINE CFIndex __CFDataNumBytesForCapacity(CFIndex capacity) { | |
99 | return capacity; | |
100 | } | |
101 | ||
102 | #if defined(DEBUG) | |
103 | CF_INLINE void __CFDataValidateRange(CFDataRef data, CFRange range, const char *func) { | |
104 | CFAssert2(0 <= range.location && range.location <= __CFDataLength(data), __kCFLogAssertion, "%s(): range.location index (%d) out of bounds", func, range.location); | |
105 | CFAssert2(0 <= range.length, __kCFLogAssertion, "%s(): length (%d) cannot be less than zero", func, range.length); | |
106 | CFAssert2(range.location + range.length <= __CFDataLength(data), __kCFLogAssertion, "%s(): ending index (%d) out of bounds", func, range.location + range.length); | |
107 | } | |
108 | #else | |
109 | #define __CFDataValidateRange(a,r,f) | |
110 | #endif | |
111 | ||
112 | static bool __CFDataEqual(CFTypeRef cf1, CFTypeRef cf2) { | |
113 | CFDataRef data1 = (CFDataRef)cf1; | |
114 | CFDataRef data2 = (CFDataRef)cf2; | |
115 | CFIndex length; | |
116 | length = __CFDataLength(data1); | |
117 | if (length != __CFDataLength(data2)) return false; | |
118 | return 0 == memcmp(data1->_bytes, data2->_bytes, length); | |
119 | } | |
120 | ||
121 | static CFHashCode __CFDataHash(CFTypeRef cf) { | |
122 | CFDataRef data = (CFDataRef)cf; | |
123 | return CFHashBytes(data->_bytes, __CFMin(__CFDataLength(data), 16)); | |
124 | } | |
125 | ||
126 | static CFStringRef __CFDataCopyDescription(CFTypeRef cf) { | |
127 | CFDataRef data = (CFDataRef)cf; | |
128 | CFMutableStringRef result; | |
129 | CFIndex idx; | |
130 | CFIndex len; | |
131 | const uint8_t *bytes; | |
132 | len = __CFDataLength(data); | |
133 | bytes = data->_bytes; | |
134 | result = CFStringCreateMutable(CFGetAllocator(data), 0); | |
135 | CFStringAppendFormat(result, NULL, CFSTR("<CFData %p [%p]>{length = %u, capacity = %u, bytes = 0x"), cf, CFGetAllocator(data), len, __CFDataCapacity(data)); | |
136 | if (24 < len) { | |
137 | for (idx = 0; idx < 16; idx += 4) { | |
138 | CFStringAppendFormat(result, NULL, CFSTR("%02x%02x%02x%02x"), bytes[idx], bytes[idx + 1], bytes[idx + 2], bytes[idx + 3]); | |
139 | } | |
140 | CFStringAppend(result, CFSTR(" ... ")); | |
141 | for (idx = len - 8; idx < len; idx += 4) { | |
142 | CFStringAppendFormat(result, NULL, CFSTR("%02x%02x%02x%02x"), bytes[idx], bytes[idx + 1], bytes[idx + 2], bytes[idx + 3]); | |
143 | } | |
144 | } else { | |
145 | for (idx = 0; idx < len; idx++) { | |
146 | CFStringAppendFormat(result, NULL, CFSTR("%02x"), bytes[idx]); | |
147 | } | |
148 | } | |
149 | CFStringAppend(result, CFSTR("}")); | |
150 | return result; | |
151 | } | |
152 | ||
153 | enum { | |
154 | kCFImmutable = 0x0, /* unchangable and fixed capacity; default */ | |
155 | kCFMutable = 0x1, /* changeable and variable capacity */ | |
156 | kCFFixedMutable = 0x3 /* changeable and fixed capacity */ | |
157 | }; | |
158 | ||
159 | static void __CFDataDeallocate(CFTypeRef cf) { | |
160 | CFMutableDataRef data = (CFMutableDataRef)cf; | |
161 | CFAllocatorRef allocator = CFGetAllocator(data); | |
162 | switch (__CFMutableVariety(data)) { | |
163 | case kCFMutable: | |
164 | CFAllocatorDeallocate(allocator, data->_bytes); | |
165 | break; | |
166 | case kCFFixedMutable: | |
167 | break; | |
168 | case kCFImmutable: | |
169 | if (NULL != data->_bytesDeallocator) { | |
170 | CFAllocatorDeallocate(data->_bytesDeallocator, data->_bytes); | |
171 | CFRelease(data->_bytesDeallocator); | |
172 | } | |
173 | break; | |
174 | } | |
175 | } | |
176 | ||
177 | static CFTypeID __kCFDataTypeID = _kCFRuntimeNotATypeID; | |
178 | ||
179 | static const CFRuntimeClass __CFDataClass = { | |
180 | 0, | |
181 | "CFData", | |
182 | NULL, // init | |
183 | NULL, // copy | |
184 | __CFDataDeallocate, | |
185 | (void *)__CFDataEqual, | |
186 | __CFDataHash, | |
187 | NULL, // | |
188 | __CFDataCopyDescription | |
189 | }; | |
190 | ||
191 | __private_extern__ void __CFDataInitialize(void) { | |
192 | __kCFDataTypeID = _CFRuntimeRegisterClass(&__CFDataClass); | |
193 | } | |
194 | ||
195 | CFTypeID CFDataGetTypeID(void) { | |
196 | return __kCFDataTypeID; | |
197 | } | |
198 | ||
199 | // NULL bytesDeallocator to this function does not mean the default allocator, it means | |
200 | // that there should be no deallocator, and the bytes should be copied. | |
201 | static CFMutableDataRef __CFDataInit(CFAllocatorRef allocator, CFOptionFlags flags, CFIndex capacity, const uint8_t *bytes, CFIndex length, CFAllocatorRef bytesDeallocator) { | |
202 | CFMutableDataRef memory; | |
203 | CFIndex size; | |
204 | __CFGenericValidateMutabilityFlags(flags); | |
205 | CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity); | |
206 | CFAssert3(kCFFixedMutable != __CFMutableVarietyFromFlags(flags) || length <= capacity, __kCFLogAssertion, "%s(): for kCFFixedMutable type, capacity (%d) must be greater than or equal to number of initial elements (%d)", __PRETTY_FUNCTION__, capacity, length); | |
207 | CFAssert2(0 <= length, __kCFLogAssertion, "%s(): length (%d) cannot be less than zero", __PRETTY_FUNCTION__, length); | |
208 | size = sizeof(struct __CFData) - sizeof(CFRuntimeBase); | |
209 | if (__CFMutableVarietyFromFlags(flags) != kCFMutable && (bytesDeallocator == NULL)) { | |
210 | size += sizeof(uint8_t) * __CFDataNumBytesForCapacity(capacity); | |
211 | } | |
212 | if (__CFMutableVarietyFromFlags(flags) != kCFMutable) { | |
213 | size += sizeof(uint8_t) * 15; // for 16-byte alignment fixup | |
214 | } | |
215 | memory = (CFMutableDataRef)_CFRuntimeCreateInstance(allocator, __kCFDataTypeID, size, NULL); | |
216 | if (NULL == memory) { | |
217 | return NULL; | |
218 | } | |
219 | __CFDataSetNumBytesUsed(memory, 0); | |
220 | __CFDataSetLength(memory, 0); | |
221 | switch (__CFMutableVarietyFromFlags(flags)) { | |
222 | case kCFMutable: | |
223 | __CFDataSetCapacity(memory, __CFDataRoundUpCapacity(1)); | |
224 | __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(__CFDataRoundUpCapacity(1))); | |
225 | // assume that allocators give 16-byte aligned memory back -- it is their responsibility | |
226 | memory->_bytes = CFAllocatorAllocate(allocator, __CFDataNumBytes(memory) * sizeof(uint8_t), 0); | |
227 | if (__CFOASafe) __CFSetLastAllocationEventName(memory->_bytes, "CFData (store)"); | |
228 | if (NULL == memory->_bytes) { | |
229 | CFRelease(memory); | |
230 | return NULL; | |
231 | } | |
232 | memory->_bytesDeallocator = NULL; | |
233 | __CFSetMutableVariety(memory, kCFMutable); | |
234 | CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length); | |
235 | break; | |
236 | case kCFFixedMutable: | |
237 | /* Don't round up capacity */ | |
238 | __CFDataSetCapacity(memory, capacity); | |
239 | __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(capacity)); | |
240 | memory->_bytes = (uint8_t *)((uintptr_t)((int8_t *)memory + sizeof(struct __CFData) + 15) & ~0xF); // 16-byte align | |
241 | memory->_bytesDeallocator = NULL; | |
242 | __CFSetMutableVariety(memory, kCFFixedMutable); | |
243 | CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length); | |
244 | break; | |
245 | case kCFImmutable: | |
246 | /* Don't round up capacity */ | |
247 | __CFDataSetCapacity(memory, capacity); | |
248 | __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(capacity)); | |
249 | if (bytesDeallocator != NULL) { | |
250 | memory->_bytes = (uint8_t *)bytes; | |
251 | memory->_bytesDeallocator = CFRetain(bytesDeallocator); | |
252 | __CFDataSetNumBytesUsed(memory, length); | |
253 | __CFDataSetLength(memory, length); | |
254 | } else { | |
255 | memory->_bytes = (uint8_t *)((uintptr_t)((int8_t *)memory + sizeof(struct __CFData) + 15) & ~0xF); // 16-byte align | |
256 | memory->_bytesDeallocator = NULL; | |
257 | __CFSetMutableVariety(memory, kCFFixedMutable); | |
258 | CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length); | |
259 | } | |
260 | break; | |
261 | } | |
262 | __CFSetMutableVariety(memory, __CFMutableVarietyFromFlags(flags)); | |
263 | return memory; | |
264 | } | |
265 | ||
266 | CFDataRef CFDataCreate(CFAllocatorRef allocator, const uint8_t *bytes, CFIndex length) { | |
267 | return __CFDataInit(allocator, kCFImmutable, length, bytes, length, NULL); | |
268 | } | |
269 | ||
270 | CFDataRef CFDataCreateWithBytesNoCopy(CFAllocatorRef allocator, const uint8_t *bytes, CFIndex length, CFAllocatorRef bytesDeallocator) { | |
271 | CFAssert1((0 == length || bytes != NULL), __kCFLogAssertion, "%s(): bytes pointer cannot be NULL if length is non-zero", __PRETTY_FUNCTION__); | |
272 | if (NULL == bytesDeallocator) bytesDeallocator = __CFGetDefaultAllocator(); | |
273 | if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionJaguar)) { | |
274 | bytesDeallocator = NULL; | |
275 | } | |
276 | return __CFDataInit(allocator, kCFImmutable, length, bytes, length, bytesDeallocator); | |
277 | } | |
278 | ||
279 | CFDataRef CFDataCreateCopy(CFAllocatorRef allocator, CFDataRef data) { | |
280 | CFIndex length = CFDataGetLength(data); | |
281 | return __CFDataInit(allocator, kCFImmutable, length, CFDataGetBytePtr(data), length, NULL); | |
282 | } | |
283 | ||
284 | CFMutableDataRef CFDataCreateMutable(CFAllocatorRef allocator, CFIndex capacity) { | |
285 | return __CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, NULL, 0, NULL); | |
286 | } | |
287 | ||
288 | CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFDataRef data) { | |
289 | return __CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, CFDataGetBytePtr(data), CFDataGetLength(data), NULL); | |
290 | } | |
291 | ||
292 | CFIndex CFDataGetLength(CFDataRef data) { | |
293 | CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, CFIndex, data, "length"); | |
294 | __CFGenericValidateType(data, __kCFDataTypeID); | |
295 | return __CFDataLength(data); | |
296 | } | |
297 | ||
298 | const uint8_t *CFDataGetBytePtr(CFDataRef data) { | |
299 | CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, const uint8_t *, data, "bytes"); | |
300 | __CFGenericValidateType(data, __kCFDataTypeID); | |
301 | return data->_bytes; | |
302 | } | |
303 | ||
304 | uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) { | |
305 | CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, uint8_t *, data, "mutableBytes"); | |
306 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
307 | return data->_bytes; | |
308 | } | |
309 | ||
310 | void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) { | |
311 | CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "getBytes:range:", buffer, range); | |
312 | memmove(buffer, data->_bytes + range.location, range.length); | |
313 | } | |
314 | ||
315 | static void __CFDataGrow(CFMutableDataRef data, CFIndex numNewValues) { | |
316 | CFIndex oldLength = __CFDataLength(data); | |
317 | CFIndex capacity = __CFDataRoundUpCapacity(oldLength + numNewValues); | |
318 | __CFDataSetCapacity(data, capacity); | |
319 | __CFDataSetNumBytes(data, __CFDataNumBytesForCapacity(capacity)); | |
320 | data->_bytes = CFAllocatorReallocate(CFGetAllocator(data), data->_bytes, __CFDataNumBytes(data) * sizeof(uint8_t), 0); | |
321 | if (__CFOASafe) __CFSetLastAllocationEventName(data->_bytes, "CFData (store)"); | |
322 | if (NULL == data->_bytes) HALT; | |
323 | } | |
324 | ||
325 | void CFDataSetLength(CFMutableDataRef data, CFIndex length) { | |
326 | CFIndex len; | |
327 | CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "setLength:", length); | |
328 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
329 | len = __CFDataLength(data); | |
330 | switch (__CFMutableVariety(data)) { | |
331 | case kCFMutable: | |
332 | if (len < length) { | |
333 | // CF: should only grow when new length exceeds current capacity, not whenever it exceeds the current length | |
334 | __CFDataGrow(data, length - len); | |
335 | } | |
336 | break; | |
337 | case kCFFixedMutable: | |
338 | CFAssert1(length <= __CFDataCapacity(data), __kCFLogAssertion, "%s(): fixed-capacity data is full", __PRETTY_FUNCTION__); | |
339 | break; | |
340 | } | |
341 | if (len < length) { | |
342 | memset(data->_bytes + len, 0, length - len); | |
343 | } | |
344 | __CFDataSetLength(data, length); | |
345 | __CFDataSetNumBytesUsed(data, length); | |
346 | } | |
347 | ||
348 | void CFDataIncreaseLength(CFMutableDataRef data, CFIndex extraLength) { | |
349 | CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "increaseLengthBy:", extraLength); | |
350 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
351 | CFDataSetLength(data, __CFDataLength(data) + extraLength); | |
352 | } | |
353 | ||
354 | void CFDataAppendBytes(CFMutableDataRef data, const uint8_t *bytes, CFIndex length) { | |
355 | CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "appendBytes:length:", bytes, length); | |
356 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
357 | CFDataReplaceBytes(data, CFRangeMake(__CFDataLength(data), 0), bytes, length); | |
358 | } | |
359 | ||
360 | void CFDataDeleteBytes(CFMutableDataRef data, CFRange range) { | |
361 | CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, NULL, 0); | |
362 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
363 | CFDataReplaceBytes(data, range, NULL, 0); | |
364 | } | |
365 | ||
366 | void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *newBytes, CFIndex newLength) { | |
367 | CFIndex len; | |
368 | CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, newBytes, newLength); | |
369 | __CFGenericValidateType(data, __kCFDataTypeID); | |
370 | __CFDataValidateRange(data, range, __PRETTY_FUNCTION__); | |
371 | CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); | |
372 | CFAssert2(0 <= newLength, __kCFLogAssertion, "%s(): newLength (%d) cannot be less than zero", __PRETTY_FUNCTION__, newLength); | |
373 | len = __CFDataLength(data); | |
374 | switch (__CFMutableVariety(data)) { | |
375 | case kCFMutable: | |
376 | if (range.length < newLength && __CFDataNumBytes(data) < len - range.length + newLength) { | |
377 | __CFDataGrow(data, newLength - range.length); | |
378 | } | |
379 | break; | |
380 | case kCFFixedMutable: | |
381 | CFAssert1(len - range.length + newLength <= __CFDataCapacity(data), __kCFLogAssertion, "%s(): fixed-capacity data is full", __PRETTY_FUNCTION__); | |
382 | break; | |
383 | } | |
384 | if (newLength != range.length && range.location + range.length < len) { | |
385 | memmove(data->_bytes + range.location + newLength, data->_bytes + range.location + range.length, (len - range.location - range.length) * sizeof(uint8_t)); | |
386 | } | |
387 | if (0 < newLength) { | |
388 | memmove(data->_bytes + range.location, newBytes, newLength * sizeof(uint8_t)); | |
389 | } | |
390 | __CFDataSetNumBytesUsed(data, (len - range.length + newLength)); | |
391 | __CFDataSetLength(data, (len - range.length + newLength)); | |
392 | } | |
393 | ||
394 | #undef __CFDataValidateRange | |
395 | #undef __CFGenericValidateMutabilityFlags | |
396 |