+64
-36
bini.h
+64
-36
bini.h
···
1
-
#ifndef __bini__
2
-
#define __bini__
1
+
#ifndef __kf_bini__
2
+
#define __kf_bini__
3
3
4
4
/*
5
5
bini.h: endian-independent binary IO.
6
6
License: BSD 3-Clause. See EOF for license text.
7
7
8
-
Version: 1.0
8
+
Version: 1.1
9
9
10
10
Changelog:
11
11
1.0 (Dec 28, 2025): Initial version.
12
+
1.1 (Dec 30, 2025): Use an offset instead of shifting the
13
+
byte buffer so carelessly. _bini_grow will shift the
14
+
buffer on-demand instead so as to conserve CPU time.
12
15
*/
13
16
14
17
/* Used to add functions for version-specific types. */
···
100
103
{
101
104
/* Read mode for the stream. Should be either BINI_STACK or BINI_STREAM. */
102
105
int mode;
106
+
/* Offset from the start of the buffer in bytes. Only used for BINI_STREAM. */
107
+
size_t off;
103
108
size_t cap;
104
109
size_t len;
105
110
uint8_t *buffer;
···
125
130
buffer, and frees the provided variable as well. */
126
131
void bini_close(struct bini_stream *bs);
127
132
133
+
/* Shift a binary stream, resetting the offset and shifting the array. */
134
+
void bini_shift(struct bini_stream *);
128
135
/* Flush a binary stream, clearing its buffer. */
129
136
int bini_flush(struct bini_stream *);
130
137
/* Dump the binary stream's buffer to fp. */
···
255
262
bs->buffer = calloc(BINI_BUFSIZ, 1);
256
263
if (!bs->buffer)
257
264
return BINI_ERR;
265
+
bs->off = 0;
258
266
bs->len = 0;
259
267
bs->cap = BINI_BUFSIZ;
260
268
bs->mode = BINI_STREAM;
···
280
288
free(bs);
281
289
}
282
290
291
+
static
292
+
#if bini_c >= 1999
293
+
inline
294
+
#endif
295
+
void _bini_shiftleft(struct bini_stream *bs, size_t n)
296
+
{
297
+
size_t i;
298
+
_bini_dbg("shift %d: (len=%lu)\n", n, bs->len);
299
+
for (i = 0 ; i < bs->len ; i++)
300
+
{
301
+
if (i+n >= bs->len)
302
+
{
303
+
_bini_dbg(" %d: [%d] (out of bounds) to [%d]\n", n, i+n, i);
304
+
bs->buffer[i] = 0;
305
+
continue;
306
+
}
307
+
_bini_dbg(" %d: [%d] (%02x '%c') to [%d]\n",
308
+
n,
309
+
i+n,
310
+
bs->buffer[i+n],
311
+
bs->buffer[i+n],
312
+
i);
313
+
bs->buffer[i] = bs->buffer[i+n];
314
+
}
315
+
}
316
+
317
+
void bini_shift(struct bini_stream *bs)
318
+
{
319
+
_bini_shiftleft(bs, bs->off);
320
+
bs->off = 0;
321
+
}
322
+
283
323
int bini_flush(struct bini_stream *bs)
284
324
{
285
325
size_t i;
···
307
347
int _bini_grow(struct bini_stream *bs, size_t n)
308
348
{
309
349
uint8_t *newbuf;
350
+
351
+
if (bs->off + bs->len + n < bs->cap)
352
+
return BINI_OK;
353
+
354
+
/* Shifting the array could give enough space to
355
+
fit `n`, avoiding the need to realloc. */
356
+
bini_shift(bs);
357
+
310
358
if (bs->len + n < bs->cap)
311
359
return BINI_OK;
360
+
312
361
while (bs->len + n >= bs->cap)
313
362
{
314
363
newbuf = realloc(bs->buffer, bs->cap * 2);
···
317
366
bs->buffer = newbuf;
318
367
bs->cap *= 2;
319
368
}
369
+
320
370
return BINI_OK;
321
371
}
322
372
···
334
384
return fwrite(bs->buffer, size, n, fp);
335
385
}
336
386
337
-
static
338
-
#if bini_c >= 1999
339
-
inline
340
-
#endif
341
-
void _bini_shiftleft(struct bini_stream *bs, size_t n)
342
-
{
343
-
size_t i;
344
-
_bini_dbg("shift %d: (len=%lu)\n", n, bs->len);
345
-
for (i = 0 ; i < bs->len ; i++)
346
-
{
347
-
if (i+n >= bs->len)
348
-
{
349
-
_bini_dbg(" %d: [%d] (out of bounds) to [%d]\n", n, i+n, i);
350
-
bs->buffer[i] = 0;
351
-
continue;
352
-
}
353
-
_bini_dbg(" %d: [%d] (%02x '%c') to [%d]\n",
354
-
n,
355
-
i+n,
356
-
bs->buffer[i+n],
357
-
bs->buffer[i+n],
358
-
i);
359
-
bs->buffer[i] = bs->buffer[i+n];
360
-
}
361
-
}
362
-
363
387
#define _bini_rwx(_type, _name) \
364
388
void bini_w##_name(struct bini_stream *bs, _type v) \
365
389
{ \
···
376
400
l ? sizeof(v)-i-1 : i, \
377
401
bytes[l ? sizeof(v)-i-1 : i], \
378
402
bytes[l ? sizeof(v)-i-1 : i], \
379
-
bs->len+i); \
380
-
bs->buffer[bs->len+i] = bytes[l ? sizeof(v)-i-1 : i]; \
403
+
bs->off+bs->len+i); \
404
+
bs->buffer[bs->off+bs->len+i] = bytes[l ? sizeof(v)-i-1 : i]; \
381
405
} \
382
406
bs->len += i; \
383
407
_bini_dbg("-> %s: %d (%lu bytes)\n", __FUNCTION__, *(int *)bytes, sizeof(v)); \
···
391
415
int m = bs->mode == BINI_STREAM; \
392
416
for (i = 0 ; i < sizeof(v) ; i++) \
393
417
{ \
418
+
const size_t p = bs->off + (m ? i : (bs->len-sizeof(v)+i)); \
394
419
_bini_dbg("%s: byte index [%lu] from buffer index %lu (= %02x '%c')\n", \
395
420
__FUNCTION__, \
396
421
l ? sizeof(v)-i-1 : i, \
397
-
m ? i : (bs->len-sizeof(v)+i), \
398
-
bs->buffer[m ? i : (bs->len-sizeof(v)+i)], \
399
-
bs->buffer[m ? i : (bs->len-sizeof(v)+i)]); \
400
-
bytes[l ? sizeof(v)-i-1 : i] = bs->buffer[m ? i : (bs->len-sizeof(v)+i)]; \
422
+
p, \
423
+
bs->buffer[p], \
424
+
bs->buffer[p]); \
425
+
bytes[l ? sizeof(v)-i-1 : i] = bs->buffer[p]; \
401
426
} \
402
427
if (m) \
403
-
_bini_shiftleft(bs, i); \
428
+
{ \
429
+
bs->off += i; \
430
+
/* _bini_shiftleft(bs, i); */ \
431
+
} \
404
432
bs->len -= i; \
405
433
return v; \
406
434
}