/* * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // //CoreFoundation related utilities // #ifndef _H_CFUTILITIES #define _H_CFUTILITIES #include #include #include namespace Security { // // Initialize-only self-releasing CF object handler (lightweight). // Does not support assignment. // template 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 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; }; // // A simple function that turns a non-array CFTypeRef into // an array of one with that element. This will retain its argument // (directly or indirectly). // inline CFArrayRef cfArrayize(CFTypeRef arrayOrItem) { if (arrayOrItem == NULL) return NULL; // NULL is NULL else if (CFGetTypeID(arrayOrItem) == CFArrayGetTypeID()) { CFRetain(arrayOrItem); return CFArrayRef(arrayOrItem); // already an array } else { CFArrayRef array = CFArrayCreate(NULL, (const void **)&arrayOrItem, 1, &kCFTypeArrayCallBacks); return array; } } // // Translate CFStringRef to (UTF8-encoded) C++ string // string cfString(CFStringRef str); // // Translate any Data-oid source to a CFDataRef. The contents are copied. // template inline CFDataRef makeCFData(const Data &source) { return CFDataCreate(NULL, reinterpret_cast(source.data()), source.length()); } // // Translate strings into CFStrings // inline CFStringRef makeCFString(const char *s) { return CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8); } inline CFStringRef makeCFString(const string &s) { return CFStringCreateWithCString(NULL, s.c_str(), kCFStringEncodingUTF8); } // // Internally used STL adapters. Should probably be in utilities.h. // template Self projectPair(const Self &me) { return me; } template Second projectPair(const pair &me) { return me.second; } // // A CFToVector turns a CFArrayRef of items into a flat // C vector of some type, using a conversion function // (from CFTypeRef) specified. As a special bonus, if // you provide a CFTypeRef (other than CFArrayRef), it // will be transparently handled as an array-of-one. // The array will be automatically released on destruction // of the CFToVector object. Any internal structure shared // with the CFTypeRef inputs will be left alone. // template 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 CFToVector::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))); } } // // Generate a CFArray of CFTypeId things generated from iterators. // @@@ This should be cleaned up with partial specializations based // @@@ on iterator_traits. // template inline CFArrayRef makeCFArray(Generator &generate, Iterator first, Iterator last) { // how many elements? size_t size = distance(first, last); // do the CFArrayCreate tango auto_array 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 inline CFArrayRef makeCFArray(Generator &generate, const Container &container) { return makeCFArray(generate, container.begin(), container.end()); } } // end namespace Security #endif //_H_CFUTILITIES