aboutsummaryrefslogtreecommitdiff
path: root/src/str.c
diff options
context:
space:
mode:
authorElis Eriksson <spelis@spelis.li>2026-06-13 17:40:25 +0200
committerElis Eriksson <spelis@spelis.li>2026-06-13 17:40:25 +0200
commit7ccae1c362a45b28f4fbf96da4f479730e4b382b (patch)
treef59ba4d76221590901784464a03a6a871d774305 /src/str.c
downloadbfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar.gz
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar.bz2
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar.lz
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar.xz
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.tar.zst
bfc-7ccae1c362a45b28f4fbf96da4f479730e4b382b.zip
Initial Commit, probably needs heavy code cleanup
Diffstat (limited to 'src/str.c')
-rw-r--r--src/str.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/str.c b/src/str.c
new file mode 100644
index 0000000..ddca742
--- /dev/null
+++ b/src/str.c
@@ -0,0 +1,119 @@
+#include "str.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define STARTING_SIZE 256
+#define READ_CHUNK_SIZE 1024
+
+static void str_ensure_init(str *s) {
+ if (s->data)
+ return;
+
+ s->capacity = STARTING_SIZE;
+ s->length = 0;
+ s->data = malloc(s->capacity);
+ if (!s->data)
+ abort();
+
+ s->data[0] = '\0';
+}
+
+static void str_ensure_capacity(str *s, size_t extra) {
+ str_ensure_init(s);
+
+ size_t needed = s->length + extra + 1; // +1 for '\0'
+ if (needed <= s->capacity)
+ return;
+
+ while (s->capacity < needed)
+ s->capacity *= 2;
+
+ char *new_data = realloc(s->data, s->capacity);
+ if (!new_data)
+ abort();
+
+ s->data = new_data;
+}
+
+void free_str(str *s) {
+ free(s->data);
+ s->data = NULL;
+ s->length = 0;
+ s->capacity = 0;
+}
+
+void str_append(str *s, const char *from) {
+ str_append_len(s, from, strlen(from));
+}
+
+void str_append_c(str *s, char c) { str_append_len(s, &c, 1); }
+
+void str_append_len(str *s, const char *from, size_t len) {
+ str_ensure_capacity(s, len);
+
+ memcpy(s->data + s->length, from, len);
+ s->length += len;
+ s->data[s->length] = '\0';
+}
+
+void str_append_read(str *s, int fd) {
+ char buf[READ_CHUNK_SIZE];
+ ssize_t n;
+
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ str_append_len(s, buf, (size_t)n);
+ }
+}
+
+void str_append_fread(str *s, FILE *file) {
+ char buf[READ_CHUNK_SIZE];
+ size_t n;
+
+ while ((n = fread(buf, 1, sizeof(buf), file)) > 0) {
+ str_append_len(s, buf, n);
+ }
+}
+
+void str_append_fread_len(str *s, size_t size, FILE *file) {
+ char buf[READ_CHUNK_SIZE];
+
+ while (size > 0) {
+ size_t chunk = size > sizeof(buf) ? sizeof(buf) : size;
+ size_t n = fread(buf, 1, chunk, file);
+
+ if (n == 0)
+ break;
+
+ str_append_len(s, buf, n);
+ size -= n;
+
+ if (n < chunk)
+ break;
+ }
+}
+
+void str_appendf(str *s, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ va_list copy;
+ va_copy(copy, args);
+ int needed = vsnprintf(NULL, 0, fmt, copy);
+ va_end(copy);
+
+ if (needed < 0) {
+ va_end(args);
+ return;
+ }
+
+ str_ensure_capacity(s, (size_t)needed);
+
+ vsnprintf(s->data + s->length, s->capacity - s->length, fmt, args);
+ s->length += (size_t)needed;
+
+ va_end(args);
+}