summaryrefslogtreecommitdiff
path: root/stalloc.c
blob: 6a2eb7b92a5a8323cf9fad21c129532cb5b44236 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <stdlib.h>
#include <string.h>

#include "stalloc.h"

struct st_alloc_t {
    int nb_pools;
    char ** mem_pools;
    size_t * pools_size;
};

struct st_alloc_t * st_init() {
    struct st_alloc_t * r = (struct st_alloc_t *) malloc(sizeof(struct st_alloc_t));
    
    if (r) {
        r->nb_pools = 0;
        r->mem_pools = 0;
        r->pools_size = 0;
    }
    
    return r;
}

#define POOL_SIZE 16384

static int create_pool(struct st_alloc_t * s) {
    s->nb_pools++;
    // No error checking, because it'd be a pain to handle.
    s->mem_pools = (char **) realloc(s->mem_pools, sizeof(char *) * s->nb_pools);
    s->pools_size = (size_t *) realloc(s->pools_size, sizeof(size_t) * s->nb_pools);
    s->mem_pools[s->nb_pools - 1] = malloc(POOL_SIZE);
    s->pools_size[s->nb_pools - 1] = 0;
    
    return s->nb_pools - 1;
}

static int search_pool(struct st_alloc_t * s, size_t siz) {
    int i;
    
    // This algorithm could use a little bit more of cleverness, but... *shrug*
    // the whole purpose is to be used for small static strings, so...
    for (i = 0; i < s->nb_pools; i++) {
        if (siz <= (POOL_SIZE - s->pools_size[i]))
            return i;
    }
    
    return -1;
}

void * st_alloc(struct st_alloc_t * s, size_t siz) {
    int pool;
    
    if (siz > POOL_SIZE) {
        pool = create_pool(s);
        s->mem_pools[pool] = realloc(s->mem_pools[pool], siz);
        s->pools_size[pool] = siz;
        return s->mem_pools[pool];
    }
    
    pool = search_pool(s, siz);
    if (pool < 0)
        pool = create_pool(s);
    
    s->pools_size[pool] += siz;
    
    return s->mem_pools[pool] + s->pools_size[pool] - siz;
}

char * st_strdup(struct st_alloc_t * s, const char * src) {
    int siz = strlen(src) + 1;
    char * r = (char *) st_alloc(s, siz);
    memcpy(r, src, siz);
    
    return r;
}

void st_destroy(struct st_alloc_t * s) {
    int i;
    
    for (i = 0; i < s->nb_pools; i++) {
        free(s->mem_pools[i]);
    }
    free(s->mem_pools);
    free(s->pools_size);
    
    free(s);
}