]> git.saurik.com Git - apple/security.git/blob - Security/utilities/src/SecCFWrappers.h
Security-57031.30.12.tar.gz
[apple/security.git] / Security / utilities / src / SecCFWrappers.h
1 /*
2 * Copyright (c) 2011-2014 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
25 #ifndef _SECCFWRAPPERS_H_
26 #define _SECCFWRAPPERS_H_
27
28 #include <CoreFoundation/CFRuntime.h>
29 #include <CoreFoundation/CoreFoundation.h>
30
31 #include <utilities/SecCFRelease.h>
32 #include <utilities/debugging.h>
33
34 #include <assert.h>
35 #include <dispatch/dispatch.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdio.h>
39
40 //
41 // Convenience routines.
42 //
43
44 //
45 // Macros for the pattern
46 //
47 // typedef struct _privateNewClass* NewClassRef;
48 //
49 // struct _privateNewClass {
50 // CFRuntimeBase _base;
51 // ... class additions
52 // };
53 //
54 // kClassNameRegisterClass
55 // kClassNameTypeID
56 //
57 // ClassNameGetTypeID()
58 //
59 // CFGiblisFor(NewClass);
60 //
61 // .. define NewClassDestroy
62 // .. define NewClassCopyDescription
63 //
64 // .. use CFTypeAllocate(NewClass, _privateNewClass, allocator);
65 //
66 //
67
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
72 CFDictionaryRef kDebugDescriptionFormatOptions;
73
74 #define CFGiblisGetSingleton(returnType, giblisClassName, result, doThisOnce) \
75 returnType giblisClassName(void); \
76 returnType giblisClassName(void) { \
77 static dispatch_once_t s##giblisClassName##Once; \
78 static returnType s##giblisClassName##Singleton; \
79 returnType *result = &s##giblisClassName##Singleton; \
80 dispatch_once(&s##giblisClassName##Once, doThisOnce); \
81 return s##giblisClassName##Singleton; \
82 }
83
84 #define CFGiblisWithFunctions(gibliClassName, init_func, copy_func, finalize_func, equal_func, hash_func, copyFormattingDesc_func, copyDebugDesc_func, reclaim_func, refcount_func, run_once_block) \
85 CFGiblisGetSingleton(CFTypeID, gibliClassName##GetTypeID, typeID, (^{ \
86 void(^_onceBlock)() = (run_once_block); \
87 static const CFRuntimeClass s##gibliClassName##Class = { \
88 .version = (reclaim_func == NULL ? 0 : _kCFRuntimeResourcefulObject) \
89 | (refcount_func == NULL ? 0 : _kCFRuntimeCustomRefCount), \
90 .className = #gibliClassName, \
91 .init = init_func, \
92 .copy = copy_func, \
93 .finalize = finalize_func, \
94 .equal = equal_func, \
95 .hash = hash_func, \
96 .copyFormattingDesc = copyFormattingDesc_func, \
97 .copyDebugDesc = copyDebugDesc_func, \
98 .reclaim = reclaim_func, \
99 .refcount = refcount_func, \
100 }; \
101 *typeID = _CFRuntimeRegisterClass(&s##gibliClassName##Class); \
102 if (_onceBlock) \
103 _onceBlock(); \
104 }))
105
106 #define CFGiblisWithHashFor(gibliClassName) \
107 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
108 static void gibliClassName##Destroy(CFTypeRef cf); \
109 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
110 static CFHashCode gibliClassName##Hash(CFTypeRef cf); \
111 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
112 return gibliClassName##CopyFormatDescription(cf, kDebugDescriptionFormatOptions);\
113 }\
114 \
115 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
116
117 #define CFGiblisWithCompareFor(gibliClassName) \
118 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
119 static void gibliClassName##Destroy(CFTypeRef cf); \
120 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
121 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
122 return gibliClassName##CopyFormatDescription(cf, kDebugDescriptionFormatOptions);\
123 }\
124 \
125 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
126
127
128 #define CFGiblisFor(gibliClassName) \
129 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
130 static void gibliClassName##Destroy(CFTypeRef cf); \
131 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
132 return gibliClassName##CopyFormatDescription(cf, kDebugDescriptionFormatOptions);\
133 }\
134 \
135 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, NULL, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
136
137 #define CFTypeAllocateWithSpace(classType, space, allocator) \
138 (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), space, NULL)
139
140 #define CFTypeAllocate(classType, internalType, allocator) \
141 CFTypeAllocateWithSpace(classType, sizeof(internalType) - sizeof(CFRuntimeBase), allocator)
142
143
144
145 __BEGIN_DECLS
146
147 //
148 // Call block function
149 //
150
151 static void apply_block_1(const void *value, void *context)
152 {
153 return ((void (^)(const void *value))context)(value);
154 }
155
156 static void apply_block_2(const void *key, const void *value, void *context)
157 {
158 return ((void (^)(const void *key, const void *value))context)(key, value);
159 }
160
161 //
162 // CFEqual Helpers
163 //
164
165 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
166 {
167 if (left == NULL || right == NULL)
168 return left == right;
169 else
170 return CFEqual(left, right);
171 }
172
173
174 //
175 // Printing
176 //
177
178 static void fprint_string(FILE *file, CFStringRef string) {
179 UInt8 buf[256];
180 CFRange range = { .location = 0 };
181 range.length = CFStringGetLength(string);
182 while (range.length > 0) {
183 CFIndex bytesUsed = 0;
184 CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed);
185 fwrite(buf, 1, bytesUsed, file);
186 range.length -= converted;
187 range.location += converted;
188 }
189 }
190
191 static inline void cffprint_v(FILE *file, CFStringRef fmt, va_list args) {
192 CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args);
193 fprint_string(file, line);
194 CFRelease(line);
195 }
196
197 static inline void cffprint_c_v(FILE *file, const char *fmt, va_list args) {
198 CFStringRef cffmt = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8);
199 cffprint_v(file, cffmt, args);
200 CFRelease(cffmt);
201 }
202
203 static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0);
204 static inline void cffprint(FILE *file, CFStringRef fmt, ...) {
205 va_list args;
206 va_start(args, fmt);
207 cffprint_v(file, fmt, args);
208 va_end(args);
209 }
210
211 //
212 // CFError Helpers
213 //
214
215 /* Return false if possibleError is set. Propagates possibleError into *error
216 if *error is NULL, otherwise releases possibleError. */
217 static inline
218 bool CFErrorPropagate(CFErrorRef possibleError CF_CONSUMED, CFErrorRef *error) {
219 if (possibleError) {
220 if (error && !*error) {
221 *error = possibleError;
222 } else {
223 CFRelease(possibleError);
224 }
225 return false;
226 }
227 return true;
228 }
229
230 //
231 // CFNumber Helpers
232 //
233
234 static inline CFNumberRef CFNumberCreateWithCFIndex(CFAllocatorRef allocator, CFIndex value)
235 {
236 return CFNumberCreate(allocator, kCFNumberCFIndexType, &value);
237 }
238
239 //
240 // CFData Helpers
241 //
242
243 static inline CFMutableDataRef CFDataCreateMutableWithScratch(CFAllocatorRef allocator, CFIndex size) {
244 CFMutableDataRef result = CFDataCreateMutable(allocator, 0);
245 CFDataSetLength(result, size);
246
247 return result;
248 }
249
250 static inline void CFDataAppend(CFMutableDataRef appendTo, CFDataRef dataToAppend)
251 {
252 CFDataAppendBytes(appendTo, CFDataGetBytePtr(dataToAppend), CFDataGetLength(dataToAppend));
253 }
254
255 static inline CFDataRef CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range)
256 {
257 return CFDataCreateWithBytesNoCopy(allocator,
258 CFDataGetBytePtr(sourceData) + range.location, range.length,
259 kCFAllocatorNull);
260 }
261
262 static inline CFDataRef CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range)
263 {
264 return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length);
265 }
266
267 static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data, CFIndex extraLength)
268 {
269 CFIndex startOffset = CFDataGetLength(data);
270
271 CFDataIncreaseLength(data, extraLength);
272
273 return CFDataGetMutableBytePtr(data) + startOffset;
274 }
275
276 static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData)
277 {
278 return CFDataGetMutableBytePtr(theData) + CFDataGetLength(theData);
279 }
280
281 static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) {
282 return CFDataGetBytePtr(theData) + CFDataGetLength(theData);
283 }
284
285 static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right)
286 {
287 const size_t left_size = CFDataGetLength(left);
288 const size_t right_size = CFDataGetLength(right);
289 const size_t shortest = (left_size <= right_size) ? left_size : right_size;
290
291 int comparison = memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), shortest);
292
293 if (comparison > 0 || (comparison == 0 && left_size > right_size))
294 return kCFCompareGreaterThan;
295 else if (comparison < 0 || (comparison == 0 && left_size < right_size))
296 return kCFCompareLessThan;
297 else
298 return kCFCompareEqualTo;
299 }
300
301
302 //
303 // CFString Helpers
304 //
305
306 //
307 // Turn a CFString into an allocated UTF8-encoded C string.
308 //
309 static inline char *CFStringToCString(CFStringRef inStr)
310 {
311 if (!inStr)
312 return (char *)strdup("");
313 CFRetain(inStr); // compensate for release on exit
314
315 // need to extract into buffer
316 CFIndex length = CFStringGetLength(inStr); // in 16-bit character units
317 size_t len = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
318 char *buffer = (char *)malloc(len); // pessimistic
319 if (!CFStringGetCString(inStr, buffer, len, kCFStringEncodingUTF8))
320 buffer[0] = 0;
321
322 CFRelease(inStr);
323 return buffer;
324 }
325
326 // runs operation with inStr as a zero terminated C string
327 // in utf8 encoding passed to the operation block.
328 void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8Str));
329
330 // runs operation with inStr as a zero terminated C string
331 // in utf8 passed to the operation block, the length of
332 // the string is also provided to the block.
333 void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8Str, size_t utf8Length));
334
335 #include <CommonNumerics/CommonCRC.h>
336
337 static inline void CFStringAppendEncryptedData(CFMutableStringRef s, CFDataRef edata)
338 {
339 const uint8_t *bytes = CFDataGetBytePtr(edata);
340 CFIndex len = CFDataGetLength(edata);
341 CFStringAppendFormat(s, 0, CFSTR("%04lx:"), len);
342 if(len<=8) {
343 for (CFIndex ix = 0; ix < len; ++ix) {
344 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
345 }
346 } else {
347 uint64_t crc = 0;
348 CNCRC(kCN_CRC_64_ECMA_182, bytes+8, len-8, &crc);
349 for (CFIndex ix = 0; ix < 8; ++ix) {
350 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
351 }
352 CFStringAppendFormat(s, 0, CFSTR("...|%08llx"), crc);
353 }
354 }
355
356 static inline void CFStringAppendHexData(CFMutableStringRef s, CFDataRef data) {
357 const uint8_t *bytes = CFDataGetBytePtr(data);
358 CFIndex len = CFDataGetLength(data);
359 for (CFIndex ix = 0; ix < len; ++ix) {
360 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
361 }
362 }
363
364 static inline CF_RETURNS_RETAINED CFStringRef CFDataCopyHexString(CFDataRef data) {
365 CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 2 * CFDataGetLength(data));
366 CFStringAppendHexData(hexString, data);
367 return hexString;
368 }
369
370 static inline void CFDataPerformWithHexString(CFDataRef data, void (^operation)(CFStringRef dataString)) {
371 CFStringRef hexString = CFDataCopyHexString(data);
372 operation(hexString);
373 CFRelease(hexString);
374 }
375
376 static inline void BufferPerformWithHexString(const UInt8 *bytes, CFIndex length, void (^operation)(CFStringRef dataString)) {
377 CFDataRef bufferAsData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorNull);
378
379 CFDataPerformWithHexString(bufferAsData, operation);
380
381 CFReleaseNull(bufferAsData);
382 }
383
384
385
386 static inline void CFStringWriteToFile(CFStringRef inStr, FILE* file)
387 {
388 CFStringPerformWithCStringAndLength(inStr, ^(const char *utf8Str, size_t utf8Length) {
389 fwrite(utf8Str, 1, utf8Length, file);
390 });
391 }
392
393 static inline void CFStringWriteToFileWithNewline(CFStringRef inStr, FILE* file)
394 {
395 CFStringWriteToFile(inStr, file);
396 fputc('\n', file);
397 }
398
399 //
400 // MARK: CFCollectionHelpers
401 //
402
403 static inline
404 const void *SecCFRetainForCollection(CFAllocatorRef allocator, const void *value)
405 {
406 return CFRetain(value);
407 }
408
409 static inline
410 void SecCFReleaseForCollection(CFAllocatorRef allocator, const void *value)
411 {
412 CFRelease(value);
413 }
414
415 //
416 // MARK: CFArray Helpers
417 //
418
419 static inline CFIndex CFArrayRemoveAllValue(CFMutableArrayRef array, const void* value)
420 {
421 CFIndex position = kCFNotFound;
422 CFIndex numberRemoved = 0;
423
424 position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value);
425 while (position != kCFNotFound) {
426 CFArrayRemoveValueAtIndex(array, position);
427 ++numberRemoved;
428 position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value);
429 }
430
431 return numberRemoved;
432 }
433
434 #define CFArrayForEachC(array, value) for (CFIndex _aCount = CFArrayGetCount(array), _aIX = 0;value = (__typeof__(value))(_aIX < _aCount ? CFArrayGetValueAtIndex(array, _aIX) : 0), _aIX < _aCount; ++_aIX)
435
436 static inline void CFArrayForEach(CFArrayRef array, void (^operation)(const void *value)) {
437 CFArrayApplyFunction(array, CFRangeMake(0, CFArrayGetCount(array)), apply_block_1, operation);
438 }
439
440 static inline void CFArrayForEachReverse(CFArrayRef array, void (^operation)(const void *value)) {
441 for(CFIndex count = CFArrayGetCount(array); count > 0; --count) {
442 operation(CFArrayGetValueAtIndex(array, count - 1));
443 }
444 }
445
446 static inline const void *CFArrayGetValueMatching(CFArrayRef array, bool (^match)(const void *value)) {
447 CFIndex i, n = CFArrayGetCount(array);
448 for (i = 0; i < n; ++i) {
449 const void *value = CFArrayGetValueAtIndex(array, i);
450 if (match(value)) {
451 return value;
452 }
453 }
454 return NULL;
455 }
456
457 static inline bool CFArrayHasValueMatching(CFArrayRef array, bool (^match)(const void *value)) {
458 return CFArrayGetValueMatching(array, match) != NULL;
459 }
460
461 static inline void CFMutableArrayModifyValues(CFMutableArrayRef array, const void * (^process)(const void *value)) {
462 CFIndex i, n = CFArrayGetCount(array);
463 for (i = 0; i < n; ++i) {
464 const void *value = CFArrayGetValueAtIndex(array, i);
465 CFArraySetValueAtIndex(array, i, process(value));
466 }
467 }
468
469 //
470 // MARK: CFArray creatino Var args helper functions.
471 //
472 static inline CFArrayRef CFArrayCreateCountedForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, CFIndex entries, va_list args)
473 {
474 const void *values[entries ? entries : 1];
475 for (CFIndex currentValue = 0; currentValue < entries; ++currentValue)
476 {
477 values[currentValue] = va_arg(args, void*);
478
479 if (values[currentValue] == NULL)
480 values[currentValue] = kCFNull;
481 }
482
483 return CFArrayCreate(allocator, values, entries, cbs);
484 }
485
486 static inline CFArrayRef CFArrayCreateForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, va_list args)
487 {
488 va_list count;
489 va_copy(count, args);
490
491 CFIndex entries = 0;
492 while (NULL != va_arg(count, void*)) {
493 entries += 1;
494 }
495
496 return CFArrayCreateCountedForVC(allocator, cbs, entries, args);
497
498 }
499
500
501
502 //
503 // MARK: CFArray of CFTypes support
504 //
505
506 static inline CFMutableArrayRef CFArrayCreateMutableForCFTypesWithCapacity(CFAllocatorRef allocator, CFIndex capacity)
507 {
508 return CFArrayCreateMutable(allocator, capacity, &kCFTypeArrayCallBacks);
509 }
510
511
512 static inline CFMutableArrayRef CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator)
513 {
514 return CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
515 }
516
517 static inline CFArrayRef CFArrayCreateForCFTypes(CFAllocatorRef allocator, ...)
518 {
519 va_list args;
520 va_start(args, allocator);
521
522 return CFArrayCreateForVC(allocator, &kCFTypeArrayCallBacks, args);
523
524 }
525
526 static inline CFArrayRef CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...)
527 {
528 va_list args;
529 va_start(args, entries);
530
531 return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args);
532 }
533
534 static inline CFArrayRef CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args)
535 {
536 return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args);
537 }
538
539 //
540 // MARK: CFDictionary of CFTypes helpers
541 //
542
543 static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args)
544 {
545 const void *keys[entries];
546 const void *values[entries];
547
548 for(CFIndex currentValue = 0; currentValue < entries; ++currentValue)
549 {
550 keys[currentValue] = va_arg(args, void*);
551 values[currentValue] = va_arg(args, void*);
552
553 if (values[currentValue] == NULL)
554 values[currentValue] = kCFNull;
555 }
556
557 return CFDictionaryCreate(allocator, keys, values, entries,
558 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
559 }
560
561 static inline CFDictionaryRef CFDictionaryCreateForCFTypes(CFAllocatorRef allocator, ...)
562 {
563 va_list args;
564 va_start(args, allocator);
565
566 CFIndex entries = 0;
567 while (NULL != va_arg(args, void*)) {
568 entries += 2;
569 (void) va_arg(args, void*);
570 }
571
572 entries /= 2;
573
574 va_start(args, allocator);
575
576 return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args);
577
578 }
579
580 static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...)
581 {
582 va_list args;
583 va_start(args, entries);
584
585 return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args);
586 }
587
588 static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator)
589 {
590 return CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
591 }
592
593 static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator, ...)
594 {
595 CFMutableDictionaryRef result = CFDictionaryCreateMutableForCFTypes(allocator);
596
597 va_list args;
598 va_start(args, allocator);
599
600 void* key = va_arg(args, void*);
601
602 while (key != NULL) {
603 CFDictionarySetValue(result, key, va_arg(args, void*));
604 key = va_arg(args, void*);
605 };
606
607 return result;
608 }
609
610 //
611 // MARK: CFSet Helpers
612 //
613
614 static inline CFMutableSetRef CFSetCreateMutableForCFTypes(CFAllocatorRef allocator)
615 {
616 return CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
617 }
618
619 static inline void CFSetForEach(CFSetRef set, void (^operation)(const void *value)) {
620 CFSetApplyFunction(set, apply_block_1, operation);
621 }
622
623 static inline void CFSetSetValues(CFMutableSetRef set, CFArrayRef valuesToSet) {
624 CFArrayForEach(valuesToSet, ^(const void *value) {
625 CFSetSetValue(set, value);
626 });
627 }
628
629 static inline CFMutableArrayRef CFSetCopyValues(CFSetRef set) {
630 CFMutableArrayRef values = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
631
632 CFSetForEach(set, ^(const void *value) {
633 CFArrayAppendValue(values, value);
634 });
635
636 return values;
637 }
638
639 //
640 // MARK: CFDictionary Helpers
641 //
642
643 static inline void CFDictionaryForEach(CFDictionaryRef dictionary, void (^operation)(const void *key, const void *value)) {
644 CFDictionaryApplyFunction(dictionary, apply_block_2, operation);
645 }
646
647 //
648 // MARK: CFCalendar helpers
649 //
650
651 void SecCFCalendarDoWithZuluCalendar(void(^action)(CFCalendarRef zuluCalendar));
652
653 //
654 // MARK: CFAbsoluteTime helpers
655 //
656
657 static inline CFAbsoluteTime CFAbsoluteTimeForCalendarMoment(CFCalendarRef cal, int year, int month, int day, int hour, int minute, int second) {
658 CFAbsoluteTime at;
659 CFCalendarComposeAbsoluteTime(cal, &at, "yMdHms", year, month, day, hour, minute, second);
660 return at;
661 }
662
663 static inline CFAbsoluteTime CFAbsoluteTimeForCalendarDay(CFCalendarRef cal, int year, int month, int day) {
664 CFAbsoluteTime at;
665 CFCalendarComposeAbsoluteTime(cal, &at, "yMd", year, month, day);
666 return at;
667 }
668
669 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianMoment(CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
670 {
671 CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar);
672 CFCalendarSetTimeZone(cal, tz);
673 CFAbsoluteTime at = CFAbsoluteTimeForCalendarMoment(cal, year, month, day, hour, minute, second);
674 CFReleaseSafe(cal);
675 return at;
676 }
677
678 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianDay(CFTimeZoneRef tz, int year, int month, int day)
679 {
680 CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar);
681 CFCalendarSetTimeZone(cal, tz);
682 CFAbsoluteTime at = CFAbsoluteTimeForCalendarDay(cal, year, month, day);
683 CFReleaseSafe(cal);
684 return at;
685 }
686
687 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluMoment(int year, int month, int day, int hour, int minute, int second)
688 {
689 __block CFAbsoluteTime result = 0.0;
690 SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) {
691 result = CFAbsoluteTimeForCalendarMoment(zuluCalendar, year, month, day, hour, minute, second);
692 });
693 return result;
694 }
695
696
697 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluDay(int year, int month, int day)
698 {
699 __block CFAbsoluteTime result = 0.0;
700 SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) {
701 result = CFAbsoluteTimeForCalendarDay(zuluCalendar, year, month, day);
702 });
703 return result;
704 }
705
706
707
708 //
709 // MARK: CFDate Helpers
710 //
711
712 static inline CFDateRef CFDateCreateForGregorianMoment(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
713 {
714 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianMoment(tz, year, month, day, hour, minute, second));
715 }
716
717 static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
718 {
719 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianDay(tz, year, month, day));
720 }
721
722 static inline CFDateRef CFDateCreateForGregorianZuluMoment(CFAllocatorRef allocator, int year, int month, int day, int hour, int minute, int second)
723 {
724 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluMoment(year, month, day, hour, minute, second));
725 }
726
727 static inline CFDateRef CFDateCreateForGregorianZuluDay(CFAllocatorRef allocator, int year, int month, int day)
728 {
729 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluDay(year, month, day));
730 }
731
732
733 //
734 // MARK: Type checking
735 //
736
737 static inline bool isArray(CFTypeRef cfType) {
738 return cfType && CFGetTypeID(cfType) == CFArrayGetTypeID();
739 }
740
741 static inline bool isSet(CFTypeRef cfType) {
742 return cfType && CFGetTypeID(cfType) == CFSetGetTypeID();
743 }
744
745 static inline bool isData(CFTypeRef cfType) {
746 return cfType && CFGetTypeID(cfType) == CFDataGetTypeID();
747 }
748
749 static inline bool isDate(CFTypeRef cfType) {
750 return cfType && CFGetTypeID(cfType) == CFDateGetTypeID();
751 }
752
753 static inline bool isDictionary(CFTypeRef cfType) {
754 return cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID();
755 }
756
757 static inline bool isNumber(CFTypeRef cfType) {
758 return cfType && CFGetTypeID(cfType) == CFNumberGetTypeID();
759 }
760
761 static inline bool isNumberOfType(CFTypeRef cfType, CFNumberType number) {
762 return isNumber(cfType) && CFNumberGetType((CFNumberRef)cfType) == number;
763 }
764
765 static inline bool isString(CFTypeRef cfType) {
766 return cfType && CFGetTypeID(cfType) == CFStringGetTypeID();
767 }
768
769 static inline bool isBoolean(CFTypeRef cfType) {
770 return cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID();
771 }
772
773 static inline bool isNull(CFTypeRef cfType) {
774 return cfType && CFGetTypeID(cfType) == CFNullGetTypeID();
775 }
776
777
778 //
779 // MARK: PropertyList Helpers
780 //
781
782 //
783 // Crazy reading and writing stuff
784 //
785
786 static inline void CFPropertyListWriteToFile(CFPropertyListRef plist, CFURLRef file)
787 {
788 CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, file);
789 CFErrorRef error = NULL;
790
791 CFWriteStreamOpen(writeStream);
792 CFPropertyListWrite(plist, writeStream, kCFPropertyListBinaryFormat_v1_0, 0, &error);
793 if (error)
794 secerror("Can't write plist: %@", error);
795
796 CFReleaseNull(error);
797 CFReleaseNull(writeStream);
798 }
799
800 static inline CF_RETURNS_RETAINED CFPropertyListRef CFPropertyListReadFromFile(CFURLRef file)
801 {
802 CFPropertyListRef result = NULL;
803 CFErrorRef error = NULL;
804 CFBooleanRef isRegularFile;
805 if (!CFURLCopyResourcePropertyForKey(file, kCFURLIsRegularFileKey, &isRegularFile, &error)) {
806 secdebug("plist", "file %@: %@", file, error);
807 } else if (CFBooleanGetValue(isRegularFile)) {
808 CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, file);
809 if (readStream) {
810 if (CFReadStreamOpen(readStream)) {
811 CFPropertyListFormat format;
812 result = CFPropertyListCreateWithStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListMutableContainers, &format, &error);
813 if (!result) {
814 secerror("read plist from %@: %@", file, error);
815 }
816 }
817 CFRelease(readStream);
818 }
819 }
820 CFReleaseNull(error);
821
822 return result;
823 }
824
825 __END_DECLS
826
827 #endif /* _SECCFWRAPPERS_H_ */