]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/cfutilities.h
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / cfutilities.h
1 /*
2 * Copyright (c) 2000-2004,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 //
26 //CoreFoundation related utilities
27 //
28 #ifndef _H_CFUTILITIES
29 #define _H_CFUTILITIES
30
31 #include <security_utilities/utilities.h>
32 #include <security_utilities/globalizer.h>
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <algorithm>
35 #include <Security/SecBase.h>
36 #undef check
37
38
39 namespace Security {
40
41
42 //
43 // Traits of popular CF types
44 //
45 template <class CFType> struct CFTraits { };
46
47 template <> struct CFTraits<CFTypeRef> {
48 static bool check(CFTypeRef ref) { return true; }
49 };
50
51 #define __SEC_CFTYPE(name) \
52 template <> struct CFTraits<name##Ref> { \
53 static CFTypeID cfid() { return name##GetTypeID(); } \
54 static bool check(CFTypeRef ref) { return CFGetTypeID(ref) == cfid(); } \
55 };
56
57 __SEC_CFTYPE(CFNull)
58 __SEC_CFTYPE(CFBoolean)
59 __SEC_CFTYPE(CFNumber)
60 __SEC_CFTYPE(CFString)
61 __SEC_CFTYPE(CFData)
62 __SEC_CFTYPE(CFDate)
63 __SEC_CFTYPE(CFURL)
64 __SEC_CFTYPE(CFBundle)
65 __SEC_CFTYPE(CFArray)
66 __SEC_CFTYPE(CFDictionary)
67 __SEC_CFTYPE(CFSet)
68
69
70 //
71 // Initialize-only self-releasing CF object handler (lightweight).
72 //
73 template <class CFType> class CFRef {
74 public:
75 CFRef() : mRef(NULL) { }
76 CFRef(CFType ref) : mRef(ref) { }
77 ~CFRef() { this->release(); }
78 CFRef(const CFRef &ref) : mRef(ref) {}
79 template <class _T> CFRef(const CFRef<_T> &ref) : mRef(ref) {}
80
81 CFRef(CFTypeRef ref, OSStatus err)
82 : mRef(CFType(ref))
83 {
84 if (ref && !CFTraits<CFType>::check(ref))
85 MacOSError::throwMe(err);
86 }
87
88 CFRef &take(CFType ref)
89 { this->release(); mRef = ref; return *this; }
90
91 CFType yield()
92 { CFType r = mRef; mRef = NULL; return r; }
93
94 CFRef &operator = (CFType ref)
95 { if (ref) CFRetain(ref); return take(ref); }
96
97 CFRef &operator = (const CFRef &ref)
98 { if (ref) CFRetain(ref); return take(ref); }
99
100 // take variant for when newly created CFType is returned
101 // via a ptr-to-CFType argument.
102 CFType *take()
103 { if (mRef) CFRelease(mRef); mRef = NULL; return &mRef; }
104
105 operator CFType () const { return mRef; }
106 operator bool () const { return mRef != NULL; }
107 bool operator ! () const { return mRef == NULL; }
108
109 CFType get() const { return mRef; }
110
111 CFType &aref()
112 { take(NULL); return mRef; }
113
114 CFType retain() const
115 { if (mRef) CFRetain(mRef); return mRef; }
116
117 void release() const
118 { if (mRef) CFRelease(mRef); }
119
120 template <class NewType>
121 bool is() const { return CFTraits<NewType>::check(mRef); }
122
123 template <class OldType>
124 static CFType check(OldType cf, OSStatus err)
125 {
126 if (cf && !CFTraits<CFType>::check(cf))
127 MacOSError::throwMe(err);
128 return CFType(cf);
129 }
130
131 template <class NewType>
132 NewType as() const { return NewType(mRef); }
133
134 template <class NewType>
135 NewType as(OSStatus err) const { return CFRef<NewType>::check(mRef, err); }
136
137 private:
138 CFType mRef;
139 };
140
141
142 template <class CFType> class CFCopyRef : public CFRef<CFType> {
143 typedef CFRef<CFType> _Base;
144 public:
145 CFCopyRef() { }
146 CFCopyRef(CFType ref) : _Base(ref) { this->retain(); }
147 CFCopyRef(const CFCopyRef &ref) : _Base(ref) { this->retain(); }
148 template <class _T> CFCopyRef(const CFRef<_T> &ref) : _Base(ref) { this->retain(); }
149 CFCopyRef(CFTypeRef ref, OSStatus err) : _Base(ref, err) { this->retain(); }
150
151 CFCopyRef &take(CFType ref)
152 { _Base::take(ref); return *this; }
153
154 CFCopyRef &operator = (CFType ref)
155 { if (ref) CFRetain(ref); return take(ref); }
156
157 CFCopyRef &operator = (const CFCopyRef &ref)
158 { _Base::operator = (ref); return *this; }
159
160 template <class _T> CFCopyRef &operator = (const CFRef<_T> &ref)
161 { _Base::operator = (ref); return *this; }
162 };
163
164
165 //
166 // A simple function that turns a non-array CFTypeRef into
167 // an array of one with that element. This will retain its argument
168 // (directly or indirectly).
169 //
170 inline CFArrayRef cfArrayize(CFTypeRef arrayOrItem)
171 {
172 if (arrayOrItem == NULL)
173 return NULL; // NULL is NULL
174 else if (CFGetTypeID(arrayOrItem) == CFArrayGetTypeID()) {
175 CFRetain(arrayOrItem);
176 return CFArrayRef(arrayOrItem); // already an array
177 } else {
178 return CFArrayCreate(NULL,
179 (const void **)&arrayOrItem, 1, &kCFTypeArrayCallBacks);
180 }
181 }
182
183
184 //
185 // An empty CFArray.
186 // Since CFArrays are type-neutral, a single immutable empty array will
187 // serve for all uses. So keep it.
188 //
189 struct CFEmptyArray {
190 operator CFArrayRef () { return mArray; }
191 CFEmptyArray();
192 private:
193 CFArrayRef mArray;
194 };
195
196 extern ModuleNexus<CFEmptyArray> cfEmptyArray;
197
198
199 //
200 // Translate CFStringRef or CFURLRef to (UTF8-encoded) C++ string.
201 // If release==true, a CFRelease will be performed on the CFWhatever argument
202 // whether the call succeeds or not(!).
203 //
204 string cfString(CFStringRef str); // extract UTF8 string
205 string cfString(CFURLRef url); // path of file: URL (only)
206 string cfString(CFBundleRef bundle); // path to bundle root
207
208 string cfStringRelease(CFStringRef str CF_CONSUMED); // extract UTF8 string
209 string cfStringRelease(CFURLRef url CF_CONSUMED); // path of file: URL (only)
210 string cfStringRelease(CFBundleRef bundle CF_CONSUMED); // path to bundle root
211
212
213 string cfString(CFTypeRef anything, OSStatus err); // dynamic form; throws err on NULL
214
215
216 //
217 // Handle CFNumberRefs.
218 // This is nasty because CFNumber does not support unsigned types, and there's really no portably-safe
219 // way of working around this. So the handling of unsigned numbers is "almost correct."
220 //
221 template <class Number>
222 struct CFNumberTraits;
223
224 template <> struct CFNumberTraits<char> {
225 static const CFNumberType cfnType = kCFNumberCharType;
226 typedef char ValueType;
227 };
228 template <> struct CFNumberTraits<short> {
229 static const CFNumberType cfnType = kCFNumberShortType;
230 typedef short ValueType;
231 };
232 template <> struct CFNumberTraits<int> {
233 static const CFNumberType cfnType = kCFNumberIntType;
234 typedef int ValueType;
235 };
236 template <> struct CFNumberTraits<long> {
237 static const CFNumberType cfnType = kCFNumberLongType;
238 typedef long ValueType;
239 };
240 template <> struct CFNumberTraits<long long> {
241 static const CFNumberType cfnType = kCFNumberLongLongType;
242 typedef long long ValueType;
243 };
244 template <> struct CFNumberTraits<float> {
245 static const CFNumberType cfnType = kCFNumberFloatType;
246 typedef float ValueType;
247 };
248 template <> struct CFNumberTraits<double> {
249 static const CFNumberType cfnType = kCFNumberDoubleType;
250 typedef double ValueType;
251 };
252
253 template <> struct CFNumberTraits<unsigned char> {
254 static const CFNumberType cfnType = kCFNumberIntType;
255 typedef int ValueType;
256 };
257 template <> struct CFNumberTraits<unsigned short> {
258 static const CFNumberType cfnType = kCFNumberIntType;
259 typedef int ValueType;
260 };
261 template <> struct CFNumberTraits<unsigned int> {
262 static const CFNumberType cfnType = kCFNumberLongLongType;
263 typedef long long ValueType;
264 };
265 template <> struct CFNumberTraits<unsigned long> {
266 static const CFNumberType cfnType = kCFNumberLongLongType;
267 typedef long long ValueType;
268 };
269 template <> struct CFNumberTraits<unsigned long long> {
270 static const CFNumberType cfnType = kCFNumberLongLongType;
271 typedef long long ValueType;
272 };
273
274 template <class Number>
275 Number cfNumber(CFNumberRef number)
276 {
277 typename CFNumberTraits<Number>::ValueType value;
278 if (CFNumberGetValue(number, CFNumberTraits<Number>::cfnType, &value))
279 return (Number)value;
280 else
281 CFError::throwMe();
282 }
283
284 template <class Number>
285 Number cfNumber(CFNumberRef number, Number defaultValue)
286 {
287 typename CFNumberTraits<Number>::ValueType value;
288 if (CFNumberGetValue(number, CFNumberTraits<Number>::cfnType, &value))
289 return value;
290 else
291 return defaultValue;
292 }
293
294 template <class Number>
295 CFNumberRef makeCFNumber(Number value)
296 {
297 typename CFNumberTraits<Number>::ValueType cfValue = value;
298 return CFNumberCreate(NULL, CFNumberTraits<Number>::cfnType, &cfValue);
299 }
300
301 // legacy form
302 inline uint32_t cfNumber(CFNumberRef number) { return cfNumber<uint32_t>(number); }
303
304
305 //
306 // Translate strings into CFStrings
307 //
308 inline CFStringRef makeCFString(const char *s, CFStringEncoding encoding)
309 {
310 return s ? CFStringCreateWithCString(NULL, s, encoding) : NULL;
311 }
312
313 inline CFStringRef makeCFString(const char *s)
314 {
315 if (s == NULL)
316 return NULL;
317 CFStringRef result = CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8);
318 if (result == NULL) {
319 result = CFStringCreateWithCString(NULL, s, kCFStringEncodingASCII);
320 if (result == NULL)
321 CFError::throwMe();
322 }
323 return result;
324 }
325
326 inline CFStringRef makeCFString(const string &s, CFStringEncoding encoding)
327 {
328 return makeCFString(s.c_str(), encoding);
329 }
330
331 inline CFStringRef makeCFString(const string &s)
332 {
333 return makeCFString(s.c_str());
334 }
335
336 inline CFStringRef makeCFString(CFDataRef data, CFStringEncoding encoding = kCFStringEncodingUTF8)
337 {
338 return CFStringCreateFromExternalRepresentation(NULL, data, encoding);
339 }
340
341
342 //
343 // Create CFURL objects from various sources
344 //
345 CFURLRef CF_RETURNS_RETAINED makeCFURL(const char *s, bool isDirectory = false, CFURLRef base = NULL);
346 CFURLRef CF_RETURNS_RETAINED makeCFURL(CFStringRef s, bool isDirectory = false, CFURLRef base = NULL);
347
348 inline CFURLRef makeCFURL(const string &s, bool isDirectory = false, CFURLRef base = NULL)
349 {
350 return makeCFURL(s.c_str(), isDirectory, base);
351 }
352
353
354 //
355 // Make temporary CF objects.
356 //
357 class CFTempString : public CFRef<CFStringRef> {
358 public:
359 template <class Source>
360 CFTempString(Source s) : CFRef<CFStringRef>(makeCFString(s)) { }
361 };
362
363 class CFTempURL : public CFRef<CFURLRef> {
364 public:
365 template <class Source>
366 CFTempURL(Source s, bool isDirectory = false, CFURLRef base = NULL)
367 : CFRef<CFURLRef>(makeCFURL(s, isDirectory, base)) { }
368 };
369
370
371 //
372 // A temporary CFNumber
373 //
374 class CFTempNumber : public CFRef<CFNumberRef> {
375 public:
376 template <class Value>
377 CFTempNumber(Value value) : CFRef<CFNumberRef>(makeCFNumber(value)) { }
378 };
379
380
381 //
382 // A temporary CFData.
383 //
384 class CFTempData : public CFRef<CFDataRef> {
385 public:
386 CFTempData(const void *data, size_t length)
387 : CFRef<CFDataRef>(CFDataCreate(NULL, (const UInt8 *)data, length)) { }
388
389 template <class Dataoid>
390 CFTempData(const Dataoid &dataoid)
391 : CFRef<CFDataRef>(CFDataCreate(NULL, (const UInt8 *)dataoid.data(), dataoid.length())) { }
392 };
393
394 class CFTempDataWrap : public CFRef<CFDataRef> {
395 public:
396 CFTempDataWrap(const void *data, size_t length)
397 : CFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)data, length, kCFAllocatorNull)) { }
398
399 template <class Dataoid>
400 CFTempDataWrap(const Dataoid &dataoid)
401 : CFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)dataoid.data(), dataoid.length(), kCFAllocatorNull)) { }
402 };
403
404
405 //
406 // Create CFData objects from various sources.
407 //
408 inline CFDataRef makeCFData(const void *data, size_t size)
409 {
410 return CFDataCreate(NULL, (const UInt8 *)data, size);
411 }
412
413 inline CFDataRef makeCFData(CFDictionaryRef dictionary)
414 {
415 return CFPropertyListCreateData(NULL, dictionary, kCFPropertyListXMLFormat_v1_0, 0, NULL);
416 }
417
418 inline CFDataRef makeCFData(CFArrayRef array)
419 {
420 return CFPropertyListCreateData(NULL, array, kCFPropertyListXMLFormat_v1_0, 0, NULL);
421 }
422
423 template <class Data>
424 inline CFDataRef makeCFData(const Data &source)
425 {
426 return CFDataCreate(NULL, reinterpret_cast<const UInt8 *>(source.data()), source.length());
427 }
428
429 inline CFDataRef makeCFDataMalloc(const void *data, size_t size)
430 {
431 return CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)data, size, kCFAllocatorMalloc);
432 }
433
434 template <class Data>
435 inline CFDataRef makeCFDataMalloc(const Data &source)
436 {
437 return CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)source.data(), source.length(), kCFAllocatorMalloc);
438 }
439
440
441 //
442 // Create a CFDataRef from malloc'ed data, exception-safely
443 //
444 class CFMallocData {
445 public:
446 CFMallocData(size_t size)
447 : mData(::malloc(size)), mSize(size)
448 {
449 if (!mData)
450 UnixError::throwMe();
451 }
452
453 ~CFMallocData()
454 {
455 if (mData)
456 ::free(mData);
457 }
458
459 template <class T>
460 operator T * ()
461 { return static_cast<T *>(mData); }
462
463 operator CFDataRef ();
464
465 void *data() { return mData; }
466 const void *data() const { return mData; }
467 size_t length() const { return mSize; }
468
469 private:
470 void *mData;
471 size_t mSize;
472 };
473
474
475 //
476 // Make CFDictionaries from stuff
477 //
478 CFDictionaryRef makeCFDictionary(unsigned count, ...) CF_RETURNS_RETAINED; // key/value pairs
479 CFMutableDictionaryRef makeCFMutableDictionary() CF_RETURNS_RETAINED; // empty
480 CFMutableDictionaryRef makeCFMutableDictionary(unsigned count, ...) CF_RETURNS_RETAINED; // (count) key/value pairs
481 CFMutableDictionaryRef makeCFMutableDictionary(CFDictionaryRef dict) CF_RETURNS_RETAINED; // copy of dictionary
482
483 CFDictionaryRef makeCFDictionaryFrom(CFDataRef data) CF_RETURNS_RETAINED;// interpret plist form
484 CFDictionaryRef makeCFDictionaryFrom(const void *data, size_t length) CF_RETURNS_RETAINED; // ditto
485
486
487 //
488 // Parsing out a CFDictionary without losing your lunch
489 //
490 class CFDictionary : public CFCopyRef<CFDictionaryRef> {
491 typedef CFCopyRef<CFDictionaryRef> _Base;
492 public:
493 CFDictionary(CFDictionaryRef ref, OSStatus error) : _Base(ref), mDefaultError(error)
494 { if (!ref) MacOSError::throwMe(error); }
495 CFDictionary(CFTypeRef ref, OSStatus error) : _Base(ref, error), mDefaultError(error)
496 { if (!ref) MacOSError::throwMe(error); }
497 CFDictionary(OSStatus error) : _Base(NULL), mDefaultError(error) { }
498
499 using CFCopyRef<CFDictionaryRef>::get;
500
501 CFTypeRef get(CFStringRef key) { return CFDictionaryGetValue(*this, key); }
502 CFTypeRef get(const char *key) { return CFDictionaryGetValue(*this, CFTempString(key)); }
503
504 template <class CFType>
505 CFType get(CFStringRef key, OSStatus err = errSecSuccess) const
506 {
507 CFTypeRef elem = CFDictionaryGetValue(*this, key);
508 return CFRef<CFType>::check(elem, err ? err : mDefaultError);
509 }
510
511 template <class CFType>
512 CFType get(const char *key, OSStatus err = errSecSuccess) const
513 { return get<CFType>(CFTempString(key), err); }
514
515 void apply(CFDictionaryApplierFunction func, void *context)
516 { return CFDictionaryApplyFunction(*this, func, context); }
517
518 private:
519 template <class T>
520 struct Applier {
521 T *object;
522 void (T::*func)(CFTypeRef key, CFTypeRef value);
523 static void apply(CFTypeRef key, CFTypeRef value, void *context)
524 { Applier *me = (Applier *)context; return ((me->object)->*(me->func))(key, value); }
525 };
526
527 template <class Key, class Value>
528 struct BlockApplier {
529 void (^action)(Key key, Value value);
530 static void apply(CFTypeRef key, CFTypeRef value, void* context)
531 { BlockApplier *me = (BlockApplier *)context; return me->action(Key(key), Value(value)); }
532 };
533
534 public:
535 template <class T>
536 void apply(T *object, void (T::*func)(CFTypeRef key, CFTypeRef value))
537 { Applier<T> app; app.object = object; app.func = func; return apply(app.apply, &app); }
538
539 template <class Key = CFTypeRef, class Value = CFTypeRef>
540 void apply(void (^action)(Key key, Value value))
541 { BlockApplier<Key, Value> app; app.action = action; return apply(app.apply, &app); }
542
543 private:
544 OSStatus mDefaultError;
545 };
546
547
548 //
549 // Apply a block to a dictionary
550 //
551 typedef void (^CFDictionaryApplierBlock)(const void *, const void *);
552 void cfDictionaryApplyBlock(CFDictionaryRef source, CFDictionaryApplierBlock block);
553
554
555
556 //
557 // CFURLAccess wrappers for specific purposes
558 // cfLoadFile family will use mmap(2) when appropriate
559 // cfReadFile will read the data into memory
560 // cfMapFile will mmap(2) the file
561 //
562 CFDataRef CF_RETURNS_RETAINED cfLoadFile(CFURLRef url);
563 CFDataRef CF_RETURNS_RETAINED cfLoadFile(int fd, size_t bytes);
564 inline CFDataRef CF_RETURNS_RETAINED cfLoadFile(CFStringRef path) { return cfLoadFile(CFTempURL(path)); }
565 inline CFDataRef CF_RETURNS_RETAINED cfLoadFile(const std::string &path) { return cfLoadFile(CFTempURL(path)); }
566 inline CFDataRef CF_RETURNS_RETAINED cfLoadFile(const char *path) { return cfLoadFile(CFTempURL(path)); }
567
568
569 CFDataRef cfReadFile(CFURLRef url) CF_RETURNS_RETAINED;
570 CFDataRef cfReadFile(int fd, size_t bytes) CF_RETURNS_RETAINED;
571 inline CFDataRef cfReadFile(CFStringRef path) { return cfReadFile(CFTempURL(path)); }
572 inline CFDataRef cfReadFile(const std::string &path) { return cfReadFile(CFTempURL(path)); }
573 inline CFDataRef cfReadFile(const char *path) { return cfReadFile(CFTempURL(path)); }
574
575 CFDataRef cfMapFile(CFURLRef url) CF_RETURNS_RETAINED;
576 CFDataRef cfMapFile(int fd, size_t bytes) CF_RETURNS_RETAINED;
577 inline CFDataRef cfMapFile(CFStringRef path) { return cfMapFile(CFTempURL(path)); }
578 inline CFDataRef cfMapFile(const std::string &path) { return cfMapFile(CFTempURL(path)); }
579 inline CFDataRef cfMapFile(const char *path) { return cfMapFile(CFTempURL(path)); }
580
581
582 //
583 // Internally used STL adapters. Should probably be in utilities.h.
584 //
585 template <class Self>
586 Self projectPair(const Self &me)
587 { return me; }
588
589 template <class First, class Second>
590 Second projectPair(const pair<First, Second> &me)
591 { return me.second; }
592
593
594 //
595 // A CFToVector turns a CFArrayRef of items into a flat
596 // C vector of some type, using a conversion function
597 // (from CFTypeRef) specified. As a special bonus, if
598 // you provide a CFTypeRef (other than CFArrayRef), it
599 // will be transparently handled as an array-of-one.
600 // The array will be automatically released on destruction
601 // of the CFToVector object. Any internal structure shared
602 // with the CFTypeRef inputs will be left alone.
603 //
604 template <class VectorBase, class CFRefType, VectorBase convert(CFRefType)>
605 class CFToVector {
606 public:
607 CFToVector(CFArrayRef arrayRef);
608 ~CFToVector() { delete[] mVector; }
609 operator UInt32 () const { return mCount; }
610 operator VectorBase *() const { return mVector; }
611 bool empty() const { return mCount == 0; }
612
613 VectorBase *begin() const { return mVector; }
614 VectorBase *end() const { return mVector + mCount; }
615
616 VectorBase &operator [] (UInt32 ix) const { assert(ix < mCount); return mVector[ix]; }
617
618 private:
619 VectorBase *mVector;
620 UInt32 mCount;
621 };
622
623 template <class VectorBase, class CFRefType, VectorBase convert(CFRefType)>
624 CFToVector<VectorBase, CFRefType, convert>::CFToVector(CFArrayRef arrayRef)
625 {
626 if (arrayRef == NULL) {
627 mCount = 0;
628 mVector = NULL;
629 } else {
630 mCount = (UInt32)CFArrayGetCount(arrayRef);
631 mVector = new VectorBase[mCount];
632 for (UInt32 n = 0; n < mCount; n++)
633 mVector[n] = convert(CFRefType(CFArrayGetValueAtIndex(arrayRef, n)));
634 }
635 }
636
637
638 //
639 // Make CFArrays from stuff.
640 //
641 template <class Iterator, class Generator>
642 inline CFArrayRef CF_RETURNS_RETAINED makeCFArrayFrom(const Generator &generate, Iterator first, Iterator last)
643 {
644 // how many elements?
645 size_t size = distance(first, last);
646
647 // do the CFArrayCreate tango
648 auto_array<CFTypeRef> vec(size);
649 for (UInt32 n = 0; n < size; n++)
650 vec[n] = generate(projectPair(*first++));
651 assert(first == last);
652 return CFArrayCreate(NULL, (const void **)vec.get(), size, &kCFTypeArrayCallBacks);
653 }
654
655 template <class Container, class Generator>
656 inline CFArrayRef makeCFArrayFrom(const Generator &generate, const Container &container)
657 {
658 return makeCFArrayFrom(generate, container.begin(), container.end());
659 }
660
661 CFArrayRef makeCFArray(CFIndex count, ...) CF_RETURNS_RETAINED;
662 CFMutableArrayRef makeCFMutableArray(CFIndex count, ...) CF_RETURNS_RETAINED;
663
664
665 //
666 // Apply a block to aa array
667 //
668 typedef void (^CFArrayApplierBlock)(const void *value);
669 void cfArrayApplyBlock(CFArrayRef array, CFRange range, CFArrayApplierBlock block);
670 void cfArrayApplyBlock(CFArrayRef array, CFArrayApplierBlock block);
671
672
673 } // end namespace Security
674
675 #endif //_H_CFUTILITIES