diff options
| -rw-r--r-- | txt.c | 64 |
1 files changed, 52 insertions, 12 deletions
@@ -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); +} |
