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