98 lines
2.4 KiB
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;
|
|
}
|