This commit is contained in:
snarmph 2024-11-29 16:10:48 +01:00
parent 82aee127b0
commit a92b119549
99 changed files with 6922 additions and 5723 deletions

408
str.c Normal file
View file

@ -0,0 +1,408 @@
#include "str.h"
#include "warnings/colla_warn_beg.h"
#include "arena.h"
#include "format.h"
#include "tracelog.h"
#if COLLA_WIN
#include <windows.h>
#else
#include <wchar.h>
#endif
#if COLLA_TCC
#include "tcc/colla_tcc.h"
#endif
// == STR_T ========================================================
str_t strInit(arena_t *arena, const char *buf) {
return buf ? strInitLen(arena, buf, strlen(buf)) : STR_EMPTY;
}
str_t strInitLen(arena_t *arena, const char *buf, usize len) {
if (!buf || !len) return STR_EMPTY;
str_t out = {
.buf = alloc(arena, char, len + 1),
.len = len
};
memcpy(out.buf, buf, len);
return out;
}
str_t strInitView(arena_t *arena, strview_t view) {
return strInitLen(arena, view.buf, view.len);
}
str_t strFmt(arena_t *arena, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
str_t out = strFmtv(arena, fmt, args);
va_end(args);
return out;
}
str_t strFmtv(arena_t *arena, const char *fmt, va_list args) {
va_list vcopy;
va_copy(vcopy, args);
// stb_vsnprintf returns the length + null_term
int len = fmtBufferv(NULL, 0, fmt, vcopy);
va_end(vcopy);
char *buffer = alloc(arena, char, len + 1);
fmtBufferv(buffer, len + 1, fmt, args);
return (str_t) { .buf = buffer, .len = (usize)len };
}
str_t strFromWChar(arena_t *arena, const wchar_t *src) {
return strFromWCharLen(arena, src, 0);
}
str_t strFromWCharLen(arena_t *arena, const wchar_t *src, usize srclen) {
if (!src) return STR_EMPTY;
if (!srclen) srclen = wcslen(src);
str_t out = {0};
#if COLLA_WIN
int outlen = WideCharToMultiByte(
CP_UTF8, 0,
src, (int)srclen,
NULL, 0,
NULL, NULL
);
if (outlen == 0) {
unsigned long error = GetLastError();
if (error == ERROR_NO_UNICODE_TRANSLATION) {
err("couldn't translate wide string (%S) to utf8, no unicode translation", src);
}
else {
err("couldn't translate wide string (%S) to utf8, %u", error);
}
return STR_EMPTY;
}
out.buf = alloc(arena, char, outlen + 1);
WideCharToMultiByte(
CP_UTF8, 0,
src, (int)srclen,
out.buf, outlen,
NULL, NULL
);
out.len = outlen;
#elif COLLA_LIN
fatal("strFromWChar not implemented yet!");
#endif
return out;
}
bool strEquals(str_t a, str_t b) {
return strCompare(a, b) == 0;
}
int strCompare(str_t a, str_t b) {
return a.len == b.len ?
memcmp(a.buf, b.buf, a.len) :
(int)(a.len - b.len);
}
str_t strDup(arena_t *arena, str_t src) {
return strInitLen(arena, src.buf, src.len);
}
bool strIsEmpty(str_t ctx) {
return ctx.len == 0 || ctx.buf == NULL;
}
void strReplace(str_t *ctx, char from, char to) {
if (!ctx) return;
char *buf = ctx->buf;
for (usize i = 0; i < ctx->len; ++i) {
buf[i] = buf[i] == from ? to : buf[i];
}
}
strview_t strSub(str_t ctx, usize from, usize to) {
if (to > ctx.len) to = ctx.len;
if (from > to) from = to;
return (strview_t){ ctx.buf + from, to - from };
}
void strLower(str_t *ctx) {
char *buf = ctx->buf;
for (usize i = 0; i < ctx->len; ++i) {
buf[i] = (buf[i] >= 'A' && buf[i] <= 'Z') ?
buf[i] += 'a' - 'A' :
buf[i];
}
}
void strUpper(str_t *ctx) {
char *buf = ctx->buf;
for (usize i = 0; i < ctx->len; ++i) {
buf[i] = (buf[i] >= 'a' && buf[i] <= 'z') ?
buf[i] -= 'a' - 'A' :
buf[i];
}
}
str_t strToLower(arena_t *arena, str_t ctx) {
strLower(&ctx);
return strDup(arena, ctx);
}
str_t strToUpper(arena_t *arena, str_t ctx) {
strUpper(&ctx);
return strDup(arena, ctx);
}
// == STRVIEW_T ====================================================
strview_t strvInit(const char *cstr) {
return (strview_t){
.buf = cstr,
.len = cstr ? strlen(cstr) : 0,
};
}
strview_t strvInitLen(const char *buf, usize size) {
return (strview_t){
.buf = buf,
.len = size,
};
}
strview_t strvInitStr(str_t str) {
return (strview_t){
.buf = str.buf,
.len = str.len
};
}
bool strvIsEmpty(strview_t ctx) {
return ctx.len == 0 || !ctx.buf;
}
bool strvEquals(strview_t a, strview_t b) {
return strvCompare(a, b) == 0;
}
int strvCompare(strview_t a, strview_t b) {
return a.len == b.len ?
memcmp(a.buf, b.buf, a.len) :
(int)(a.len - b.len);
}
char strvFront(strview_t ctx) {
return ctx.len > 0 ? ctx.buf[0] : '\0';
}
char strvBack(strview_t ctx) {
return ctx.len > 0 ? ctx.buf[ctx.len - 1] : '\0';
}
wchar_t *strvToWChar(arena_t *arena, strview_t ctx, usize *outlen) {
wchar_t *out = NULL;
int len = 0;
if (strvIsEmpty(ctx)) {
goto error;
}
#if COLLA_WIN
len = MultiByteToWideChar(
CP_UTF8, 0,
ctx.buf, (int)ctx.len,
NULL, 0
);
if (len == 0) {
unsigned long error = GetLastError();
if (error == ERROR_NO_UNICODE_TRANSLATION) {
err("couldn't translate string (%v) to a wide string, no unicode translation", ctx);
}
else {
err("couldn't translate string (%v) to a wide string, %u", ctx, error);
}
goto error;
}
out = alloc(arena, wchar_t, len + 1);
MultiByteToWideChar(
CP_UTF8, 0,
ctx.buf, (int)ctx.len,
out, len
);
#elif COLLA_LIN
fatal("strFromWChar not implemented yet!");
#endif
error:
if (outlen) {
*outlen = (usize)len;
}
return out;
}
TCHAR *strvToTChar(arena_t *arena, strview_t str) {
#if UNICODE
return strvToWChar(arena, str, NULL);
#else
char *cstr = alloc(arena, char, str.len + 1);
memcpy(cstr, str.buf, str.len);
return cstr;
#endif
}
strview_t strvRemovePrefix(strview_t ctx, usize n) {
if (n > ctx.len) n = ctx.len;
return (strview_t){
.buf = ctx.buf + n,
.len = ctx.len - n,
};
}
strview_t strvRemoveSuffix(strview_t ctx, usize n) {
if (n > ctx.len) n = ctx.len;
return (strview_t){
.buf = ctx.buf,
.len = ctx.len - n,
};
}
strview_t strvTrim(strview_t ctx) {
return strvTrimLeft(strvTrimRight(ctx));
}
strview_t strvTrimLeft(strview_t ctx) {
strview_t out = ctx;
for (usize i = 0; i < ctx.len; ++i) {
char c = ctx.buf[i];
if (c != ' ' && (c < '\t' || c > '\r')) {
break;
}
out.buf++;
out.len--;
}
return out;
}
strview_t strvTrimRight(strview_t ctx) {
strview_t out = ctx;
for (isize i = ctx.len - 1; i >= 0; --i) {
char c = ctx.buf[i];
if (c != ' ' && (c < '\t' || c > '\r')) {
break;
}
out.len--;
}
return out;
}
strview_t strvSub(strview_t ctx, usize from, usize to) {
if (to > ctx.len) to = ctx.len;
if (from > to) from = to;
return (strview_t){ ctx.buf + from, to - from };
}
bool strvStartsWith(strview_t ctx, char c) {
return ctx.len > 0 && ctx.buf[0] == c;
}
bool strvStartsWithView(strview_t ctx, strview_t view) {
return ctx.len >= view.len && memcmp(ctx.buf, view.buf, view.len) == 0;
}
bool strvEndsWith(strview_t ctx, char c) {
return ctx.len > 0 && ctx.buf[ctx.len - 1] == c;
}
bool strvEndsWithView(strview_t ctx, strview_t view) {
return ctx.len >= view.len && memcmp(ctx.buf + ctx.len - view.len, view.buf, view.len) == 0;
}
bool strvContains(strview_t ctx, char c) {
for(usize i = 0; i < ctx.len; ++i) {
if(ctx.buf[i] == c) {
return true;
}
}
return false;
}
bool strvContainsView(strview_t ctx, strview_t view) {
if (ctx.len < view.len) return false;
usize end = ctx.len - view.len;
for (usize i = 0; i < end; ++i) {
if (memcmp(ctx.buf + i, view.buf, view.len) == 0) {
return true;
}
}
return false;
}
usize strvFind(strview_t ctx, char c, usize from) {
for (usize i = from; i < ctx.len; ++i) {
if (ctx.buf[i] == c) {
return i;
}
}
return STR_NONE;
}
usize strvFindView(strview_t ctx, strview_t view, usize from) {
if (ctx.len < view.len) return STR_NONE;
usize end = ctx.len - view.len;
for (usize i = from; i < end; ++i) {
if (memcmp(ctx.buf + i, view.buf, view.len) == 0) {
return i;
}
}
return STR_NONE;
}
usize strvRFind(strview_t ctx, char c, usize from_right) {
if (from_right > ctx.len) from_right = ctx.len;
isize end = (isize)(ctx.len - from_right);
for (isize i = end; i >= 0; --i) {
if (ctx.buf[i] == c) {
return (usize)i;
}
}
return STR_NONE;
}
usize strvRFindView(strview_t ctx, strview_t view, usize from_right) {
if (from_right > ctx.len) from_right = ctx.len;
isize end = (isize)(ctx.len - from_right);
if (end < (isize)view.len) return STR_NONE;
for (isize i = end - view.len; i >= 0; --i) {
if (memcmp(ctx.buf + i, view.buf, view.len) == 0) {
return (usize)i;
}
}
return STR_NONE;
}
#include "warnings/colla_warn_beg.h"