#ifndef _H_ALLOC
#define _H_ALLOC
#include <security_utilities/utilities.h>
#include <cstring>
namespace Security
{
class Allocator {
public:
virtual ~Allocator();
virtual void *malloc(size_t) throw(std::bad_alloc) = 0;
virtual void free(void *) throw() = 0;
virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0;
template <class T> T *alloc() throw(std::bad_alloc)
{ return reinterpret_cast<T *>(malloc(sizeof(T))); }
template <class T> T *alloc(UInt32 count) throw(std::bad_alloc)
{ return reinterpret_cast<T *>(malloc(sizeof(T) * count)); }
template <class T> T *alloc(T *old, UInt32 count) throw(std::bad_alloc)
{ return reinterpret_cast<T *>(realloc(old, sizeof(T) * count)); }
template <class T> T *malloc(size_t size) throw(std::bad_alloc)
{ return reinterpret_cast<T *>(malloc(size)); }
template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
{ return reinterpret_cast<T *>(realloc(addr, size)); }
void *calloc(size_t size, size_t count) throw(std::bad_alloc)
{
void *addr = malloc(size * count);
memset(addr, 0, size * count);
return addr;
}
virtual bool operator == (const Allocator &alloc) const throw();
public:
enum {
normal = 0x0000,
sensitive = 0x0001
};
static Allocator &standard(UInt32 request = normal);
};
template <class T>
inline void destroy(T *obj, Allocator &alloc) throw()
{
obj->~T();
alloc.free(obj);
}
inline void destroy(void *obj, Allocator &alloc) throw()
{
alloc.free(obj);
}
class CssmHeap {
public:
void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc);
void operator delete (void *addr, size_t size) throw();
void operator delete (void *addr, size_t size, Allocator *alloc) throw();
};
template <class T>
class CssmAutoPtr {
public:
Allocator &allocator;
CssmAutoPtr(Allocator &alloc = Allocator::standard())
: allocator(alloc), mine(NULL) { }
CssmAutoPtr(Allocator &alloc, T *p)
: allocator(alloc), mine(p) { }
CssmAutoPtr(T *p)
: allocator(Allocator::standard()), mine(p) { }
template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
: allocator(src.allocator), mine(src.release()) { }
template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
: allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
~CssmAutoPtr() { allocator.free(mine); }
T *get() const throw() { return mine; }
T *release() { T *result = mine; mine = NULL; return result; }
void reset() { allocator.free(mine); mine = NULL; }
operator T * () const { return mine; }
T *operator -> () const { return mine; }
T &operator * () const { assert(mine); return *mine; }
private:
T *mine;
};
template <>
class CssmAutoPtr<void> {
public:
Allocator &allocator;
CssmAutoPtr(Allocator &alloc) : allocator(alloc), mine(NULL) { }
CssmAutoPtr(Allocator &alloc, void *p) : allocator(alloc), mine(p) { }
template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
: allocator(src.allocator), mine(src.release()) { }
template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
: allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
~CssmAutoPtr() { destroy(mine, allocator); }
void *get() throw() { return mine; }
void *release() { void *result = mine; mine = NULL; return result; }
void reset() { allocator.free(mine); mine = NULL; }
private:
void *mine;
};
template <class T>
class CssmNewAutoPtr : public CssmAutoPtr<T> {
public:
CssmNewAutoPtr(Allocator &alloc = Allocator::standard())
: CssmAutoPtr<T>(alloc, new(alloc) T) { }
template <class A1>
CssmNewAutoPtr(Allocator &alloc, A1 &arg1) : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
template <class A1>
CssmNewAutoPtr(Allocator &alloc, const A1 &arg1)
: CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
template <class A1, class A2>
CssmNewAutoPtr(Allocator &alloc, A1 &arg1, A2 &arg2)
: CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
template <class A1, class A2>
CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, A2 &arg2)
: CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
template <class A1, class A2>
CssmNewAutoPtr(Allocator &alloc, A1 &arg1, const A2 &arg2)
: CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
template <class A1, class A2>
CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, const A2 &arg2)
: CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
};
}
inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc)
{ return allocator.malloc(size); }
inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc)
{ return allocator.malloc(size); }
#endif //_H_ALLOC