38949070cbb7a9bb28dc78625633b02e869b3e2b
[yaz-moved-to-github.git] / odr / odr_mem.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_mem.c,v $
7  * Revision 1.11  1995-11-01 13:54:43  quinn
8  * Minor adjustments
9  *
10  * Revision 1.10  1995/10/25  16:58:19  quinn
11  * Stupid bug in odr_malloc
12  *
13  * Revision 1.9  1995/10/13  16:08:08  quinn
14  * Added OID utility
15  *
16  * Revision 1.8  1995/09/29  17:12:24  quinn
17  * Smallish
18  *
19  * Revision 1.7  1995/09/27  15:02:59  quinn
20  * Modified function heads & prototypes.
21  *
22  * Revision 1.6  1995/08/21  09:10:41  quinn
23  * Smallish fixes to suppport new formats.
24  *
25  * Revision 1.5  1995/05/16  08:50:55  quinn
26  * License, documentation, and memory fixes
27  *
28  * Revision 1.4  1995/05/15  11:56:09  quinn
29  * More work on memory management.
30  *
31  * Revision 1.3  1995/04/18  08:15:21  quinn
32  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
33  * neater. We'll make the same change for decoding one day.
34  *
35  * Revision 1.2  1995/03/17  10:17:52  quinn
36  * Added memory management.
37  *
38  * Revision 1.1  1995/03/14  10:27:40  quinn
39  * Modified makefile to use common lib
40  * Beginning to add memory management to odr
41  *
42  */
43
44 #include <stdlib.h>
45 #include <odr.h>
46 #include <xmalloc.h>
47
48 /* ------------------------ NIBBLE MEMORY ---------------------- */
49
50 #define ODR_MEM_CHUNK (10*1024)
51
52 typedef struct odr_memblock
53 {
54     char *buf;
55     int size;
56     int top;
57     int total;
58     struct odr_memblock *next;
59 } odr_memblock;
60
61 static odr_memblock *freelist = 0; /* global freelist */
62
63 static void free_block(odr_memblock *p)
64 {
65     p->next = freelist;
66     freelist = p;
67 }
68
69 /*
70  * acquire a block with a minimum of size free bytes.
71  */
72 static odr_memblock *get_block(int size)
73 {
74     odr_memblock *r, *l;
75
76     for (r = freelist, l = 0; r; l = r, r = r->next)
77         if (r->size >= size)
78             break;
79     if (r)
80         if (l)
81             l->next = r->next;
82         else
83             freelist = r->next;
84     else
85     {
86         int get = ODR_MEM_CHUNK;
87
88         if (get < size)
89             get = size;
90         if (!(r = xmalloc(sizeof(*r))))
91             abort();
92         if (!(r->buf = xmalloc(r->size = get)))
93             abort();
94     }
95     r->top = 0;
96     r->total = 0;
97     return r;
98 }
99
100 /*
101  * Return p to the global freelist.
102  */
103 void odr_release_mem(ODR_MEM p)
104 {
105     odr_memblock *t;
106
107     while (p)
108     {
109         t = p;
110         p = p->next;
111         free_block(t);
112     }
113 }
114
115 /*
116  * Extract the memory control block from o.
117  */
118 ODR_MEM odr_extract_mem(ODR o)
119 {
120     ODR_MEM r = o->mem;
121
122     o->mem = 0;
123     return r;
124 }
125
126 void *odr_malloc(ODR o, int size)
127 {
128     struct odr_memblock *p;
129     char *r;
130
131     if (!o)
132     {
133         if (!(r = xmalloc(size)))
134             abort();
135         return r;
136     }
137     p = o->mem;
138     if (!p || p->size - p->top < size)
139         if (!(p = get_block(size)))
140             abort();
141         else
142         {
143             if (o->mem)
144                 p->total = o->mem->total;
145             p->next = o->mem;
146             o->mem = p;
147         }
148     r = p->buf + p->top;
149     /* align size */
150     p->top += (size + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
151     p->total += size;
152     return r;
153 }
154
155 int odr_total(ODR o)
156 {
157     return o->mem ? o->mem->total : 0;
158 }
159
160 /* ---------- memory management for data encoding ----------*/
161
162
163 int odr_grow_block(odr_ecblock *b, int min_bytes)
164 {
165     int togrow;
166
167     if (!b->can_grow)
168         return -1;
169     if (!b->size)
170         togrow = 1024;
171     else
172         togrow = b->size;
173     if (togrow < min_bytes)
174         togrow = min_bytes;
175     if (b->size && !(b->buf =xrealloc(b->buf, b->size += togrow)))
176         abort();
177     else if (!b->size && !(b->buf = xmalloc(b->size = togrow)))
178         abort();
179 #ifdef ODR_DEBUG
180     fprintf(stderr, "New size for encode_buffer: %d\n", b->size);
181 #endif
182     return 0;
183 }
184
185 int odr_write(ODR o, unsigned char *buf, int bytes)
186 {
187     if (o->ecb.pos + bytes >= o->ecb.size && odr_grow_block(&o->ecb, bytes))
188     {
189         o->error = OSPACE;
190         return -1;
191     }
192     memcpy(o->ecb.buf + o->ecb.pos, buf, bytes);
193     o->ecb.pos += bytes;
194     if (o->ecb.pos > o->ecb.top)
195         o->ecb.top = o->ecb.pos;
196     return 0;
197 }
198
199 int odr_seek(ODR o, int whence, int offset)
200 {
201     if (whence == ODR_S_CUR)
202         offset += o->ecb.pos;
203     else if (whence == ODR_S_END)
204         offset += o->ecb.top;
205     if (offset > o->ecb.size && odr_grow_block(&o->ecb, offset - o->ecb.size))
206     {
207         o->error = OSPACE;
208         return -1;
209     }
210     o->ecb.pos = offset;
211     return 0;
212 }