joeylib2/tests/gate/common/gateText.c

98 lines
2.4 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// gateText.c - message text for the gate tools (gateText.h).
#define _DEFAULT_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "gateText.h"
#include "toolFile.h"
void gateTextAdd(ToolBufT *buf, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
gateTextAddV(buf, fmt, args);
va_end(args);
}
void gateTextAddV(ToolBufT *buf, const char *fmt, va_list args) {
va_list again;
char *text;
int len;
va_copy(again, args);
len = vsnprintf(NULL, 0, fmt, args);
if (len < 0) {
toolFail("bad message format");
}
text = (char *)malloc((size_t)len + 1u);
if (text == NULL) {
toolFail("out of memory");
}
vsnprintf(text, (size_t)len + 1u, fmt, again);
va_end(again);
toolBufAdd(buf, text, (size_t)len);
free(text);
}
size_t gateTextFind(const uint8_t *hay, size_t hayLen, size_t from, const void *needle, size_t needleLen) {
const uint8_t *first;
const uint8_t *at;
const uint8_t *last;
if (from > hayLen || hayLen - from < needleLen) {
return GATE_TEXT_NOT_FOUND;
}
if (needleLen == 0u) {
return from;
}
first = (const uint8_t *)needle;
last = hay + hayLen - needleLen;
at = hay + from;
while (at <= last) {
at = (const uint8_t *)memchr(at, first[0], (size_t)(last - at) + 1u);
if (at == NULL) {
return GATE_TEXT_NOT_FOUND;
}
if (memcmp(at, needle, needleLen) == 0) {
return (size_t)(at - hay);
}
at++;
}
return GATE_TEXT_NOT_FOUND;
}
bool gateTextReadFile(const char *path, uint8_t **data, size_t *len, ToolBufT *problem) {
struct stat info;
// A directory opens, then reads as nonsense: say what it is.
if (stat(path, &info) == 0 && S_ISDIR(info.st_mode)) {
gateTextAdd(problem, "cannot read %s: %s", path, strerror(EISDIR));
return false;
}
errno = 0;
if (!toolReadFile(path, data, len)) {
gateTextAdd(problem, "cannot read %s: %s", path, strerror(errno != 0 ? errno : EIO));
return false;
}
return true;
}
const char *gateTextString(ToolBufT *buf) {
toolBufByte(buf, 0u);
buf->len--;
return (const char *)buf->data;
}