#ifndef _H_CFUTILITIES
#define _H_CFUTILITIES
#include <Security/utilities.h>
#include <CoreFoundation/CoreFoundation.h>
#include <algorithm>
namespace Security {
template <class CFType> class CFRef {
public:
CFRef() : mRef(NULL) { }
CFRef(CFType ref) : mRef(ref) { }
CFRef(const CFRef &ref) : mRef(ref) { if (ref) CFRetain(ref); }
~CFRef() { if (mRef) CFRelease(mRef); }
CFRef &take(CFType ref)
{ if (mRef) CFRelease(mRef); mRef = ref; return *this; }
CFRef &operator = (CFType ref)
{ if (ref) CFRetain(ref); return take(ref); }
operator CFType () const { return mRef; }
operator bool () const { return mRef != NULL; }
bool operator ! () const { return mRef == NULL; }
private:
CFType mRef;
};
template <class CFType> class CFCopyRef {
public:
CFCopyRef() : mRef(NULL) { }
explicit CFCopyRef(CFType ref) : mRef(ref) { if (ref) CFRetain(ref); }
CFCopyRef(const CFCopyRef &ref) : mRef(ref) { if (ref) CFRetain(ref); }
~CFCopyRef() { if (mRef) CFRelease(mRef); }
CFCopyRef &take(CFType ref)
{ if (mRef) CFRelease(mRef); mRef = ref; return *this; }
CFCopyRef &operator = (CFType ref)
{ if (ref) CFRetain(ref); return take(ref); }
operator CFType () const { return mRef; }
operator bool () const { return mRef != NULL; }
bool operator ! () const { return mRef == NULL; }
private:
CFType mRef;
};
inline CFArrayRef cfArrayize(CFTypeRef arrayOrItem)
{
if (arrayOrItem == NULL)
return NULL; else if (CFGetTypeID(arrayOrItem) == CFArrayGetTypeID()) {
CFRetain(arrayOrItem);
return CFArrayRef(arrayOrItem); } else {
CFArrayRef array = CFArrayCreate(NULL,
(const void **)&arrayOrItem, 1, &kCFTypeArrayCallBacks);
return array;
}
}
inline CssmData cfData(CFDataRef data)
{
return CssmData(const_cast<UInt8 *>(CFDataGetBytePtr(data)),
CFDataGetLength(data));
}
string cfString(CFStringRef str);
template <class Data>
inline CFDataRef makeCFData(const Data &source)
{
return CFDataCreate(NULL, reinterpret_cast<const UInt8 *>(source.data()), source.length());
}
inline CFStringRef makeCFString(const char *s)
{
return CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8);
}
inline CFStringRef makeCFString(const string &s)
{
return CFStringCreateWithCString(NULL, s.c_str(), kCFStringEncodingUTF8);
}
template <class Self>
Self projectPair(const Self &me)
{ return me; }
template <class First, class Second>
Second projectPair(const pair<First, Second> &me)
{ return me.second; }
template <class VectorBase, class CFRefType, VectorBase convert(CFRefType)>
class CFToVector {
public:
CFToVector(CFArrayRef arrayRef);
~CFToVector() { delete[] mVector; }
operator uint32 () const { return mCount; }
operator VectorBase *() const { return mVector; }
bool empty() const { return mCount == 0; }
VectorBase *begin() const { return mVector; }
VectorBase *end() const { return mVector + mCount; }
VectorBase &operator [] (uint32 ix) const { assert(ix < mCount); return mVector[ix]; }
private:
VectorBase *mVector;
uint32 mCount;
};
template <class VectorBase, class CFRefType, VectorBase convert(CFRefType)>
CFToVector<VectorBase, CFRefType, convert>::CFToVector(CFArrayRef arrayRef)
{
if (arrayRef == NULL) {
mCount = 0;
mVector = NULL;
} else {
mCount = CFArrayGetCount(arrayRef);
mVector = new VectorBase[mCount];
for (uint32 n = 0; n < mCount; n++)
mVector[n] = convert(CFRefType(CFArrayGetValueAtIndex(arrayRef, n)));
}
}
template <class Iterator, class Generator>
inline CFArrayRef makeCFArray(Generator &generate, Iterator first, Iterator last)
{
size_t size = distance(first, last);
auto_array<CFTypeRef> vec(size);
for (uint32 n = 0; n < size; n++)
vec[n] = generate(projectPair(*first++));
assert(first == last);
return CFArrayCreate(NULL, (const void **)vec.get(), size, &kCFTypeArrayCallBacks);
}
template <class Container, class Generator>
inline CFArrayRef makeCFArray(Generator &generate, const Container &container)
{
return makeCFArray(generate, container.begin(), container.end());
}
}
#endif //_H_CFUTILITIES