]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/alloc.h
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / alloc.h
1 /*
2 * Copyright (c) 2000-2004,2011-2012,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 // alloc - abstract malloc-like allocator abstraction
27 //
28 #ifndef _H_ALLOC
29 #define _H_ALLOC
30
31 #include <security_utilities/utilities.h>
32 #include <cstring>
33
34 namespace Security
35 {
36
37
38 //
39 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
40 // that CDSA loves so much. If you have an allocation strategy and want objects
41 // to be allocated through it, inherit from this.
42 //
43 class Allocator {
44 public:
45 virtual ~Allocator();
46 virtual void *malloc(size_t) throw(std::bad_alloc) = 0;
47 virtual void free(void *) throw() = 0;
48 virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0;
49
50 //
51 // Template versions for added expressiveness.
52 // Note that the integers are element counts, not byte sizes.
53 //
54 template <class T> T *alloc() throw(std::bad_alloc)
55 { return reinterpret_cast<T *>(malloc(sizeof(T))); }
56
57 template <class T> T *alloc(UInt32 count) throw(std::bad_alloc)
58 { return reinterpret_cast<T *>(malloc(sizeof(T) * count)); }
59
60 template <class T> T *alloc(T *old, UInt32 count) throw(std::bad_alloc)
61 { return reinterpret_cast<T *>(realloc(old, sizeof(T) * count)); }
62
63
64 //
65 // Happier malloc/realloc for any type. Note that these still have
66 // the original (byte-sized) argument profile.
67 //
68 template <class T> T *malloc(size_t size) throw(std::bad_alloc)
69 { return reinterpret_cast<T *>(malloc(size)); }
70
71 template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
72 { return reinterpret_cast<T *>(realloc(addr, size)); }
73
74 // All right, if you *really* have to have calloc...
75 void *calloc(size_t size, size_t count) throw(std::bad_alloc)
76 {
77 size_t bytes = 0;
78 if(__builtin_mul_overflow(size, count, &bytes)) {
79 // Multiplication overflowed.
80 throw std::bad_alloc();
81 }
82 void *addr = malloc(bytes);
83 memset(addr, 0, bytes);
84 return addr;
85 }
86
87 // compare Allocators for identity
88 virtual bool operator == (const Allocator &alloc) const throw();
89
90 public:
91 // allocator chooser options
92 enum {
93 normal = 0x0000,
94 sensitive = 0x0001
95 };
96
97 static Allocator &standard(UInt32 request = normal);
98 };
99
100
101 //
102 // You'd think that this is operator delete(const T *, Allocator &), but you'd
103 // be wrong. Specialized operator delete is only called during constructor cleanup.
104 // Use this to cleanly destroy things.
105 //
106 template <class T>
107 inline void destroy(T *obj, Allocator &alloc) throw()
108 {
109 obj->~T();
110 alloc.free(obj);
111 }
112
113 // untyped (release memory only, no destructor call)
114 inline void destroy(void *obj, Allocator &alloc) throw()
115 {
116 alloc.free(obj);
117 }
118
119
120 //
121 // A mixin class to automagically manage your allocator.
122 // To allow allocation (of your object) from any instance of Allocator,
123 // inherit from CssmHeap. Your users can then create heap instances of your thing by
124 // new (an-allocator) YourClass(...)
125 // or (still)
126 // new YourClass(...)
127 // for the default allocation source. The beauty is that when someone does a
128 // delete pointer-to-your-instance
129 // then the magic fairies will find the allocator that created the object and ask it
130 // to free the memory (by calling its free() method).
131 // The price of all that glory is memory overhead - typically one pointer per object.
132 //
133 class CssmHeap {
134 public:
135 void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc);
136 void operator delete (void *addr, size_t size) throw();
137 void operator delete (void *addr, size_t size, Allocator *alloc) throw();
138 };
139
140
141 //
142 // Here is a version of auto_ptr that works with Allocators. It is designed
143 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
144 // argument, of course.
145 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
146 // You can't dereference it, naturally.
147 //
148 template <class T>
149 class CssmAutoPtr {
150 public:
151 Allocator &allocator;
152
153 CssmAutoPtr(Allocator &alloc = Allocator::standard())
154 : allocator(alloc), mine(NULL) { }
155 CssmAutoPtr(Allocator &alloc, T *p)
156 : allocator(alloc), mine(p) { }
157 CssmAutoPtr(T *p)
158 : allocator(Allocator::standard()), mine(p) { }
159 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
160 : allocator(src.allocator), mine(src.release()) { }
161 template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
162 : allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
163
164 ~CssmAutoPtr() { allocator.free(mine); }
165
166 T *get() const throw() { return mine; }
167 T *release() { T *result = mine; mine = NULL; return result; }
168 void reset() { allocator.free(mine); mine = NULL; }
169
170 operator T * () const { return mine; }
171 T *operator -> () const { return mine; }
172 T &operator * () const { assert(mine); return *mine; }
173
174 private:
175 T *mine;
176 };
177
178 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
179 template <>
180 class CssmAutoPtr<void> {
181 public:
182 Allocator &allocator;
183
184 CssmAutoPtr(Allocator &alloc) : allocator(alloc), mine(NULL) { }
185 CssmAutoPtr(Allocator &alloc, void *p) : allocator(alloc), mine(p) { }
186 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
187 : allocator(src.allocator), mine(src.release()) { }
188 template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
189 : allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
190
191 ~CssmAutoPtr() { destroy(mine, allocator); }
192
193 void *get() throw() { return mine; }
194 void *release() { void *result = mine; mine = NULL; return result; }
195 void reset() { allocator.free(mine); mine = NULL; }
196
197 private:
198 void *mine;
199 };
200
201
202 //
203 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
204 //
205 template <class T>
206 class CssmNewAutoPtr : public CssmAutoPtr<T> {
207 public:
208 CssmNewAutoPtr(Allocator &alloc = Allocator::standard())
209 : CssmAutoPtr<T>(alloc, new(alloc) T) { }
210
211 template <class A1>
212 CssmNewAutoPtr(Allocator &alloc, A1 &arg1) : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
213 template <class A1>
214 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1)
215 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
216
217 template <class A1, class A2>
218 CssmNewAutoPtr(Allocator &alloc, A1 &arg1, A2 &arg2)
219 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
220 template <class A1, class A2>
221 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, A2 &arg2)
222 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
223 template <class A1, class A2>
224 CssmNewAutoPtr(Allocator &alloc, A1 &arg1, const A2 &arg2)
225 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
226 template <class A1, class A2>
227 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, const A2 &arg2)
228 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
229 };
230
231
232 } // end namespace Security
233
234
235 //
236 // Global C++ allocation hooks to use Allocators (global namespace)
237 //
238 inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc)
239 { return allocator.malloc(size); }
240
241 inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc)
242 { return allocator.malloc(size); }
243
244
245 #endif //_H_ALLOC