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) throw(std::bad_alloc) \
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) throw(std::bad_alloc
);
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
) throw();
101 static SecCFObject
*required(CFTypeRef
, OSStatus error
);
102 static void *allocate(size_t size
, const CFClass
&cfclass
) throw(std::bad_alloc
);
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
) throw();
110 virtual operator CFTypeRef() const throw()
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) throw();
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 auto_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
); }
166 bool operator <(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
168 T
*p1
= r1
.get(), *p2
= r2
.get();
169 return p1
&& p2
? *p1
< *p2
: p1
< p2
;
173 bool operator ==(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
175 T
*p1
= r1
.get(), *p2
= r2
.get();
176 return p1
&& p2
? *p1
== *p2
: p1
== p2
;
180 bool operator !=(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
182 T
*p1
= r1
.get(), *p2
= r2
.get();
183 return p1
&& p2
? *p1
!= *p2
: p1
!= p2
;
186 } // end namespace Security