2  * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 #ifndef _SECCFOBJECT_H 
  27 #define _SECCFOBJECT_H 
  29 #include <CoreFoundation/CFRuntime.h> 
  31 #include "threading.h" 
  34 #if( __cplusplus <= 201103L) 
  35 #include <stdatomic.h> 
  42 #define SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR) \ 
  44 operator APIPTR() const \ 
  45 { return (APIPTR)(this->operator CFTypeRef()); } \ 
  48 { SecCFObject::handle(true); return this; } \ 
  49 APIPTR CF_RETURNS_RETAINED handle() \ 
  50 { return (APIPTR)SecCFObject::handle(true); } \ 
  51 APIPTR handle(bool retain) \ 
  52 { return (APIPTR)SecCFObject::handle(retain); } 
  54 #define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ 
  55 SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\ 
  57 void *operator new(size_t size)\ 
  58 { return SecCFObject::allocate(size, CFCLASS); } 
  60 #define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ 
  61 SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ 
  63 static OBJTYPE *required(APIPTR ptr) \ 
  64 { if (OBJTYPE *p = dynamic_cast<OBJTYPE *>(SecCFObject::required(ptr, ERRCODE))) \ 
  65         return p; else MacOSError::throwMe(ERRCODE); } \ 
  67 static OBJTYPE *optional(APIPTR ptr) \ 
  68 { if (SecCFObject *p = SecCFObject::optional(ptr)) \ 
  69         if (OBJTYPE *pp = dynamic_cast<OBJTYPE *>(p)) return pp; else MacOSError::throwMe(ERRCODE); \ 
  72 #define SECALIGNUP(SIZE, ALIGNMENT) (((SIZE - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT) 
  74 struct SecRuntimeBase
: CFRuntimeBase
 
  82         void *operator new(size_t); 
  84         // Align up to a multiple of 16 bytes 
  85         static const size_t kAlignedRuntimeSize 
= SECALIGNUP(sizeof(SecRuntimeBase
), 4); 
  87     uint32_t mRetainCount
; 
  88     os_unfair_lock mRetainLock
; 
  91         // For use by SecPointer only. Returns true once the first time it's called after the object has been created. 
  94                 SecRuntimeBase 
*base 
= reinterpret_cast<SecRuntimeBase 
*>(reinterpret_cast<uint8_t *>(this) - kAlignedRuntimeSize
); 
  96         // atomic flags start clear, and like to go high. 
  97         return !atomic_flag_test_and_set(&(base
->isOld
)); 
 100         static SecCFObject 
*optional(CFTypeRef
) _NOEXCEPT
; 
 101         static SecCFObject 
*required(CFTypeRef
, OSStatus error
); 
 102         static void *allocate(size_t size
, const CFClass 
&cfclass
); 
 105         virtual ~SecCFObject(); 
 106     uint32_t updateRetainCount(intptr_t direction
, uint32_t *oldCount
); 
 107     uint32_t getRetainCount() {return updateRetainCount(0, NULL
);} 
 109         static void operator delete(void *object
) _NOEXCEPT
; 
 110         virtual operator CFTypeRef() const _NOEXCEPT
 
 112                 return reinterpret_cast<CFTypeRef
>(reinterpret_cast<const uint8_t *>(this) - kAlignedRuntimeSize
); 
 115         // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true 
 116         CFTypeRef 
handle(bool retain 
= true) _NOEXCEPT
; 
 118     virtual bool equal(SecCFObject 
&other
); 
 119     virtual CFHashCode 
hash(); 
 120         virtual CFStringRef 
copyFormattingDesc(CFDictionaryRef dict
); 
 121         virtual CFStringRef 
copyDebugDesc(); 
 122         virtual void aboutToDestruct(); 
 123         virtual Mutex
* getMutexForObject() const; 
 124     virtual bool mayDelete(); 
 128 // A pointer type for SecCFObjects. 
 129 // T must be derived from SecCFObject. 
 134         SecPointerBase() : ptr(NULL
) 
 136         SecPointerBase(const SecPointerBase
& p
); 
 137         SecPointerBase(SecCFObject 
*p
); 
 139         SecPointerBase
& operator = (const SecPointerBase
& p
); 
 142         void assign(SecCFObject 
* p
); 
 143         void copy(SecCFObject 
* p
); 
 148 class SecPointer 
: public SecPointerBase
 
 151         SecPointer() : SecPointerBase() {} 
 152         SecPointer(const SecPointer
& p
) : SecPointerBase(p
) {} 
 153         SecPointer(T 
*p
): SecPointerBase(p
) {} 
 154         SecPointer 
&operator =(T 
*p
) { this->assign(p
); return *this; } 
 155         SecPointer 
&take(T 
*p
) { this->copy(p
); return *this; } 
 156         T 
*yield() { T 
*result 
= static_cast<T 
*>(ptr
); ptr 
= NULL
; return result
; } 
 158         // dereference operations 
 159     T
* get () const                             { return static_cast<T
*>(ptr
); }        // mimic unique_ptr 
 160         operator T 
* () const           { return static_cast<T
*>(ptr
); } 
 161         T 
* operator -> () const        { return static_cast<T
*>(ptr
); } 
 162         T 
& operator * () const         { return *static_cast<T
*>(ptr
); } 
 164     SecPointer
& operator=(const SecPointer
& other
) { SecPointerBase::operator=(other
); return *this; } 
 168 bool operator <(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
) 
 170         T 
*p1 
= r1
.get(), *p2 
= r2
.get(); 
 171         return p1 
&& p2 
? *p1 
< *p2 
: p1 
< p2
; 
 175 bool operator ==(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
) 
 177         T 
*p1 
= r1
.get(), *p2 
= r2
.get(); 
 178         return p1 
&& p2 
? *p1 
== *p2 
: p1 
== p2
; 
 182 bool operator !=(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
) 
 184         T 
*p1 
= r1
.get(), *p2 
= r2
.get(); 
 185         return p1 
&& p2 
? *p1 
!= *p2 
: p1 
!= p2
; 
 188 } // end namespace Security