joeylib2/tools/common/toolBuf.c

102 lines
2.3 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// toolBuf.c - a growing byte buffer for the JoeyLib host tools (toolBuf.h).
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "toolBuf.h"
#include "toolFile.h"
#define BUF_FIRST_CAP 256u
#define BYTE_BITS 8u
#define BYTE_MASK 0xFFu
static uint8_t *bufGrow(ToolBufT *buf, size_t len);
static void bufNumber(ToolBufT *buf, uint32_t value, uint32_t bytes, bool bigEndian);
// Room for len more bytes at the end, counted in: where they go.
static uint8_t *bufGrow(ToolBufT *buf, size_t len) {
uint8_t *data;
size_t cap;
if (buf->len + len > buf->cap) {
cap = buf->cap == 0u ? BUF_FIRST_CAP : buf->cap;
while (cap < buf->len + len) {
cap *= 2u;
}
data = (uint8_t *)realloc(buf->data, cap);
if (data == NULL) {
toolFail("out of memory");
}
buf->data = data;
buf->cap = cap;
}
data = buf->data + buf->len;
buf->len += len;
return data;
}
static void bufNumber(ToolBufT *buf, uint32_t value, uint32_t bytes, bool bigEndian) {
uint8_t *out;
uint32_t i;
uint32_t shift;
out = bufGrow(buf, bytes);
for (i = 0; i < bytes; i++) {
shift = (bigEndian ? bytes - 1u - i : i) * BYTE_BITS;
out[i] = (uint8_t)((value >> shift) & BYTE_MASK);
}
}
void toolBufAdd(ToolBufT *buf, const void *data, size_t len) {
if (len > 0u) {
memcpy(bufGrow(buf, len), data, len);
}
}
void toolBufBe16(ToolBufT *buf, uint32_t value) {
bufNumber(buf, value, 2u, true);
}
void toolBufBe32(ToolBufT *buf, uint32_t value) {
bufNumber(buf, value, 4u, true);
}
void toolBufByte(ToolBufT *buf, uint32_t value) {
*bufGrow(buf, 1u) = (uint8_t)value;
}
void toolBufFree(ToolBufT *buf) {
free(buf->data);
buf->data = NULL;
buf->len = 0u;
buf->cap = 0u;
}
void toolBufLe16(ToolBufT *buf, uint32_t value) {
bufNumber(buf, value, 2u, false);
}
void toolBufLe32(ToolBufT *buf, uint32_t value) {
bufNumber(buf, value, 4u, false);
}
void toolBufZeros(ToolBufT *buf, size_t count) {
if (count > 0u) {
memset(bufGrow(buf, count), 0, count);
}
}