diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-12 20:57:06 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-12 20:59:39 +0200 |
| commit | e5af28536bfb0f4c9131df56d2009ba5196f5e3a (patch) | |
| tree | 3ab928f961a1ccd8440b070d7b57f79146457e8c /src/util | |
| download | animtool-e5af28536bfb0f4c9131df56d2009ba5196f5e3a.tar.xz | |
init
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/container.h | 64 | ||||
| -rw-r--r-- | src/util/err.h | 19 | ||||
| -rw-r--r-- | src/util/file.c | 39 | ||||
| -rw-r--r-- | src/util/file.h | 10 | ||||
| -rw-r--r-- | src/util/str.c | 93 | ||||
| -rw-r--r-- | src/util/str.h | 24 |
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 |
