2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #ifndef _SECCFWRAPPERS_H_
26 #define _SECCFWRAPPERS_H_
28 #include <CoreFoundation/CFRuntime.h>
29 #include <CoreFoundation/CoreFoundation.h>
31 #include <utilities/SecCFRelease.h>
32 #include <utilities/debugging.h>
35 #include <dispatch/dispatch.h>
41 // Convenience routines.
45 // Macros for the pattern
47 // typedef struct _privateNewClass* NewClassRef;
49 // struct _privateNewClass {
50 // CFRuntimeBase _base;
51 // ... class additions
54 // kClassNameRegisterClass
57 // ClassNameGetTypeID()
59 // CFGiblisFor(NewClass);
61 // .. define NewClassDestroy
62 // .. define NewClassCopyDescription
64 // .. use CFTypeAllocate(NewClass, _privateNewClass, allocator);
68 // Call this to create a function that returns a singleton instance of type stype,
69 // which is initialized once by calling doThisOnce, with result in its context. Upon
70 // completion body should assign to *result.
71 #define CFGiblisGetSingleton(returnType, giblisClassName, result, doThisOnce) \
72 returnType giblisClassName(void); \
73 returnType giblisClassName(void) { \
74 static dispatch_once_t s##giblisClassName##Once; \
75 static returnType s##giblisClassName##Singleton; \
76 returnType *result = &s##giblisClassName##Singleton; \
77 dispatch_once(&s##giblisClassName##Once, doThisOnce); \
78 return s##giblisClassName##Singleton; \
81 #define CFGiblisWithFunctions(gibliClassName, init_func, copy_func, finalize_func, equal_func, hash_func, copyFormattingDesc_func, copyDebugDesc_func, reclaim_func, refcount_func, run_once_block) \
82 CFGiblisGetSingleton(CFTypeID, gibliClassName##GetTypeID, typeID, (^{ \
83 void(^_onceBlock)() = (run_once_block); \
84 static const CFRuntimeClass s##gibliClassName##Class = { \
85 .version = (reclaim_func == NULL ? 0 : _kCFRuntimeResourcefulObject) \
86 | (refcount_func == NULL ? 0 : _kCFRuntimeCustomRefCount), \
87 .className = #gibliClassName, \
90 .finalize = finalize_func, \
91 .equal = equal_func, \
93 .copyFormattingDesc = copyFormattingDesc_func, \
94 .copyDebugDesc = copyDebugDesc_func, \
95 .reclaim = reclaim_func, \
96 .refcount = refcount_func, \
98 *typeID = _CFRuntimeRegisterClass(&s##gibliClassName##Class); \
104 #define CFGiblisWithHashFor(gibliClassName) \
105 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \
106 static void gibliClassName##Destroy(CFTypeRef cf); \
107 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
108 static CFHashCode gibliClassName##Hash(CFTypeRef cf); \
110 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL)
112 #define CFGiblisWithCompareFor(gibliClassName) \
113 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \
114 static void gibliClassName##Destroy(CFTypeRef cf); \
115 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
117 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, NULL, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL)
120 #define CFGiblisFor(gibliClassName) \
121 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \
122 static void gibliClassName##Destroy(CFTypeRef cf); \
124 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, NULL, NULL, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL)
126 #define CFTypeAllocateWithSpace(classType, space, allocator) \
127 (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), space, NULL)
129 #define CFTypeAllocate(classType, internalType, allocator) \
130 CFTypeAllocateWithSpace(classType, sizeof(internalType) - sizeof(CFRuntimeBase), allocator)
136 // Call block function
139 static void apply_block_1(const void *value
, void *context
)
141 return ((void (^)(const void *value
))context
)(value
);
144 static void apply_block_2(const void *key
, const void *value
, void *context
)
146 return ((void (^)(const void *key
, const void *value
))context
)(key
, value
);
153 static inline bool CFEqualSafe(CFTypeRef left
, CFTypeRef right
)
155 if (left
== NULL
|| right
== NULL
)
156 return left
== right
;
158 return CFEqual(left
, right
);
166 static void fprint_string(FILE *file
, CFStringRef string
) {
168 CFRange range
= { .location
= 0 };
169 range
.length
= CFStringGetLength(string
);
170 while (range
.length
> 0) {
171 CFIndex bytesUsed
= 0;
172 CFIndex converted
= CFStringGetBytes(string
, range
, kCFStringEncodingUTF8
, 0, false, buf
, sizeof(buf
), &bytesUsed
);
173 fwrite(buf
, 1, bytesUsed
, file
);
174 range
.length
-= converted
;
175 range
.location
+= converted
;
179 static inline void cffprint_v(FILE *file
, CFStringRef fmt
, va_list args
) {
180 CFStringRef line
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, fmt
, args
);
181 fprint_string(file
, line
);
185 static inline void cffprint_c_v(FILE *file
, const char *fmt
, va_list args
) {
186 CFStringRef cffmt
= CFStringCreateWithCString(kCFAllocatorDefault
, fmt
, kCFStringEncodingUTF8
);
187 cffprint_v(file
, cffmt
, args
);
191 static void cffprint(FILE *file
, CFStringRef fmt
, ...) CF_FORMAT_FUNCTION(2,0);
192 static inline void cffprint(FILE *file
, CFStringRef fmt
, ...) {
195 cffprint_v(file
, fmt
, args
);
203 /* Return false if possibleError is set. Propagates possibleError into *error
204 if *error is NULL, otherwise releases possibleError. */
206 bool CFErrorPropagate(CFErrorRef possibleError CF_CONSUMED
, CFErrorRef
*error
) {
208 if (error
&& !*error
) {
209 *error
= possibleError
;
211 CFRelease(possibleError
);
222 static inline CFNumberRef
CFNumberCreateWithCFIndex(CFAllocatorRef allocator
, CFIndex value
)
224 return CFNumberCreate(allocator
, kCFNumberCFIndexType
, &value
);
231 static inline CFMutableDataRef
CFDataCreateMutableWithScratch(CFAllocatorRef allocator
, CFIndex size
) {
232 CFMutableDataRef result
= CFDataCreateMutable(allocator
, 0);
233 CFDataSetLength(result
, size
);
238 static inline void CFDataAppend(CFMutableDataRef appendTo
, CFDataRef dataToAppend
)
240 CFDataAppendBytes(appendTo
, CFDataGetBytePtr(dataToAppend
), CFDataGetLength(dataToAppend
));
243 static inline CFDataRef
CFDataCreateReferenceFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
)
245 return CFDataCreateWithBytesNoCopy(allocator
,
246 CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
,
250 static inline CFDataRef
CFDataCreateCopyFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
)
252 return CFDataCreate(allocator
, CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
);
255 static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data
, CFIndex extraLength
)
257 CFIndex startOffset
= CFDataGetLength(data
);
259 CFDataIncreaseLength(data
, extraLength
);
261 return CFDataGetMutableBytePtr(data
) + startOffset
;
264 static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData
)
266 return CFDataGetMutableBytePtr(theData
) + CFDataGetLength(theData
);
269 static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData
) {
270 return CFDataGetBytePtr(theData
) + CFDataGetLength(theData
);
273 static inline CFComparisonResult
CFDataCompare(CFDataRef left
, CFDataRef right
)
275 const size_t left_size
= CFDataGetLength(left
);
276 const size_t right_size
= CFDataGetLength(right
);
277 const size_t shortest
= (left_size
<= right_size
) ? left_size
: right_size
;
279 int comparison
= memcmp(CFDataGetBytePtr(left
), CFDataGetBytePtr(right
), shortest
);
281 if (comparison
> 0 || (comparison
== 0 && left_size
> right_size
))
282 return kCFCompareGreaterThan
;
283 else if (comparison
< 0 || (comparison
== 0 && left_size
< right_size
))
284 return kCFCompareLessThan
;
286 return kCFCompareEqualTo
;
295 // Turn a CFString into an allocated UTF8-encoded C string.
297 static inline char *CFStringToCString(CFStringRef inStr
)
300 return (char *)strdup("");
301 CFRetain(inStr
); // compensate for release on exit
303 // need to extract into buffer
304 CFIndex length
= CFStringGetLength(inStr
); // in 16-bit character units
305 size_t len
= CFStringGetMaximumSizeForEncoding(length
, kCFStringEncodingUTF8
);
306 char *buffer
= (char *)malloc(len
); // pessimistic
307 if (!CFStringGetCString(inStr
, buffer
, len
, kCFStringEncodingUTF8
))
314 // runs operation with inStr as a zero terminated C string
315 // in utf8 encoding passed to the operation block.
316 void CFStringPerformWithCString(CFStringRef inStr
, void(^operation
)(const char *utf8Str
));
318 // runs operation with inStr as a zero terminated C string
319 // in utf8 passed to the operation block, the length of
320 // the string is also provided to the block.
321 void CFStringPerformWithCStringAndLength(CFStringRef inStr
, void(^operation
)(const char *utf8Str
, size_t utf8Length
));
323 #include <CommonNumerics/CommonCRC.h>
325 static inline void CFStringAppendEncryptedData(CFMutableStringRef s
, CFDataRef edata
)
327 const uint8_t *bytes
= CFDataGetBytePtr(edata
);
328 CFIndex len
= CFDataGetLength(edata
);
329 CFStringAppendFormat(s
, 0, CFSTR("%04lx:"), len
);
331 for (CFIndex ix
= 0; ix
< len
; ++ix
) {
332 CFStringAppendFormat(s
, 0, CFSTR("%02X"), bytes
[ix
]);
336 CNCRC(kCN_CRC_64_ECMA_182
, bytes
+8, len
-8, &crc
);
337 for (CFIndex ix
= 0; ix
< 8; ++ix
) {
338 CFStringAppendFormat(s
, 0, CFSTR("%02X"), bytes
[ix
]);
340 CFStringAppendFormat(s
, 0, CFSTR("...|%08llx"), crc
);
344 static inline void CFStringAppendHexData(CFMutableStringRef s
, CFDataRef data
) {
345 const uint8_t *bytes
= CFDataGetBytePtr(data
);
346 CFIndex len
= CFDataGetLength(data
);
347 for (CFIndex ix
= 0; ix
< len
; ++ix
) {
348 CFStringAppendFormat(s
, 0, CFSTR("%02X"), bytes
[ix
]);
352 static inline CF_RETURNS_RETAINED CFStringRef
CFDataCopyHexString(CFDataRef data
) {
353 CFMutableStringRef hexString
= CFStringCreateMutable(kCFAllocatorDefault
, 2 * CFDataGetLength(data
));
354 CFStringAppendHexData(hexString
, data
);
358 static inline void CFDataPerformWithHexString(CFDataRef data
, void (^operation
)(CFStringRef dataString
)) {
359 CFStringRef hexString
= CFDataCopyHexString(data
);
360 operation(hexString
);
361 CFRelease(hexString
);
364 static inline void BufferPerformWithHexString(const UInt8
*bytes
, CFIndex length
, void (^operation
)(CFStringRef dataString
)) {
365 CFDataRef bufferAsData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, bytes
, length
, kCFAllocatorNull
);
367 CFDataPerformWithHexString(bufferAsData
, operation
);
369 CFReleaseNull(bufferAsData
);
374 static inline void CFStringWriteToFile(CFStringRef inStr
, FILE* file
)
376 CFStringPerformWithCStringAndLength(inStr
, ^(const char *utf8Str
, size_t utf8Length
) {
377 fwrite(utf8Str
, 1, utf8Length
, file
);
381 static inline void CFStringWriteToFileWithNewline(CFStringRef inStr
, FILE* file
)
383 CFStringWriteToFile(inStr
, file
);
388 // MARK: CFCollectionHelpers
392 const void *SecCFRetainForCollection(CFAllocatorRef allocator
, const void *value
)
394 return CFRetain(value
);
398 void SecCFReleaseForCollection(CFAllocatorRef allocator
, const void *value
)
404 // MARK: CFArray Helpers
407 static inline CFIndex
CFArrayRemoveAllValue(CFMutableArrayRef array
, const void* value
)
409 CFIndex position
= kCFNotFound
;
410 CFIndex numberRemoved
= 0;
412 position
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), value
);
413 while (position
!= kCFNotFound
) {
414 CFArrayRemoveValueAtIndex(array
, position
);
416 position
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), value
);
419 return numberRemoved
;
422 #define CFArrayForEachC(array, value) for (CFIndex _aCount = CFArrayGetCount(array), _aIX = 0;value = (__typeof__(value))(_aIX < _aCount ? CFArrayGetValueAtIndex(array, _aIX) : 0), _aIX < _aCount; ++_aIX)
424 static inline void CFArrayForEach(CFArrayRef array
, void (^operation
)(const void *value
)) {
425 CFArrayApplyFunction(array
, CFRangeMake(0, CFArrayGetCount(array
)), apply_block_1
, operation
);
428 static inline void CFArrayForEachReverse(CFArrayRef array
, void (^operation
)(const void *value
)) {
429 for(CFIndex count
= CFArrayGetCount(array
); count
> 0; --count
) {
430 operation(CFArrayGetValueAtIndex(array
, count
- 1));
434 static inline const void *CFArrayGetValueMatching(CFArrayRef array
, bool (^match
)(const void *value
)) {
435 CFIndex i
, n
= CFArrayGetCount(array
);
436 for (i
= 0; i
< n
; ++i
) {
437 const void *value
= CFArrayGetValueAtIndex(array
, i
);
445 static inline bool CFArrayHasValueMatching(CFArrayRef array
, bool (^match
)(const void *value
)) {
446 return CFArrayGetValueMatching(array
, match
) != NULL
;
449 static inline void CFMutableArrayModifyValues(CFMutableArrayRef array
, const void * (^process
)(const void *value
)) {
450 CFIndex i
, n
= CFArrayGetCount(array
);
451 for (i
= 0; i
< n
; ++i
) {
452 const void *value
= CFArrayGetValueAtIndex(array
, i
);
453 CFArraySetValueAtIndex(array
, i
, process(value
));
458 // MARK: CFArray creatino Var args helper functions.
460 static inline CFArrayRef
CFArrayCreateCountedForVC(CFAllocatorRef allocator
, const CFArrayCallBacks
*cbs
, CFIndex entries
, va_list args
)
462 const void *values
[entries
? entries
: 1];
463 for (CFIndex currentValue
= 0; currentValue
< entries
; ++currentValue
)
465 values
[currentValue
] = va_arg(args
, void*);
467 if (values
[currentValue
] == NULL
)
468 values
[currentValue
] = kCFNull
;
471 return CFArrayCreate(allocator
, values
, entries
, cbs
);
474 static inline CFArrayRef
CFArrayCreateForVC(CFAllocatorRef allocator
, const CFArrayCallBacks
*cbs
, va_list args
)
477 va_copy(count
, args
);
480 while (NULL
!= va_arg(count
, void*)) {
484 return CFArrayCreateCountedForVC(allocator
, cbs
, entries
, args
);
491 // MARK: CFArray of CFTypes support
494 static inline CFMutableArrayRef
CFArrayCreateMutableForCFTypesWithCapacity(CFAllocatorRef allocator
, CFIndex capacity
)
496 return CFArrayCreateMutable(allocator
, capacity
, &kCFTypeArrayCallBacks
);
500 static inline CFMutableArrayRef
CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator
)
502 return CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
505 static inline CFArrayRef
CFArrayCreateForCFTypes(CFAllocatorRef allocator
, ...)
508 va_start(args
, allocator
);
510 return CFArrayCreateForVC(allocator
, &kCFTypeArrayCallBacks
, args
);
514 static inline CFArrayRef
CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator
, CFIndex entries
, ...)
517 va_start(args
, entries
);
519 return CFArrayCreateCountedForVC(allocator
, &kCFTypeArrayCallBacks
, entries
, args
);
522 static inline CFArrayRef
CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator
, CFIndex entries
, va_list args
)
524 return CFArrayCreateCountedForVC(allocator
, &kCFTypeArrayCallBacks
, entries
, args
);
528 // MARK: CFDictionary of CFTypes helpers
531 static inline CFDictionaryRef
CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator
, CFIndex entries
, va_list args
)
533 const void *keys
[entries
];
534 const void *values
[entries
];
536 for(CFIndex currentValue
= 0; currentValue
< entries
; ++currentValue
)
538 keys
[currentValue
] = va_arg(args
, void*);
539 values
[currentValue
] = va_arg(args
, void*);
541 if (values
[currentValue
] == NULL
)
542 values
[currentValue
] = kCFNull
;
545 return CFDictionaryCreate(allocator
, keys
, values
, entries
,
546 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
549 static inline CFDictionaryRef
CFDictionaryCreateForCFTypes(CFAllocatorRef allocator
, ...)
552 va_start(args
, allocator
);
555 while (NULL
!= va_arg(args
, void*)) {
557 (void) va_arg(args
, void*);
562 va_start(args
, allocator
);
564 return CFDictionaryCreateCountedForCFTypesV(allocator
, entries
, args
);
568 static inline CFDictionaryRef
CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator
, CFIndex entries
, ...)
571 va_start(args
, entries
);
573 return CFDictionaryCreateCountedForCFTypesV(allocator
, entries
, args
);
576 static inline CFMutableDictionaryRef
CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator
)
578 return CFDictionaryCreateMutable(allocator
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
581 static inline CFMutableDictionaryRef
CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator
, ...)
583 CFMutableDictionaryRef result
= CFDictionaryCreateMutableForCFTypes(allocator
);
586 va_start(args
, allocator
);
588 void* key
= va_arg(args
, void*);
590 while (key
!= NULL
) {
591 CFDictionarySetValue(result
, key
, va_arg(args
, void*));
592 key
= va_arg(args
, void*);
599 // MARK: CFSet Helpers
602 static inline CFMutableSetRef
CFSetCreateMutableForCFTypes(CFAllocatorRef allocator
)
604 return CFSetCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeSetCallBacks
);
607 static inline void CFSetForEach(CFSetRef set
, void (^operation
)(const void *value
)) {
608 CFSetApplyFunction(set
, apply_block_1
, operation
);
611 static inline void CFSetSetValues(CFMutableSetRef set
, CFArrayRef valuesToSet
) {
612 CFArrayForEach(valuesToSet
, ^(const void *value
) {
613 CFSetSetValue(set
, value
);
617 static inline CFMutableArrayRef
CFSetCopyValues(CFSetRef set
) {
618 CFMutableArrayRef values
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
620 CFSetForEach(set
, ^(const void *value
) {
621 CFArrayAppendValue(values
, value
);
628 // MARK: CFDictionary Helpers
631 static inline void CFDictionaryForEach(CFDictionaryRef dictionary
, void (^operation
)(const void *key
, const void *value
)) {
632 CFDictionaryApplyFunction(dictionary
, apply_block_2
, operation
);
636 // MARK: CFCalendar helpers
639 CFCalendarRef
SecCFCalendarGetZulu();
642 // MARK: CFAbsoluteTime helpers
645 static inline CFAbsoluteTime
CFAbsoluteTimeForCalendarMoment(CFCalendarRef cal
, int year
, int month
, int day
, int hour
, int minute
, int second
) {
647 CFCalendarComposeAbsoluteTime(cal
, &at
, "yMdHms", year
, month
, day
, hour
, minute
, second
);
651 static inline CFAbsoluteTime
CFAbsoluteTimeForCalendarDay(CFCalendarRef cal
, int year
, int month
, int day
) {
653 CFCalendarComposeAbsoluteTime(cal
, &at
, "yMd", year
, month
, day
);
657 static inline CFAbsoluteTime
CFAbsoluteTimeForGregorianMoment(CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
)
659 CFCalendarRef cal
= CFCalendarCreateWithIdentifier(NULL
, kCFGregorianCalendar
);
660 CFCalendarSetTimeZone(cal
, tz
);
661 CFAbsoluteTime at
= CFAbsoluteTimeForCalendarMoment(cal
, year
, month
, day
, hour
, minute
, second
);
666 static inline CFAbsoluteTime
CFAbsoluteTimeForGregorianDay(CFTimeZoneRef tz
, int year
, int month
, int day
)
668 CFCalendarRef cal
= CFCalendarCreateWithIdentifier(NULL
, kCFGregorianCalendar
);
669 CFCalendarSetTimeZone(cal
, tz
);
670 CFAbsoluteTime at
= CFAbsoluteTimeForCalendarDay(cal
, year
, month
, day
);
675 static inline CFAbsoluteTime
CFAbsoluteTimeForGregorianZuluMoment(int year
, int month
, int day
, int hour
, int minute
, int second
)
677 return CFAbsoluteTimeForCalendarMoment(SecCFCalendarGetZulu(), year
, month
, day
, hour
, minute
, second
);
681 static inline CFAbsoluteTime
CFAbsoluteTimeForGregorianZuluDay(int year
, int month
, int day
)
683 return CFAbsoluteTimeForCalendarDay(SecCFCalendarGetZulu(), year
, month
, day
);
689 // MARK: CFDate Helpers
692 static inline CFDateRef
CFDateCreateForGregorianMoment(CFAllocatorRef allocator
, CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
)
694 return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianMoment(tz
, year
, month
, day
, hour
, minute
, second
));
697 static inline CFDateRef
CFDateCreateForGregorianDay(CFAllocatorRef allocator
, CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
)
699 return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianDay(tz
, year
, month
, day
));
702 static inline CFDateRef
CFDateCreateForGregorianZuluMoment(CFAllocatorRef allocator
, int year
, int month
, int day
, int hour
, int minute
, int second
)
704 return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianZuluMoment(year
, month
, day
, hour
, minute
, second
));
707 static inline CFDateRef
CFDateCreateForGregorianZuluDay(CFAllocatorRef allocator
, int year
, int month
, int day
)
709 return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianZuluDay(year
, month
, day
));
714 // MARK: Type checking
717 static inline bool isArray(CFTypeRef cfType
) {
718 return cfType
&& CFGetTypeID(cfType
) == CFArrayGetTypeID();
721 static inline bool isSet(CFTypeRef cfType
) {
722 return cfType
&& CFGetTypeID(cfType
) == CFSetGetTypeID();
725 static inline bool isData(CFTypeRef cfType
) {
726 return cfType
&& CFGetTypeID(cfType
) == CFDataGetTypeID();
729 static inline bool isDate(CFTypeRef cfType
) {
730 return cfType
&& CFGetTypeID(cfType
) == CFDateGetTypeID();
733 static inline bool isDictionary(CFTypeRef cfType
) {
734 return cfType
&& CFGetTypeID(cfType
) == CFDictionaryGetTypeID();
737 static inline bool isNumber(CFTypeRef cfType
) {
738 return cfType
&& CFGetTypeID(cfType
) == CFNumberGetTypeID();
741 static inline bool isNumberOfType(CFTypeRef cfType
, CFNumberType number
) {
742 return isNumber(cfType
) && CFNumberGetType((CFNumberRef
)cfType
) == number
;
745 static inline bool isString(CFTypeRef cfType
) {
746 return cfType
&& CFGetTypeID(cfType
) == CFStringGetTypeID();
749 static inline bool isBoolean(CFTypeRef cfType
) {
750 return cfType
&& CFGetTypeID(cfType
) == CFBooleanGetTypeID();
753 static inline bool isNull(CFTypeRef cfType
) {
754 return cfType
&& CFGetTypeID(cfType
) == CFNullGetTypeID();
759 // MARK: PropertyList Helpers
763 // Crazy reading and writing stuff
766 static inline void CFPropertyListWriteToFile(CFPropertyListRef plist
, CFURLRef file
)
768 CFWriteStreamRef writeStream
= CFWriteStreamCreateWithFile(kCFAllocatorDefault
, file
);
769 CFErrorRef error
= NULL
;
771 CFWriteStreamOpen(writeStream
);
772 CFPropertyListWrite(plist
, writeStream
, kCFPropertyListBinaryFormat_v1_0
, 0, &error
);
774 secerror("Can't write plist: %@", error
);
776 CFReleaseNull(error
);
777 CFReleaseNull(writeStream
);
780 static inline CF_RETURNS_RETAINED CFPropertyListRef
CFPropertyListReadFromFile(CFURLRef file
)
782 CFPropertyListRef result
= NULL
;
783 CFErrorRef error
= NULL
;
784 CFBooleanRef isRegularFile
;
785 if (!CFURLCopyResourcePropertyForKey(file
, kCFURLIsRegularFileKey
, &isRegularFile
, &error
)) {
786 secdebug("plist", "file %@: %@", file
, error
);
787 } else if (CFBooleanGetValue(isRegularFile
)) {
788 CFReadStreamRef readStream
= CFReadStreamCreateWithFile(kCFAllocatorDefault
, file
);
790 if (CFReadStreamOpen(readStream
)) {
791 CFPropertyListFormat format
;
792 result
= CFPropertyListCreateWithStream(kCFAllocatorDefault
, readStream
, 0, kCFPropertyListMutableContainers
, &format
, &error
);
794 secerror("read plist from %@: %@", file
, error
);
797 CFRelease(readStream
);
800 CFReleaseNull(error
);
807 #endif /* _SECCFWRAPPERS_H_ */