/*************************************************
* Secure Memory Allocator Header File            *
* (C) 1999-2003 The Botan Project                *
*************************************************/

#ifndef BOTAN_SECURE_ALLOCATOR_H__
#define BOTAN_SECURE_ALLOCATOR_H__

#include <botan/exceptn.h>
#include <botan/mutex.h>
#include <map>
#include <vector>

namespace Botan {

/*************************************************
* Secure Memory Allocator                        *
*************************************************/
class SecureAllocator
   {
   public:
      struct Memory_Exhaustion : public Exception
         {
         Memory_Exhaustion() :
            Exception("SecureAllocator: Ran out of memory") {}
         };

      class Buffer
         {
         public:
            void* buf;
            u32bit length;
            bool in_use;
            Buffer() { buf = 0; length = 0; in_use = false; }
            Buffer(void* b, u32bit l, bool used = false)
               { buf = b; length = l; in_use = used; }
         };

      void* allocate(u32bit) const;
      void deallocate(void*, u32bit) const;
      void destroy();

      SecureAllocator();
      virtual ~SecureAllocator();
   protected:
      const u32bit PREF_SIZE;
   private:
      static const u32bit ALIGN_TO = 8;

      void* get_block(u32bit) const;
      void free_block(void*, u32bit) const;

      virtual void* alloc_block(u32bit) const = 0;
      virtual void dealloc_block(void*, u32bit) const = 0;

      void* find_free_block(u32bit) const;
      void defrag_free_list() const;

      static bool are_contiguous(const Buffer&, const Buffer&);
      u32bit find_block(void*) const;
      bool same_buffer(Buffer&, Buffer&) const;
      void remove_empty_buffers(std::vector<Buffer>&) const;

      mutable std::vector<Buffer> allocated, free_list;
      mutable Mutex* lock;
      bool destroyed;
   };

}

#endif
