8fbfd841140af25231dacbe7b6f60bb7695ff023
[yaz-moved-to-github.git] / util / nmem.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: nmem.c,v $
7  * Revision 1.1  1995-11-13 09:27:52  quinn
8  * Fiddling with the variant stuff.
9  *
10  *
11  */
12
13 /*
14  * This is a simple and fairly wasteful little module for nibble memory
15  * allocation. Evemtually we'll put in something better.
16  */
17
18 #include <xmalloc.h>
19 #include <nmem.h>
20
21 #define NMEM_CHUNK (10*1024)
22
23 typedef struct nmem_block
24 {
25     char *buf;              /* memory allocated in this block */
26     int size;               /* size of buf */
27     int top;                /* top of buffer */
28     struct nmem_block *next;
29 } nmem_block;
30
31 typedef struct nmem_control
32 {
33     int total;
34     nmem_block *blocks;
35 } nmem_control;
36
37 static nmem_block *freelist = 0; /* global freelist */
38
39 static void free_block(nmem_block *p)
40 {
41     p->next = freelist;
42     freelist = p;
43 }
44
45 /*
46  * acquire a block with a minimum of size free bytes.
47  */
48 static nmem_block *get_block(int size)
49 {
50     nmem_block *r, *l;
51
52     for (r = freelist, l = 0; r; l = r, r = r->next)
53         if (r->size >= size)
54             break;
55     if (r)
56         if (l)
57             l->next = r->next;
58         else
59             freelist = r->next;
60     else
61     {
62         int get = NMEM_CHUNK;
63
64         if (get < size)
65             get = size;
66         r = xmalloc(sizeof(*r));
67         r->buf = xmalloc(r->size = get);
68     }
69     r->top = 0;
70     return r;
71 }
72
73 void nmem_reset(NMEM n)
74 {
75     nmem_block *t;
76
77     if (!n)
78         return;
79     while (n->blocks)
80     {
81         t = n->blocks;
82         n->blocks = n->blocks->next;
83         free_block(t);
84     }
85     n->total = 0;
86 }
87
88 void *nmem_malloc(NMEM n, int size)
89 {
90     struct nmem_block *p;
91     char *r;
92
93     if (!n)
94         return xmalloc(size);
95     p = n->blocks;
96     if (!p || p->size - p->top < size)
97     {
98         p = get_block(size);
99         p->next = n->blocks;
100         n->blocks = p;
101     }
102     r = p->buf + p->top;
103     /* align size */
104     p->top += (size + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
105     n->total += size;
106     return r;
107 }
108
109 int nmem_total(NMEM n)
110 {
111     return n->total;
112 }
113
114 NMEM nmem_create(void)
115 {
116     NMEM r = xmalloc(sizeof(*r));
117     
118     r->blocks = 0;
119     r->total = 0;
120     return r;
121 }
122
123 void nmem_destroy(NMEM n)
124 {
125     if (!n)
126         return;
127     nmem_reset(n);
128     xfree(n);
129 }