102 lines
2.3 KiB
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);
|
|
}
|
|
}
|