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"
32 #include <stdatomic.h>
38 #define SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR) \
40 operator APIPTR() const \
41 { return (APIPTR)(this->operator CFTypeRef()); } \
44 { SecCFObject::handle(true); return this; } \
45 APIPTR handle(bool retain = true) \
46 { return (APIPTR)SecCFObject::handle(retain); }
48 #define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \
49 SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\
51 void *operator new(size_t size) throw(std::bad_alloc) \
52 { return SecCFObject::allocate(size, CFCLASS); }
54 #define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \
55 SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \
57 static OBJTYPE *required(APIPTR ptr) \
58 { if (OBJTYPE *p = dynamic_cast<OBJTYPE *>(SecCFObject::required(ptr, ERRCODE))) \
59 return p; else MacOSError::throwMe(ERRCODE); } \
61 static OBJTYPE *optional(APIPTR ptr) \
62 { if (SecCFObject *p = SecCFObject::optional(ptr)) \
63 if (OBJTYPE *pp = dynamic_cast<OBJTYPE *>(p)) return pp; else MacOSError::throwMe(ERRCODE); \
66 #define SECALIGNUP(SIZE, ALIGNMENT) (((SIZE - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT)
68 struct SecRuntimeBase
: CFRuntimeBase
76 void *operator new(size_t) throw(std::bad_alloc
);
78 // Align up to a multiple of 16 bytes
79 static const size_t kAlignedRuntimeSize
= SECALIGNUP(sizeof(SecRuntimeBase
), 4);
81 uint32_t mRetainCount
;
82 OSSpinLock mRetainSpinLock
;
85 // For use by SecPointer only. Returns true once the first time it's called after the object has been created.
88 SecRuntimeBase
*base
= reinterpret_cast<SecRuntimeBase
*>(reinterpret_cast<uint8_t *>(this) - kAlignedRuntimeSize
);
90 // atomic flags start clear, and like to go high.
91 return !atomic_flag_test_and_set(&(base
->isOld
));
94 static SecCFObject
*optional(CFTypeRef
) throw();
95 static SecCFObject
*required(CFTypeRef
, OSStatus error
);
96 static void *allocate(size_t size
, const CFClass
&cfclass
) throw(std::bad_alloc
);
99 virtual ~SecCFObject();
100 uint32_t updateRetainCount(intptr_t direction
, uint32_t *oldCount
);
101 uint32_t getRetainCount() {return updateRetainCount(0, NULL
);}
103 static void operator delete(void *object
) throw();
104 virtual operator CFTypeRef() const throw()
106 return reinterpret_cast<CFTypeRef
>(reinterpret_cast<const uint8_t *>(this) - kAlignedRuntimeSize
);
109 // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true
110 CFTypeRef
handle(bool retain
= true) throw();
112 virtual bool equal(SecCFObject
&other
);
113 virtual CFHashCode
hash();
114 virtual CFStringRef
copyFormattingDesc(CFDictionaryRef dict
);
115 virtual CFStringRef
copyDebugDesc();
116 virtual void aboutToDestruct();
117 virtual Mutex
* getMutexForObject() const;
118 virtual bool mayDelete();
122 // A pointer type for SecCFObjects.
123 // T must be derived from SecCFObject.
128 SecPointerBase() : ptr(NULL
)
130 SecPointerBase(const SecPointerBase
& p
);
131 SecPointerBase(SecCFObject
*p
);
133 SecPointerBase
& operator = (const SecPointerBase
& p
);
136 void assign(SecCFObject
* p
);
137 void copy(SecCFObject
* p
);
142 class SecPointer
: public SecPointerBase
145 SecPointer() : SecPointerBase() {}
146 SecPointer(const SecPointer
& p
) : SecPointerBase(p
) {}
147 SecPointer(T
*p
): SecPointerBase(p
) {}
148 SecPointer
&operator =(T
*p
) { this->assign(p
); return *this; }
149 SecPointer
&take(T
*p
) { this->copy(p
); return *this; }
150 T
*yield() { T
*result
= static_cast<T
*>(ptr
); ptr
= NULL
; return result
; }
152 // dereference operations
153 T
* get () const { return static_cast<T
*>(ptr
); } // mimic auto_ptr
154 operator T
* () const { return static_cast<T
*>(ptr
); }
155 T
* operator -> () const { return static_cast<T
*>(ptr
); }
156 T
& operator * () const { return *static_cast<T
*>(ptr
); }
160 bool operator <(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
162 T
*p1
= r1
.get(), *p2
= r2
.get();
163 return p1
&& p2
? *p1
< *p2
: p1
< p2
;
167 bool operator ==(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
169 T
*p1
= r1
.get(), *p2
= r2
.get();
170 return p1
&& p2
? *p1
== *p2
: p1
== p2
;
174 bool operator !=(const SecPointer
<T
> &r1
, const SecPointer
<T
> &r2
)
176 T
*p1
= r1
.get(), *p2
= r2
.get();
177 return p1
&& p2
? *p1
!= *p2
: p1
!= p2
;
180 } // end namespace Security