]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmalloc.h
Security-179.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmalloc.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // cssmalloc - memory allocation in the CDSA world
21 //
22 #ifndef _H_CSSMALLOC
23 #define _H_CSSMALLOC
24
25 #include <Security/utilities.h>
26 #include <Security/cssm.h>
27 #include <cstring>
28
29 #ifdef _CPP_CSSMALLOC
30 # pragma export on
31 #endif
32
33 namespace Security
34 {
35
36 //
37 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
38 // that CDSA loves so much. If you have an allocation strategy and want objects
39 // to be allocated through it, inherit from this.
40 //
41 class CssmAllocator {
42 public:
43 virtual ~CssmAllocator();
44 virtual void *malloc(size_t) throw(std::bad_alloc) = 0;
45 virtual void free(void *) throw() = 0;
46 virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0;
47
48 //
49 // Template versions for added expressiveness.
50 // Note that the integers are element counts, not byte sizes.
51 //
52 template <class T> T *alloc() throw(std::bad_alloc)
53 { return reinterpret_cast<T *>(malloc(sizeof(T))); }
54
55 template <class T> T *alloc(uint32 count) throw(std::bad_alloc)
56 { return reinterpret_cast<T *>(malloc(sizeof(T) * count)); }
57
58 template <class T> T *alloc(T *old, uint32 count) throw(std::bad_alloc)
59 { return reinterpret_cast<T *>(realloc(old, sizeof(T) * count)); }
60
61 template <class Data> CssmData alloc(const Data &source) throw(std::bad_alloc)
62 {
63 size_t length = source.length();
64 return CssmData(memcpy(malloc(length), source.data(), length), length);
65 }
66
67 //
68 // Happier malloc/realloc for any type. Note that these still have
69 // the original (byte-sized) argument profile.
70 //
71 template <class T> T *malloc(size_t size) throw(std::bad_alloc)
72 { return reinterpret_cast<T *>(malloc(size)); }
73
74 template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
75 { return reinterpret_cast<T *>(realloc(addr, size)); }
76
77 // All right, if you *really* have to have calloc...
78 void *calloc(size_t size, unsigned int count) throw(std::bad_alloc)
79 {
80 void *addr = malloc(size * count);
81 memset(addr, 0, size * count);
82 return addr;
83 }
84
85 // compare CssmAllocators for identity
86 virtual bool operator == (const CssmAllocator &alloc) const throw();
87
88 public:
89 // allocator chooser options
90 enum {
91 normal = 0x0000,
92 sensitive = 0x0001
93 };
94
95 static CssmAllocator &standard(uint32 request = normal);
96 };
97
98
99 //
100 // A POD wrapper for the memory functions structure passed around in CSSM.
101 //
102 class CssmMemoryFunctions : public PodWrapper<CssmMemoryFunctions, CSSM_MEMORY_FUNCS> {
103 public:
104 CssmMemoryFunctions(const CSSM_MEMORY_FUNCS &funcs)
105 { *(CSSM_MEMORY_FUNCS *)this = funcs; }
106 CssmMemoryFunctions() { }
107
108 void *malloc(size_t size) const throw(std::bad_alloc);
109 void free(void *mem) const throw() { free_func(mem, AllocRef); }
110 void *realloc(void *mem, size_t size) const throw(std::bad_alloc);
111 void *calloc(uint32 count, size_t size) const throw(std::bad_alloc);
112
113 bool operator == (const CSSM_MEMORY_FUNCS &other) const throw()
114 { return !memcmp(this, &other, sizeof(*this)); }
115 };
116
117 inline void *CssmMemoryFunctions::malloc(size_t size) const throw(std::bad_alloc)
118 {
119 if (void *addr = malloc_func(size, AllocRef))
120 return addr;
121 throw std::bad_alloc();
122 }
123
124 inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const throw(std::bad_alloc)
125 {
126 if (void *addr = calloc_func(count, size, AllocRef))
127 return addr;
128 throw std::bad_alloc();
129 }
130
131 inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const throw(std::bad_alloc)
132 {
133 if (void *addr = realloc_func(mem, size, AllocRef))
134 return addr;
135 throw std::bad_alloc();
136 }
137
138
139 //
140 // A CssmAllocator based on CssmMemoryFunctions
141 //
142 class CssmMemoryFunctionsAllocator : public CssmAllocator {
143 public:
144 CssmMemoryFunctionsAllocator(const CssmMemoryFunctions &memFuncs) : functions(memFuncs) { }
145
146 void *malloc(size_t size) throw(std::bad_alloc);
147 void free(void *addr) throw();
148 void *realloc(void *addr, size_t size) throw(std::bad_alloc);
149
150 operator const CssmMemoryFunctions & () const throw() { return functions; }
151
152 private:
153 const CssmMemoryFunctions functions;
154 };
155
156 } // end namespace Security
157
158 //
159 // Global C++ allocation hooks to use CssmAllocators
160 //
161 inline void *operator new (size_t size, CssmAllocator &allocator) throw (std::bad_alloc)
162 { return allocator.malloc(size); }
163
164 inline void *operator new[] (size_t size, CssmAllocator &allocator) throw (std::bad_alloc)
165 { return allocator.malloc(size); }
166
167
168 //
169 // You'd think that this is operator delete(const T *, CssmAllocator &), but you'd
170 // be wrong. Specialized operator delete is only called during constructor cleanup.
171 // Use this to cleanly destroy things.
172 //
173 template <class T>
174 inline void destroy(T *obj, CssmAllocator &alloc) throw()
175 {
176 obj->~T();
177 alloc.free(obj);
178 }
179
180 // untyped (release memory only, no destructor call)
181 inline void destroy(void *obj, CssmAllocator &alloc) throw()
182 {
183 alloc.free(obj);
184 }
185
186 namespace Security
187 {
188
189 //
190 // A MemoryFunctions object based on a CssmAllocator.
191 // Note that we don't copy the CssmAllocator object. It needs to live (at least)
192 // as long as any CssmAllocatorMemoryFunctions object based on it.
193 //
194 class CssmAllocatorMemoryFunctions : public CssmMemoryFunctions {
195 public:
196 CssmAllocatorMemoryFunctions(CssmAllocator &alloc);
197 CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef = NULL /*)*/ ; } // later assignment req'd
198
199 private:
200 static void *relayMalloc(size_t size, void *ref) throw(std::bad_alloc);
201 static void relayFree(void *mem, void *ref) throw();
202 static void *relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc);
203 static void *relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc);
204
205 static CssmAllocator &allocator(void *ref) throw()
206 { return *reinterpret_cast<CssmAllocator *>(ref); }
207 };
208
209
210 //
211 // A mixin class to automagically manage your allocator.
212 // To allow allocation (of your object) from any instance of CssmAllocator,
213 // inherit from CssmHeap. Your users can then create heap instances of your thing by
214 // new (an-allocator) YourClass(...)
215 // or (still)
216 // new YourClass(...)
217 // for the default allocation source. The beauty is that when someone does a
218 // delete pointer-to-your-instance
219 // then the magic fairies will find the allocator that created the object and ask it
220 // to free the memory (by calling its free() method).
221 // The price of all that glory is memory overhead - typically one pointer per object.
222 //
223 class CssmHeap {
224 public:
225 void *operator new (size_t size, CssmAllocator *alloc = NULL) throw(std::bad_alloc);
226 void operator delete (void *addr, size_t size) throw();
227 void operator delete (void *addr, size_t size, CssmAllocator *alloc) throw();
228 };
229
230
231 //
232 // Here is a version of auto_ptr that works with CssmAllocators. It is designed
233 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
234 // argument, of course.
235 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
236 // You can't dereference it, naturally.
237 //
238 template <class T>
239 class CssmAutoPtr {
240 public:
241 CssmAllocator &allocator;
242
243 CssmAutoPtr(CssmAllocator &alloc = CssmAllocator::standard())
244 : allocator(alloc), mine(NULL) { }
245 CssmAutoPtr(CssmAllocator &alloc, T *p)
246 : allocator(alloc), mine(p) { }
247 CssmAutoPtr(T *p)
248 : allocator(CssmAllocator::standard()), mine(p) { }
249 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
250 : allocator(src.allocator), mine(src.release()) { }
251 template <class T1> CssmAutoPtr(CssmAllocator &alloc, CssmAutoPtr<T1> &src)
252 : allocator(alloc), mine(rc.release()) { assert(allocator == src.allocator); }
253
254 ~CssmAutoPtr() { allocator.free(mine); }
255
256 T *get() const throw() { return mine; }
257 T *release() { T *result = mine; mine = NULL; return result; }
258 void reset() { allocator.free(mine); mine = NULL; }
259
260 operator T * () const { return mine; }
261 T *operator -> () const { return mine; }
262 T &operator * () const { assert(mine); return *mine; }
263
264 private:
265 T *mine;
266 };
267
268 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
269 template <>
270 class CssmAutoPtr<void> {
271 public:
272 CssmAllocator &allocator;
273
274 CssmAutoPtr(CssmAllocator &alloc) : allocator(alloc), mine(NULL) { }
275 CssmAutoPtr(CssmAllocator &alloc, void *p) : allocator(alloc), mine(p) { }
276 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
277 : allocator(src.allocator), mine(src.release()) { }
278 template <class T1> CssmAutoPtr(CssmAllocator &alloc, CssmAutoPtr<T1> &src)
279 : allocator(alloc), mine(rc.release()) { assert(allocator == src.allocator); }
280
281 ~CssmAutoPtr() { destroy(mine, allocator); }
282
283 void *get() throw() { return mine; }
284 void *release() { void *result = mine; mine = NULL; return result; }
285 void reset() { allocator.free(mine); mine = NULL; }
286
287 private:
288 void *mine;
289 };
290
291
292 //
293 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
294 //
295 template <class T>
296 class CssmNewAutoPtr : public CssmAutoPtr<T> {
297 public:
298 CssmNewAutoPtr(CssmAllocator &alloc = CssmAllocator::standard())
299 : CssmAutoPtr<T>(alloc, new(alloc) T) { }
300
301 template <class A1>
302 CssmNewAutoPtr(CssmAllocator &alloc, A1 &arg1) : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
303 template <class A1>
304 CssmNewAutoPtr(CssmAllocator &alloc, const A1 &arg1)
305 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
306
307 template <class A1, class A2>
308 CssmNewAutoPtr(CssmAllocator &alloc, A1 &arg1, A2 &arg2)
309 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
310 template <class A1, class A2>
311 CssmNewAutoPtr(CssmAllocator &alloc, const A1 &arg1, A2 &arg2)
312 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
313 template <class A1, class A2>
314 CssmNewAutoPtr(CssmAllocator &alloc, A1 &arg1, const A2 &arg2)
315 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
316 template <class A1, class A2>
317 CssmNewAutoPtr(CssmAllocator &alloc, const A1 &arg1, const A2 &arg2)
318 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
319 };
320
321
322 //
323 // A generic helper for the unhappily ubiquitous CSSM-style
324 // (count, pointer-to-array) style of arrays.
325 //
326 template <class Base, class Wrapper = Base>
327 class CssmVector {
328 public:
329 CssmVector(uint32 &cnt, Base * &vec, CssmAllocator &alloc = CssmAllocator::standard())
330 : count(cnt), vector(reinterpret_cast<Wrapper * &>(vec)),
331 allocator(alloc)
332 {
333 count = 0;
334 vector = NULL;
335 }
336
337 ~CssmVector() { allocator.free(vector); }
338
339 uint32 &count;
340 Wrapper * &vector;
341 CssmAllocator &allocator;
342
343 public:
344 Wrapper &operator [] (uint32 ix)
345 { assert(ix < count); return vector[ix]; }
346
347 void operator += (const Wrapper &add)
348 {
349 vector = reinterpret_cast<Wrapper *>(allocator.realloc(vector, (count + 1) * sizeof(Wrapper)));
350 //@@@???compiler bug??? vector = allocator.alloc<Wrapper>(vector, count + 1);
351 vector[count++] = add;
352 }
353 };
354
355
356 } // end namespace Security
357
358 #ifdef _CPP_CSSMALLOC
359 # pragma export off
360 #endif
361
362 #endif //_H_CSSMALLOC