#include <stdlib.h>
#include "mempool.h"

void oom();

void mp_init(struct mempool *mp) {
  mp->chunk = NULL;
}

void *mp_alloc(struct mempool *mp, unsigned size) {
  struct mempool_chunk *c;
  if (size >= MEMPOOL_BUFSIZE) {
    c = (struct mempool_chunk*)malloc(sizeof(*c)+size-MEMPOOL_BUFSIZE);
    if (!c) {
      oom();
      return NULL;
    }
    c->size = 0;
    c->next = mp->chunk;
    return c->buf;
  }
  for(c = mp->chunk; c; c = c->next)
    if (c->size >= size) {
      char *b = c->buf + MEMPOOL_BUFSIZE - c->size;
      c->size -= size;
      return b;
    }
  c = (struct mempool_chunk *)malloc(sizeof(*c));
  if (!c) {
    oom();
    return NULL;
  }
  c->next = mp->chunk;
  mp->chunk = c;
  c->size = MEMPOOL_BUFSIZE - size;
  return c->buf;
}

void mp_free(struct mempool *mp) {
  struct mempool_chunk *c;
  while((c = mp->chunk) != NULL) {
    mp->chunk = c->next;
    free(c);
  }
}

char *mp_strdup(struct mempool *mp, const char *str) {
  unsigned l = strlen(str) + 1;
  char *s = (char*)mp_alloc(mp, l);
  if (s) memcpy(s, str, l);
  return s;
}
