SAA: optimize seeks when used on a byte array
[nasm.git] / saa.c
blob046659e7852121a7cd624a5c6b60ec2f45fe5873
1 #include "compiler.h"
2 #include "nasmlib.h"
3 #include "saa.h"
5 /* Aggregate SAA components smaller than this */
6 #define SAA_BLKSHIFT 16
7 #define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT)
9 struct SAA *saa_init(size_t elem_len)
11 struct SAA *s;
12 char *data;
14 s = nasm_zalloc(sizeof(struct SAA));
16 if (elem_len >= SAA_BLKLEN)
17 s->blk_len = elem_len;
18 else
19 s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
21 s->elem_len = elem_len;
22 s->length = s->blk_len;
23 data = nasm_malloc(s->blk_len);
24 s->nblkptrs = s->nblks = 1;
25 s->blk_ptrs = nasm_malloc(sizeof(char *));
26 s->blk_ptrs[0] = data;
27 s->wblk = s->rblk = &s->blk_ptrs[0];
29 return s;
32 void saa_free(struct SAA *s)
34 char **p;
35 size_t n;
37 for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
38 nasm_free(*p);
40 nasm_free(s->blk_ptrs);
41 nasm_free(s);
44 /* Add one allocation block to an SAA */
45 static void saa_extend(struct SAA *s)
47 size_t blkn = s->nblks++;
49 if (blkn >= s->nblkptrs) {
50 size_t rindex = s->rblk - s->blk_ptrs;
51 size_t windex = s->wblk - s->blk_ptrs;
53 s->nblkptrs <<= 1;
54 s->blk_ptrs = nasm_realloc(s->blk_ptrs, s->nblkptrs*sizeof(char *));
56 s->rblk = s->blk_ptrs + rindex;
57 s->wblk = s->blk_ptrs + windex;
60 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
61 s->length += s->blk_len;
64 void *saa_wstruct(struct SAA *s)
66 void *p;
68 if (s->wpos % s->elem_len)
69 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
70 "misaligned wpos in saa_wstruct");
72 if (s->wpos + s->elem_len > s->blk_len) {
73 if (s->wpos != s->blk_len)
74 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
75 "unfilled block in saa_wstruct");
77 if (s->wptr + s->elem_len > s->length)
78 saa_extend(s);
79 s->wblk++;
80 s->wpos = 0;
83 p = *s->wblk + s->wpos;
84 s->wpos += s->elem_len;
85 s->wptr += s->elem_len;
87 if (s->wptr > s->datalen)
88 s->datalen = s->wptr;
90 return p;
93 void saa_wbytes(struct SAA *s, const void *data, size_t len)
95 const char *d = data;
97 while (len) {
98 size_t l = s->blk_len - s->wpos;
99 if (l > len)
100 l = len;
101 if (l) {
102 if (d) {
103 memcpy(*s->wblk + s->wpos, d, l);
104 d += l;
105 } else
106 memset(*s->wblk + s->wpos, 0, l);
107 s->wpos += l;
108 s->wptr += l;
109 len -= l;
111 if (s->datalen < s->wptr)
112 s->datalen = s->wptr;
114 if (len) {
115 if (s->wptr >= s->length)
116 saa_extend(s);
117 s->wblk++;
118 s->wpos = 0;
123 void saa_rewind(struct SAA *s)
125 s->rblk = s->blk_ptrs;
126 s->rpos = s->rptr = 0;
129 void *saa_rstruct(struct SAA *s)
131 void *p;
133 if (s->rptr + s->elem_len > s->datalen)
134 return NULL;
136 if (s->rpos % s->elem_len)
137 nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
138 "misaligned rpos in saa_rstruct");
140 if (s->rpos + s->elem_len > s->blk_len) {
141 s->rblk++;
142 s->rpos = 0;
145 p = *s->rblk + s->rpos;
146 s->rpos += s->elem_len;
147 s->rptr += s->elem_len;
149 return p;
152 const void *saa_rbytes(struct SAA *s, size_t *lenp)
154 const void *p;
155 size_t len;
157 if (s->rptr >= s->datalen) {
158 *lenp = 0;
159 return NULL;
162 if (s->rpos >= s->blk_len) {
163 s->rblk++;
164 s->rpos = 0;
167 len = *lenp;
168 if (len > s->datalen - s->rptr)
169 len = s->datalen - s->rptr;
170 if (len > s->blk_len - s->rpos)
171 len = s->blk_len - s->rpos;
173 *lenp = len;
174 p = *s->rblk + s->rpos;
176 s->rpos += len;
177 s->rptr += len;
179 return p;
182 void saa_rnbytes(struct SAA *s, void *data, size_t len)
184 char *d = data;
186 if (s->rptr + len > s->datalen) {
187 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_rnbytes");
188 return;
191 while (len) {
192 size_t l;
193 const void *p;
195 l = len;
196 p = saa_rbytes(s, &l);
198 memcpy(d, p, l);
199 d += l;
200 len -= l;
204 /* Same as saa_rnbytes, except position the counter first */
205 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
207 size_t ix;
209 if (posn+len > s->datalen) {
210 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fread");
211 return;
214 if (s->elem_len == 1) {
215 ix = posn >> SAA_BLKSHIFT;
216 s->rpos = posn & (SAA_BLKLEN-1);
217 } else {
218 ix = posn / s->blk_len;
219 s->rpos = posn % s->blk_len;
221 s->rptr = posn;
222 s->rblk = &s->blk_ptrs[ix];
224 saa_rnbytes(s, data, len);
227 /* Same as saa_wbytes, except position the counter first */
228 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
230 size_t ix;
232 if (posn > s->datalen) {
233 /* Seek beyond the end of the existing array not supported */
234 nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fwrite");
235 return;
239 if (s->elem_len == 1) {
240 ix = posn >> SAA_BLKSHIFT;
241 s->wpos = posn & (SAA_BLKLEN-1);
242 } else {
243 ix = posn / s->blk_len;
244 s->wpos = posn % s->blk_len;
246 s->wptr = posn;
247 s->wblk = &s->blk_ptrs[ix];
249 if (!s->wpos) {
250 s->wpos = s->blk_len;
251 s->wblk--;
254 saa_wbytes(s, data, len);
257 void saa_fpwrite(struct SAA *s, FILE * fp)
259 const char *data;
260 size_t len;
262 saa_rewind(s);
263 while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
264 fwrite(data, 1, len, fp);
267 void saa_write8(struct SAA *s, uint8_t v)
269 saa_wbytes(s, &v, 1);
272 #ifdef WORDS_LITTEENDIAN
274 void saa_write16(struct SAA *s, uint16_t v)
276 saa_wbytes(s, &v, 2);
279 void saa_write32(struct SAA *s, uint32_t v)
281 saa_wbytes(s, &v, 4);
284 void saa_write64(struct SAA *s, uint64_t v)
286 saa_wbytes(s, &v, 8);
289 #else /* not WORDS_LITTLEENDIAN */
291 void saa_write16(struct SAA *s, uint16_t v)
293 uint8_t b[2];
295 b[0] = v;
296 b[1] = v >> 8;
297 saa_wbytes(s, b, 2);
300 void saa_write32(struct SAA *s, uint32_t v)
302 uint8_t b[4];
304 b[0] = v;
305 b[1] = v >> 8;
306 b[2] = v >> 16;
307 b[3] = v >> 24;
308 saa_wbytes(s, b, 4);
311 void saa_write64(struct SAA *s, uint64_t v)
313 uint8_t b[8];
315 b[0] = v;
316 b[1] = v >> 8;
317 b[2] = v >> 16;
318 b[3] = v >> 24;
319 b[4] = v >> 32;
320 b[5] = v >> 40;
321 b[6] = v >> 48;
322 b[7] = v >> 56;
323 saa_wbytes(s, b, 8);
326 #endif /* WORDS_LITTLEENDIAN */
328 /* write unsigned LEB128 value to SAA */
329 void saa_wleb128u(struct SAA *psaa, int value)
331 char temp[64], *ptemp;
332 uint8_t byte;
333 int len;
335 ptemp = temp;
336 len = 0;
339 byte = value & 127;
340 value >>= 7;
341 if (value != 0) /* more bytes to come */
342 byte |= 0x80;
343 *ptemp = byte;
344 ptemp++;
345 len++;
346 } while (value != 0);
347 saa_wbytes(psaa, temp, len);
350 /* write signed LEB128 value to SAA */
351 void saa_wleb128s(struct SAA *psaa, int value)
353 char temp[64], *ptemp;
354 uint8_t byte;
355 bool more, negative;
356 int size, len;
358 ptemp = temp;
359 more = 1;
360 negative = (value < 0);
361 size = sizeof(int) * 8;
362 len = 0;
363 while(more)
365 byte = value & 0x7f;
366 value >>= 7;
367 if (negative)
368 /* sign extend */
369 value |= - (1 <<(size - 7));
370 /* sign bit of byte is second high order bit (0x40) */
371 if ((value == 0 && ! (byte & 0x40)) ||
372 ((value == -1) && (byte & 0x40)))
373 more = 0;
374 else
375 byte |= 0x80;
376 *ptemp = byte;
377 ptemp++;
378 len++;
380 saa_wbytes(psaa, temp, len);