X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_utilities/lib/seccfobject.h diff --git a/Security/libsecurity_utilities/lib/seccfobject.h b/Security/libsecurity_utilities/lib/seccfobject.h new file mode 100644 index 00000000..2717d755 --- /dev/null +++ b/Security/libsecurity_utilities/lib/seccfobject.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * 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@ + */ + + + +#ifndef _SECCFOBJECT_H +#define _SECCFOBJECT_H + +#include +#include +#include "threading.h" + +namespace Security { + +class CFClass; + +#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ +\ +void *operator new(size_t size) throw(std::bad_alloc) \ +{ return SecCFObject::allocate(size, CFCLASS); } \ +\ +operator APIPTR() const \ +{ return (APIPTR)(this->operator CFTypeRef()); } \ +\ +OBJTYPE *retain() \ +{ SecCFObject::handle(true); return this; } \ +APIPTR handle(bool retain = true) \ +{ return (APIPTR)SecCFObject::handle(retain); } \ +\ +static OBJTYPE *required(APIPTR ptr) \ +{ if (OBJTYPE *p = dynamic_cast(SecCFObject::required(ptr, ERRCODE))) \ + return p; else MacOSError::throwMe(ERRCODE); } \ +\ +static OBJTYPE *optional(APIPTR ptr) \ +{ if (SecCFObject *p = SecCFObject::optional(ptr)) \ + if (OBJTYPE *pp = dynamic_cast(p)) return pp; else MacOSError::throwMe(ERRCODE); \ + else return NULL; } + +#define SECALIGNUP(SIZE, ALIGNMENT) (((SIZE - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT) + +struct SecRuntimeBase: CFRuntimeBase +{ + bool isNew; +}; + +class SecCFObject +{ +private: + void *operator new(size_t) throw(std::bad_alloc); + + // Align up to a multiple of 16 bytes + static const size_t kAlignedRuntimeSize = SECALIGNUP(sizeof(SecRuntimeBase), 4); + + uint32_t mRetainCount; + OSSpinLock mRetainSpinLock; + +public: + // For use by SecPointer only. Returns true once the first time it's called after the object has been created. + bool isNew() + { + SecRuntimeBase *base = reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); + bool isNew = base->isNew; + base->isNew = false; + return isNew; + } + + static SecCFObject *optional(CFTypeRef) throw(); + static SecCFObject *required(CFTypeRef, OSStatus error); + static void *allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc); + + SecCFObject(); + virtual ~SecCFObject(); + uint32_t updateRetainCount(intptr_t direction, uint32_t *oldCount); + uint32_t getRetainCount() {return updateRetainCount(0, NULL);} + + static void operator delete(void *object) throw(); + operator CFTypeRef() const throw() + { + return reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); + } + + // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true + CFTypeRef handle(bool retain = true) throw(); + + virtual bool equal(SecCFObject &other); + virtual CFHashCode hash(); + virtual CFStringRef copyFormattingDesc(CFDictionaryRef dict); + virtual CFStringRef copyDebugDesc(); + virtual void aboutToDestruct(); + virtual Mutex* getMutexForObject(); + virtual bool mayDelete(); +}; + +// +// A pointer type for SecCFObjects. +// T must be derived from SecCFObject. +// +class SecPointerBase +{ +public: + SecPointerBase() : ptr(NULL) + {} + SecPointerBase(const SecPointerBase& p); + SecPointerBase(SecCFObject *p); + ~SecPointerBase(); + SecPointerBase& operator = (const SecPointerBase& p); + +protected: + void assign(SecCFObject * p); + void copy(SecCFObject * p); + SecCFObject *ptr; +}; + +template +class SecPointer : public SecPointerBase +{ +public: + SecPointer() : SecPointerBase() {} + SecPointer(const SecPointer& p) : SecPointerBase(p) {} + SecPointer(T *p): SecPointerBase(p) {} + SecPointer &operator =(T *p) { this->assign(p); return *this; } + SecPointer &take(T *p) { this->copy(p); return *this; } + T *yield() { T *result = static_cast(ptr); ptr = NULL; return result; } + + // dereference operations + T* get () const { return static_cast(ptr); } // mimic auto_ptr + operator T * () const { return static_cast(ptr); } + T * operator -> () const { return static_cast(ptr); } + T & operator * () const { return *static_cast(ptr); } +}; + +template +bool operator <(const SecPointer &r1, const SecPointer &r2) +{ + T *p1 = r1.get(), *p2 = r2.get(); + return p1 && p2 ? *p1 < *p2 : p1 < p2; +} + +template +bool operator ==(const SecPointer &r1, const SecPointer &r2) +{ + T *p1 = r1.get(), *p2 = r2.get(); + return p1 && p2 ? *p1 == *p2 : p1 == p2; +} + +template +bool operator !=(const SecPointer &r1, const SecPointer &r2) +{ + T *p1 = r1.get(), *p2 = r2.get(); + return p1 && p2 ? *p1 != *p2 : p1 != p2; +} + +} // end namespace Security + + +#endif