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