#ifndef _D_ALLOC_H
#define _D_ALLOC_H

#include <string>
#include <map>
#include <vector>
#include "bsstream.h"
#include "bfstream.h"
#include "disk_tools.h"

namespace disk_tools {

using namespace std;
using namespace io_tools;
using namespace text_tools;

class d_database;

typedef long offset_type;

class d_alloc_node {
public:
   offset_type addr;
   offset_type data;
   offset_type size;
   offset_type next;
   bool is_free_node;

   d_alloc_node() {
      addr = 0L;
      data = 0L;
      size = 0L;
      next = 0L;
      is_free_node = false;
   }
   d_alloc_node(const d_alloc_node & cp) {
      addr = cp.addr;
      data = cp.data;
      size = cp.size;
      next = cp.next;
      is_free_node = false;
   }
   ~d_alloc_node() {
   }

   d_alloc_node & operator=(const d_alloc_node & cp) {
      addr = cp.addr;
      data = cp.data;
      size = cp.size;
      next = cp.next;
      is_free_node = cp.is_free_node;
      return *this;
   }

   void load(bfstream & stream) {
      stream >> addr >> data >> size >> next >> is_free_node;
   }

   void store(bfstream & stream) {
      //bstringstream bs;
      stream << addr << data << size << next << is_free_node;
      //char * buffer = bs.get_new_buffer();
      //stream.write(buffer, bs.size());
      //delete [] buffer;
      //stream << addr << data << size << next << is_free_node;
   }
};

class d_alloc {
public:
   typedef list< long > long_list_type;

private:
   bfstream file;
   offset_type addr;
   d_alloc_node head;
   d_alloc_node free_head;

   void insert(d_alloc_node & node);
   void compact();
   void alloc_node(d_alloc_node & node);
   void swap(d_alloc_node & arg1, d_alloc_node & arg2);
   void move_to_alloc_list(offset_type last, d_alloc_node & node);
   void move_to_dealloc_list(offset_type last, d_alloc_node & node);
public:
   d_alloc(const string & file_name);
   ~d_alloc();

   offset_type allocate(const offset_type & size, bstringstream & buffer);
   offset_type allocate(const offset_type & size) { bstringstream buf; return allocate(size, buf); }
   offset_type alloc(const offset_type & size) { return allocate(size); }
   void deallocate(const offset_type & addr);
   void dealloc(const offset_type &addr) { deallocate(addr); }
   bfstream * get_file() { return &file; }
   void sort();
};

//extern d_alloc * global_alloc_ptr;

}

#endif /* _D_ALLOC_H */
