// 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 #include #include #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); } }