#ifndef MEMLOGGER_HPP
#define MEMLOGGER_HPP

#include <vector>
#include <memory>
#include <utility>

#include "CompressedFile.hpp"
#include "MemHeader.hpp"

namespace mem
{
  typedef void* (*MEM_MALLOC)(size_t);
  typedef void* (*MEM_CALLOC)(size_t,size_t);
  typedef void* (*MEM_REALLOC)(void*,size_t);
  typedef void (*MEM_FREE)(void*);

  MEM_MALLOC real_malloc = 0;
  MEM_FREE real_free = 0;
  MEM_CALLOC real_calloc = 0;
  MEM_REALLOC real_realloc = 0;


  class MemLogger
  {
  public:
    void alloc(int id, void* addr, size_t size);
    void dealloc(void* addr);

    void writeMessage(const Header& head, void* data);

    static MemLogger* instance();

    struct HeaderAlloc
    {
      Header head_;
      void* addr_;
      int size_;
    };

    struct HeaderFree
    {
      Header head_;
      void* addr_;
    };

    typedef void* Stack[120];

    struct EventAlloc
    {
      HeaderAlloc com_;
      Stack ptrs_;
    };
    struct EventFree
    {
      HeaderFree com_;
      Stack ptrs_;
    };

    static const int alloc_head_sz = sizeof(HeaderAlloc)/sizeof(int);
    static const int free_head_sz = sizeof(HeaderFree)/sizeof(int);
    static const int ptrs_sz = sizeof(Stack)/sizeof(void*);

    void activate();
    void deactivate();

    void includePath();
    void excludePath();

    void stop();

  protected:
    MemLogger();
    ~MemLogger();
    MemLogger& operator=(const MemLogger&);
    MemLogger(const MemLogger&);

  private:
    bool is_stopped_;
    bool is_active_;
    bool want_path_;
    CompressedFile* file_;
    int filenum_;
    EventFree event_free_;
    EventAlloc event_alloc_;
    char* buf_[1000];
    int trunc_stack_count_; // zero == none
  };
}

#endif
