summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2026-04-12 20:57:06 +0200
committerLizzy Fleckenstein <lizzy@vlhl.dev>2026-04-12 20:59:39 +0200
commite5af28536bfb0f4c9131df56d2009ba5196f5e3a (patch)
tree3ab928f961a1ccd8440b070d7b57f79146457e8c /src/util
downloadanimtool-e5af28536bfb0f4c9131df56d2009ba5196f5e3a.tar.xz
init
Diffstat (limited to 'src/util')
-rw-r--r--src/util/container.h64
-rw-r--r--src/util/err.h19
-rw-r--r--src/util/file.c39
-rw-r--r--src/util/file.h10
-rw-r--r--src/util/str.c93
-rw-r--r--src/util/str.h24
6 files changed, 249 insertions, 0 deletions
diff --git a/src/util/container.h b/src/util/container.h
new file mode 100644
index 0000000..8b89440
--- /dev/null
+++ b/src/util/container.h
@@ -0,0 +1,64 @@
+#ifndef ANIMTOOL_CONTAINER_H_
+#define ANIMTOOL_CONTAINER_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbit.h>
+#include <stddef.h>
+
+#define option(type) struct { bool present; type data; }
+#define array(type) struct { size_t len; type *ptr; }
+#define arraybuf(type) struct { size_t len, cap; type *ptr; }
+#define map(type) arraybuf(struct { str key; type val; })
+
+#define array_typeck(a, b) ((void) ((a).ptr == (b).ptr))
+
+#define array_eq(a, b) (array_typeck(a, b), \
+ ((a).len == (b).len && !memcmp((a).ptr, (b).ptr, (a).len * sizeof *(a).ptr)))
+
+#define array_alloc(arr, e_len) (arr)->ptr = malloc(((arr)->len = (e_len)) * sizeof *(arr)->ptr)
+
+#define array_dup(dst, src) do { \
+ array_typeck(*(dst), *(src)); \
+ array_alloc(dst, (src)->len); \
+ memcpy((dst)->ptr, (src)->ptr, (src)->len * sizeof(*(src)->ptr)); \
+ } while(0)
+
+#define arraybuf_grow(arr, by) do { \
+ if ((arr)->len + by > (arr)->cap) \
+ (arr)->ptr = realloc((arr)->ptr, ((arr)->cap = stdc_bit_ceil((arr)->len) + by) * sizeof(*(arr)->ptr)); \
+ else if (!(arr)->ptr) \
+ (arr)->ptr = malloc((arr)->cap * sizeof(*(arr)->ptr)); \
+ } while (0)
+
+#define arraybuf_insert(arr, val) do { \
+ arraybuf_grow(arr, 1); \
+ (arr)->ptr[(arr)->len++] = (val); \
+ } while (0)
+
+#define arraybuf_cast(arr) { .len = (arr).len, .ptr = (arr).ptr }
+#define array_assign(a, b) do { (a)->len = (b).len; (a)->ptr = (b).ptr; } while(0)
+
+#define map_find(arr, e_key, p_val) do { \
+ for (size_t i = 0; i < (arr)->len; i++) \
+ if (array_eq((arr)->ptr[i].key, e_key)) { \
+ *(p_val) = &(arr)->ptr[i].val; \
+ break; \
+ } \
+ } while (0)
+
+#define map_insert_end(arr, e_key, e_val) do { \
+ arraybuf_grow(arr, 1); \
+ (arr)->ptr[(arr)->len].key = (e_key); \
+ (arr)->ptr[(arr)->len].val = (e_val); \
+ (arr)->len++; \
+ } while (0)
+
+#define map_insert(arr, e_key, e_val, p_succ) do { \
+ typeof(&(arr)->ptr->val) _val = nullptr; \
+ map_find(arr, e_key, &_val); \
+ if ((*(p_succ) = !_val)) \
+ map_insert_end(arr, e_key, e_val); \
+ } while (0)
+
+#endif
diff --git a/src/util/err.h b/src/util/err.h
new file mode 100644
index 0000000..52b3608
--- /dev/null
+++ b/src/util/err.h
@@ -0,0 +1,19 @@
+#ifndef ANIMTOOL_ERR_H
+#define ANIMTOOL_ERR_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+__attribute__((noreturn))
+__attribute__((format (printf, 1, 2)))
+static inline void eprintf(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(EXIT_FAILURE);
+}
+
+#endif
diff --git a/src/util/file.c b/src/util/file.c
new file mode 100644
index 0000000..38eb9ba
--- /dev/null
+++ b/src/util/file.c
@@ -0,0 +1,39 @@
+#include <string.h>
+#include "file.h"
+
+FILE *file_open(str s_path, const char *mode)
+{
+ NULTERM(s_path, path)
+ return fopen(path, mode);
+}
+
+static bool file_size(FILE *file, size_t *size)
+{
+ if (fseek(file, 0, SEEK_END) == -1)
+ return false;
+ long end = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ if (end == -1)
+ return false;
+ *size = end;
+ return true;
+}
+
+str file_read(FILE *file)
+{
+ size_t size;
+ if (file_size(file, &size)) {
+ str s;
+ array_alloc(&s, size);
+ s.len = fread(s.ptr, 1, size, file);
+ return s;
+ } else {
+ strbuf buf = {};
+ size_t n_read;
+ do {
+ arraybuf_grow(&buf, BUFSIZ);
+ buf.len += (n_read = fread(buf.ptr+buf.len, 1, BUFSIZ, file));
+ } while (n_read == BUFSIZ);
+ return (str) arraybuf_cast(buf);
+ }
+}
diff --git a/src/util/file.h b/src/util/file.h
new file mode 100644
index 0000000..d921456
--- /dev/null
+++ b/src/util/file.h
@@ -0,0 +1,10 @@
+#ifndef ANIMTOOL_FILE_H_
+#define ANIMTOOL_FILE_H_
+
+#include <stdio.h>
+#include "util/str.h"
+
+FILE *file_open(str s_path, const char *mode);
+str file_read(FILE *file);
+
+#endif
diff --git a/src/util/str.c b/src/util/str.c
new file mode 100644
index 0000000..09bf822
--- /dev/null
+++ b/src/util/str.c
@@ -0,0 +1,93 @@
+#include "util/str.h"
+
+static bool match_char(char c, str tokens)
+{
+ for (size_t t = 0; t < tokens.len; t++)
+ if (c == tokens.ptr[t])
+ return true;
+
+ return false;
+}
+
+size_t str_find(str s, str tokens)
+{
+ for (size_t i = 0; i < s.len; i++)
+ if (match_char(s.ptr[i], tokens))
+ return i;
+
+ return s.len;
+}
+
+str str_walk(str *s, str sep)
+{
+ if (s->len == 0)
+ return (str) {};
+
+ size_t x = str_find(*s, sep);
+ size_t o = x + (x < s->len);
+
+ *s = str_advance(*s, o);
+
+ return (str) { x, s->ptr - o };
+}
+
+str str_eat(str s, str tokens)
+{
+ while (s.len > 0 && match_char(s.ptr[0], tokens))
+ s = str_advance(s, 1);
+ return s;
+}
+
+str str_advance(str s, size_t x)
+{
+ s.len -= x;
+ s.ptr += x;
+ return s;
+}
+
+bool str_start(str s, str start)
+{
+ if (s.len < start.len)
+ return false;
+ s.len = start.len;
+ return array_eq(s, start);
+}
+
+str str_intro(char *s)
+{
+ return (str) { strlen(s), s };
+}
+
+#include <stdio.h>
+
+#define PARSE_NUM(parse, ...) \
+ NULTERM(s, buf) \
+ char *end; \
+ auto v = parse(buf, &end); \
+ if (end != buf+s.len) \
+ return false; \
+ *x = v; \
+ return true;
+
+
+bool str_parse_int(str s, long *x)
+{
+#define strtol_(start, endp) strtol(start, endp, 0)
+ PARSE_NUM(strtol_)
+#undef strtol_
+}
+
+bool str_parse_double(str s, double *x)
+{
+ PARSE_NUM(strtod)
+}
+
+bool str_split(str s, str sep, str *a, str *b)
+{
+ size_t x = str_find(s, sep);
+ if (x == s.len)
+ return false;
+ *a = (str) { x, s.ptr };
+ *b = str_advance(s, x+1);
+ return true;
+}
diff --git a/src/util/str.h b/src/util/str.h
new file mode 100644
index 0000000..4a0de1a
--- /dev/null
+++ b/src/util/str.h
@@ -0,0 +1,24 @@
+#ifndef ANIMTOOL_STR_H_
+#define ANIMTOOL_STR_H_
+
+#include "container.h"
+
+typedef arraybuf(char) strbuf;
+typedef array(char) str;
+
+#define S(x) ((str) { sizeof (x) - 1, (x) })
+#define PSTR(x) (int) (x).len, (x).ptr
+
+#define NULTERM(S, BUF) char BUF[(S).len+1]; memcpy(BUF, (S).ptr, (S).len); BUF[(S).len] = '\0';
+
+size_t str_find(str s, str tokens);
+str str_walk(str *s, str sep);
+str str_eat(str s, str tokens);
+str str_advance(str s, size_t x);
+bool str_start(str s, str start);
+str str_intro(char *s);
+bool str_parse_int(str s, long *x);
+bool str_parse_double(str s, double *x);
+bool str_split(str s, str sep, str *a, str *b);
+
+#endif