summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-12-28 01:15:15 -0500
committerWormHeamer2025-12-28 01:15:15 -0500
commit54e30f7e1a3269946bcffd0bb293c7f4f39eda7c (patch)
tree2cf4454b303d3c280cd25f9c4650a4403223bd77
parent17eddfde53dd988d7d3ac0748eaab4da52bd16d7 (diff)
txt_save()
-rw-r--r--txt.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/txt.c b/txt.c
index daa02e5..9f29f84 100644
--- a/txt.c
+++ b/txt.c
@@ -10,10 +10,16 @@
#include "dynarr.h"
#include "txt.h"
+void txt_replace_piece(Txt *b, u32 pi, TxtBufIdx buf, u32 ofs, u32 n) {
+ b->ptbl.v[pi] = (TxtPiece) { buf, ofs, n };
+}
+
void txt_insert_piece(Txt *b, u32 pi, TxtBufIdx buf, u32 ofs, u32 n) {
DA_FIT(&b->ptbl, b->ptbl.n + 1);
- MOVE(&b->ptbl.v[pi+1], &b->ptbl.v[pi], b->ptbl.n - pi);
- b->ptbl.v[pi] = (TxtPiece) { buf, ofs, n };
+ if (pi < b->ptbl.n) {
+ MOVE(&b->ptbl.v[pi+1], &b->ptbl.v[pi], b->ptbl.n - pi);
+ }
+ txt_replace_piece(b, pi, buf, ofs, n);
b->ptbl.n++;
}
@@ -43,13 +49,18 @@ TxtLoc txt_at(Txt *b, u32 cur) {
return (TxtLoc) { b->ptbl.n - 1, b->ptbl.v[b->ptbl.n - 1].n };
}
-void txt_buf_append(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
+static void txt_buf_fit(Txt *b, TxtBufIdx bi, u32 sz) {
TxtBuf *buf = &b->buf[bi];
- if (buf->n + n > buf->c) {
- buf->c = stdc_bit_ceil(buf->n + n);
+ if (sz > buf->c) {
+ buf->c = stdc_bit_ceil(sz);
buf->s = realloc(buf->s, buf->c);
if (!buf->s) FAIL_WITH_MSG("realloc failure");
}
+}
+
+static void txt_buf_append(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
+ TxtBuf *buf = &b->buf[bi];
+ txt_buf_fit(b, bi, buf->n + n);
memcpy(&buf->s[buf->n], s, n);
buf->n += n;
}
@@ -68,8 +79,11 @@ u32 txt_add_piece(Txt *b, TxtLoc l) {
}
} else {
insert:
- if (b->ptbl.v[l.p].n == 0) txt_remove_piece(b, l.p);
- txt_insert_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0);
+ if (l.p < b->ptbl.n && b->ptbl.v[l.p].n == 0) {
+ txt_replace_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0);
+ } else {
+ txt_insert_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0);
+ }
}
return l.p;
}
@@ -130,7 +144,7 @@ u32 txt_delete(Txt *b, u32 cur, u32 n) {
return cur;
}
-int txt_open(Txt *b, const char *path) {
+int txt_load(Txt *b, const char *path) {
struct stat sb;
int fd = open(path, O_RDONLY);
if (fd == -1) return -1;
@@ -138,17 +152,43 @@ int txt_open(Txt *b, const char *path) {
close(fd);
return -1;
}
+ if (!sb.st_size) {
+ txt_buf_fit(b, TXT_SRC, 8192);
+ goto done;
+ }
void *m = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (m == MAP_FAILED) {
close(fd);
return -1;
}
- memset(b, 0, sizeof(TxtBuf));
- b->buf[TXT_SRC].s = m;
+ txt_buf_fit(b, TXT_SRC, sb.st_size);
+ memcpy(b->buf[TXT_SRC].s, m, sb.st_size);
+ munmap(m, sb.st_size);
b->buf[TXT_SRC].n = sb.st_size;
- b->buf[TXT_SRC].c = sb.st_size;
- b->len = sb.st_size;
close(fd);
+done:
+ b->ptbl.n = 0;
+ b->buf[TXT_ADD].n = 0;
+ b->len = b->buf[TXT_SRC].n;
txt_insert_piece(b, 0, TXT_SRC, 0, b->len);
return 0;
}
+
+int txt_save(Txt *t, const char *path) {
+ FILE *f = fopen(path, "w");
+ if (!f) return -1;
+ for (u32 i = 0; i < t->ptbl.n; i++) {
+ TxtPiece *p = &t->ptbl.v[i];
+ TxtBuf *b = &t->buf[p->buf];
+ fwrite(b->s + p->ofs, 1, p->n, f);
+ }
+ fclose(f);
+ return ferror(f) ? -1 : 0;
+}
+
+void txt_free(Txt *t) {
+ for (u32 i = 0; i < COUNTOF(t->buf); i++) {
+ free(t->buf[i].s);
+ }
+ free(t->ptbl.v);
+}