2  * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 
   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 
  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. 
  20 // cssmalloc - memory allocation in the CDSA world 
  25 #include <Security/utilities.h> 
  26 #include <Security/cssm.h> 
  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. 
  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; 
  49         // Template versions for added expressiveness. 
  50         // Note that the integers are element counts, not byte sizes. 
  52         template <class T
> T 
*alloc() throw(std::bad_alloc
) 
  53         { return reinterpret_cast<T 
*>(malloc(sizeof(T
))); } 
  55         template <class T
> T 
*alloc(uint32 count
) throw(std::bad_alloc
) 
  56         { return reinterpret_cast<T 
*>(malloc(sizeof(T
) * count
)); } 
  58         template <class T
> T 
*alloc(T 
*old
, uint32 count
) throw(std::bad_alloc
) 
  59         { return reinterpret_cast<T 
*>(realloc(old
, sizeof(T
) * count
)); } 
  61         template <class Data
> CssmData 
alloc(const Data 
&source
) throw(std::bad_alloc
) 
  63                 size_t length 
= source
.length(); 
  64                 return CssmData(memcpy(malloc(length
), source
.data(), length
), length
); 
  68         // Happier malloc/realloc for any type. Note that these still have 
  69         // the original (byte-sized) argument profile. 
  71         template <class T
> T 
*malloc(size_t size
) throw(std::bad_alloc
) 
  72         { return reinterpret_cast<T 
*>(malloc(size
)); } 
  74         template <class T
> T 
*realloc(void *addr
, size_t size
) throw(std::bad_alloc
) 
  75         { return reinterpret_cast<T 
*>(realloc(addr
, size
)); } 
  77         // All right, if you *really* have to have calloc... 
  78         void *calloc(size_t size
, unsigned int count
) throw(std::bad_alloc
) 
  80                 void *addr 
= malloc(size 
* count
); 
  81                 memset(addr
, 0, size 
* count
); 
  85         // compare CssmAllocators for identity 
  86         virtual bool operator == (const CssmAllocator 
&alloc
) const throw(); 
  89         // allocator chooser options 
  95         static CssmAllocator 
&standard(uint32 request 
= normal
); 
 100 // A POD wrapper for the memory functions structure passed around in CSSM. 
 102 class CssmMemoryFunctions 
: public PodWrapper
<CssmMemoryFunctions
, CSSM_MEMORY_FUNCS
> { 
 104         CssmMemoryFunctions(const CSSM_MEMORY_FUNCS 
&funcs
) 
 105         { *(CSSM_MEMORY_FUNCS 
*)this = funcs
; } 
 106         CssmMemoryFunctions() { } 
 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
); 
 113         bool operator == (const CSSM_MEMORY_FUNCS 
&other
) const throw() 
 114         { return !memcmp(this, &other
, sizeof(*this)); } 
 117 inline void *CssmMemoryFunctions::malloc(size_t size
) const throw(std::bad_alloc
) 
 119         if (void *addr 
= malloc_func(size
, AllocRef
)) 
 121         throw std::bad_alloc(); 
 124 inline void *CssmMemoryFunctions::calloc(uint32 count
, size_t size
) const throw(std::bad_alloc
) 
 126         if (void *addr 
= calloc_func(count
, size
, AllocRef
)) 
 128         throw std::bad_alloc(); 
 131 inline void *CssmMemoryFunctions::realloc(void *mem
, size_t size
) const throw(std::bad_alloc
) 
 133         if (void *addr 
= realloc_func(mem
, size
, AllocRef
)) 
 135         throw std::bad_alloc(); 
 140 // A CssmAllocator based on CssmMemoryFunctions 
 142 class CssmMemoryFunctionsAllocator 
: public CssmAllocator 
{ 
 144         CssmMemoryFunctionsAllocator(const CssmMemoryFunctions 
&memFuncs
) : functions(memFuncs
) { } 
 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
); 
 150         operator const CssmMemoryFunctions 
& () const throw() { return functions
; } 
 153         const CssmMemoryFunctions functions
; 
 156 } // end namespace Security 
 159 // Global C++ allocation hooks to use CssmAllocators 
 161 inline void *operator new (size_t size
, CssmAllocator 
&allocator
) throw (std::bad_alloc
) 
 162 { return allocator
.malloc(size
); } 
 164 inline void *operator new[] (size_t size
, CssmAllocator 
&allocator
) throw (std::bad_alloc
) 
 165 { return allocator
.malloc(size
); } 
 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. 
 174 inline void destroy(T 
*obj
, CssmAllocator 
&alloc
) throw() 
 180 // untyped (release memory only, no destructor call) 
 181 inline void destroy(void *obj
, CssmAllocator 
&alloc
) throw() 
 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. 
 194 class CssmAllocatorMemoryFunctions 
: public CssmMemoryFunctions 
{ 
 196         CssmAllocatorMemoryFunctions(CssmAllocator 
&alloc
); 
 197         CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef 
= NULL 
/*)*/ ; } // later assignment req'd 
 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
); 
 205         static CssmAllocator 
&allocator(void *ref
) throw() 
 206         { return *reinterpret_cast<CssmAllocator 
*>(ref
); } 
 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(...) 
 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. 
 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(); 
 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. 
 241         CssmAllocator 
&allocator
; 
 243         CssmAutoPtr(CssmAllocator 
&alloc 
= CssmAllocator::standard()) 
 244         : allocator(alloc
), mine(NULL
) { } 
 245         CssmAutoPtr(CssmAllocator 
&alloc
, T 
*p
) 
 246         : allocator(alloc
), mine(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
); } 
 254         ~CssmAutoPtr()                          { allocator
.free(mine
); } 
 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
; } 
 260         operator T 
* () const           { return mine
; } 
 261         T 
*operator -> () const         { return mine
; } 
 262         T 
&operator * () const          { assert(mine
); return *mine
; } 
 268 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops. 
 270 class CssmAutoPtr
<void> { 
 272         CssmAllocator 
&allocator
; 
 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
); } 
 281         ~CssmAutoPtr()                          { destroy(mine
, allocator
); } 
 283         void *get() throw()             { return mine
; } 
 284         void *release()                         { void *result 
= mine
; mine 
= NULL
; return result
; } 
 285         void reset()                            { allocator
.free(mine
); mine 
= NULL
; } 
 293 // Convenience forms of CssmAutoPtr that automatically make their (initial) object. 
 296 class CssmNewAutoPtr 
: public CssmAutoPtr
<T
> { 
 298         CssmNewAutoPtr(CssmAllocator 
&alloc 
= CssmAllocator::standard()) 
 299         : CssmAutoPtr
<T
>(alloc
, new(alloc
) T
) { } 
 302         CssmNewAutoPtr(CssmAllocator 
&alloc
, A1 
&arg1
) : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { } 
 304         CssmNewAutoPtr(CssmAllocator 
&alloc
, const A1 
&arg1
) 
 305         : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { } 
 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
)) { } 
 323 // A generic helper for the unhappily ubiquitous CSSM-style 
 324 // (count, pointer-to-array) style of arrays. 
 326 template <class Base
, class Wrapper 
= Base
> 
 329     CssmVector(uint32 
&cnt
, Base 
* &vec
, CssmAllocator 
&alloc 
= CssmAllocator::standard()) 
 330         : count(cnt
), vector(reinterpret_cast<Wrapper 
* &>(vec
)), 
 337     ~CssmVector()       { allocator
.free(vector
); } 
 341     CssmAllocator 
&allocator
; 
 344     Wrapper 
&operator [] (uint32 ix
) 
 345     { assert(ix 
< count
); return vector
[ix
]; } 
 347     void operator += (const Wrapper 
&add
) 
 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
; 
 356 } // end namespace Security 
 358 #ifdef _CPP_CSSMALLOC 
 362 #endif //_H_CSSMALLOC