Added dynamic memory allocation on encoding (whew). Code is now somewhat
[yaz-moved-to-github.git] / odr / odr_mem.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_mem.c,v $
7  * Revision 1.3  1995-04-18 08:15:21  quinn
8  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
9  * neater. We'll make the same change for decoding one day.
10  *
11  * Revision 1.2  1995/03/17  10:17:52  quinn
12  * Added memory management.
13  *
14  * Revision 1.1  1995/03/14  10:27:40  quinn
15  * Modified makefile to use common lib
16  * Beginning to add memory management to odr
17  *
18  */
19
20 #include <stdlib.h>
21 #include <odr.h>
22
23 /* ------------------------ NIBBLE MEMORY ---------------------- */
24
25 #define ODR_MEM_CHUNK (10*1024)
26
27 typedef struct odr_memblock
28 {
29     char *buf;
30     int size;
31     int top;
32     struct odr_memblock *next;
33 } odr_memblock;
34
35 static odr_memblock *freelist = 0;
36
37 static void free_block(odr_memblock *p)
38 {
39     p->next = freelist;
40     freelist = p;
41 }
42
43 static odr_memblock *get_block(int size)
44 {
45     odr_memblock *r, *l;
46
47     for (r = freelist, l = 0; r; l = r, r = r->next)
48         if (r->size >= size)
49             break;
50     if (r)
51         if (l)
52             l->next = r->next;
53         else
54             freelist = r->next;
55     else
56     {
57         int get = ODR_MEM_CHUNK;
58
59         if (get < size)
60             get = size;
61         if (!(r = malloc(sizeof(*r))))
62             abort();
63         if (!(r->buf = malloc(r->size = get)))
64             abort();
65     }
66     r->top = 0;
67     return r;
68 }
69
70 void odr_release_mem(odr_memblock *p)
71 {
72     odr_memblock *t;
73
74     while (p)
75     {
76         t = p;
77         p = p->next;
78         free_block(t);
79     }
80 }
81
82 void *odr_malloc(ODR o, int size)
83 {
84     struct odr_memblock *p = o->mem;
85     char *r;
86
87     if (!p || p->size - p->top < size)
88         if (!(p = get_block(size)))
89         {
90             o->error = OMEMORY;
91             return 0;
92         }
93         else
94         {
95             p->next = o->mem;
96             o->mem = p;
97         }
98     r = p->buf + p->top;
99     p->top += (size + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
100     return r;
101 }
102
103 /* ---------- memory management for data encoding ----------*/
104
105
106 int odr_grow_block(odr_ecblock *b, int min_bytes)
107 {
108     int togrow;
109
110     if (!b->can_grow)
111         return -1;
112     if (!b->size)
113         togrow = 1024;
114     else
115         togrow = b->size;
116     if (togrow < min_bytes)
117         togrow = min_bytes;
118     if (b->size && !(b->buf = realloc(b->buf, b->size += togrow)))
119         abort();
120     else if (!b->size && !(b->buf = malloc(b->size = togrow)))
121         abort();
122 #ifdef ODR_DEBUG
123     fprintf(stderr, "New size for encode_buffer: %d\n", b->size);
124 #endif
125     return 0;
126 }
127
128 int odr_write(ODR o, unsigned char *buf, int bytes)
129 {
130     if (o->ecb.pos + bytes >= o->ecb.size && odr_grow_block(&o->ecb, bytes))
131     {
132         o->error = OSPACE;
133         return -1;
134     }
135     memcpy(o->ecb.buf + o->ecb.pos, buf, bytes);
136     o->ecb.pos += bytes;
137     if (o->ecb.pos > o->ecb.top)
138         o->ecb.top = o->ecb.pos;
139     return 0;
140 }
141
142 int odr_seek(ODR o, int whence, int offset)
143 {
144     if (whence == ODR_S_CUR)
145         offset += o->ecb.pos;
146     else if (whence == ODR_S_END)
147         offset += o->ecb.top;
148     if (offset > o->ecb.size && odr_grow_block(&o->ecb, offset - o->ecb.size))
149     {
150         o->error = OSPACE;
151         return -1;
152     }
153     o->ecb.pos = offset;
154     return 0;
155 }