1/* 2 * Copyright (c) 2000-2004,2011,2013-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#ifndef _SECCFOBJECT_H 27#define _SECCFOBJECT_H 28 29#include <CoreFoundation/CFRuntime.h> 30#include <new> 31#include "threading.h" 32 33namespace Security { 34 35class CFClass; 36 37#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ 38\ 39void *operator new(size_t size) throw(std::bad_alloc) \ 40{ return SecCFObject::allocate(size, CFCLASS); } \ 41\ 42operator APIPTR() const \ 43{ return (APIPTR)(this->operator CFTypeRef()); } \ 44\ 45OBJTYPE *retain() \ 46{ SecCFObject::handle(true); return this; } \ 47APIPTR handle(bool retain = true) \ 48{ return (APIPTR)SecCFObject::handle(retain); } \ 49\ 50static OBJTYPE *required(APIPTR ptr) \ 51{ if (OBJTYPE *p = dynamic_cast<OBJTYPE *>(SecCFObject::required(ptr, ERRCODE))) \ 52 return p; else MacOSError::throwMe(ERRCODE); } \ 53\ 54static OBJTYPE *optional(APIPTR ptr) \ 55{ if (SecCFObject *p = SecCFObject::optional(ptr)) \ 56 if (OBJTYPE *pp = dynamic_cast<OBJTYPE *>(p)) return pp; else MacOSError::throwMe(ERRCODE); \ 57 else return NULL; } 58 59#define SECALIGNUP(SIZE, ALIGNMENT) (((SIZE - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT) 60 61struct SecRuntimeBase: CFRuntimeBase 62{ 63 bool isNew; 64}; 65 66class SecCFObject 67{ 68private: 69 void *operator new(size_t) throw(std::bad_alloc); 70 71 // Align up to a multiple of 16 bytes 72 static const size_t kAlignedRuntimeSize = SECALIGNUP(sizeof(SecRuntimeBase), 4); 73 74 uint32_t mRetainCount; 75 OSSpinLock mRetainSpinLock; 76 77public: 78 // For use by SecPointer only. Returns true once the first time it's called after the object has been created. 79 bool isNew() 80 { 81 SecRuntimeBase *base = reinterpret_cast<SecRuntimeBase *>(reinterpret_cast<uint8_t *>(this) - kAlignedRuntimeSize); 82 bool isNew = base->isNew; 83 base->isNew = false; 84 return isNew; 85 } 86 87 static SecCFObject *optional(CFTypeRef) throw(); 88 static SecCFObject *required(CFTypeRef, OSStatus error); 89 static void *allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc); 90 91 SecCFObject(); 92 virtual ~SecCFObject(); 93 uint32_t updateRetainCount(intptr_t direction, uint32_t *oldCount); 94 uint32_t getRetainCount() {return updateRetainCount(0, NULL);} 95 96 static void operator delete(void *object) throw(); 97 operator CFTypeRef() const throw() 98 { 99 return reinterpret_cast<CFTypeRef>(reinterpret_cast<const uint8_t *>(this) - kAlignedRuntimeSize); 100 } 101 102 // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true 103 CFTypeRef handle(bool retain = true) throw(); 104 105 virtual bool equal(SecCFObject &other); 106 virtual CFHashCode hash(); 107 virtual CFStringRef copyFormattingDesc(CFDictionaryRef dict); 108 virtual CFStringRef copyDebugDesc(); 109 virtual void aboutToDestruct(); 110 virtual Mutex* getMutexForObject(); 111 virtual bool mayDelete(); 112}; 113 114// 115// A pointer type for SecCFObjects. 116// T must be derived from SecCFObject. 117// 118class SecPointerBase 119{ 120public: 121 SecPointerBase() : ptr(NULL) 122 {} 123 SecPointerBase(const SecPointerBase& p); 124 SecPointerBase(SecCFObject *p); 125 ~SecPointerBase(); 126 SecPointerBase& operator = (const SecPointerBase& p); 127 128protected: 129 void assign(SecCFObject * p); 130 void copy(SecCFObject * p); 131 SecCFObject *ptr; 132}; 133 134template <class T> 135class SecPointer : public SecPointerBase 136{ 137public: 138 SecPointer() : SecPointerBase() {} 139 SecPointer(const SecPointer& p) : SecPointerBase(p) {} 140 SecPointer(T *p): SecPointerBase(p) {} 141 SecPointer &operator =(T *p) { this->assign(p); return *this; } 142 SecPointer &take(T *p) { this->copy(p); return *this; } 143 T *yield() { T *result = static_cast<T *>(ptr); ptr = NULL; return result; } 144 145 // dereference operations 146 T* get () const { return static_cast<T*>(ptr); } // mimic auto_ptr 147 operator T * () const { return static_cast<T*>(ptr); } 148 T * operator -> () const { return static_cast<T*>(ptr); } 149 T & operator * () const { return *static_cast<T*>(ptr); } 150}; 151 152template <class T> 153bool operator <(const SecPointer<T> &r1, const SecPointer<T> &r2) 154{ 155 T *p1 = r1.get(), *p2 = r2.get(); 156 return p1 && p2 ? *p1 < *p2 : p1 < p2; 157} 158 159template <class T> 160bool operator ==(const SecPointer<T> &r1, const SecPointer<T> &r2) 161{ 162 T *p1 = r1.get(), *p2 = r2.get(); 163 return p1 && p2 ? *p1 == *p2 : p1 == p2; 164} 165 166template <class T> 167bool operator !=(const SecPointer<T> &r1, const SecPointer<T> &r2) 168{ 169 T *p1 = r1.get(), *p2 = r2.get(); 170 return p1 && p2 ? *p1 != *p2 : p1 != p2; 171} 172 173} // end namespace Security 174 175 176#endif 177