From 50e13c722a62a2b7acf613b3992692d28d2ef0fd Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 14 Oct 2019 22:09:38 -0400 Subject: [PATCH] refactored more gapbuf functions --- inc/edit.h | 23 +++++++++---- src/lib/buf.c | 84 +++++++++++++++++++----------------------------- src/lib/gapbuf.c | 35 +++++++++++--------- src/tide.c | 11 +++---- tests/lib/buf.c | 37 +++++++++++++-------- 5 files changed, 98 insertions(+), 92 deletions(-) diff --git a/inc/edit.h b/inc/edit.h index bb75120..d351f3c 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -16,18 +16,21 @@ typedef struct { size_t col; } Sel; -/* gap buffer main data structure */ typedef struct { - enum { - NORMAL = 0, MODIFIED, OUTDATED, ERRORED - } status; - char* path; /* the path to the open file */ - uint64_t modtime; /* modification time of the opened file */ size_t bufsize; /* size of the buffer in runes */ char* bufstart; /* start of the data buffer */ char* bufend; /* end of the data buffer */ char* gapstart; /* start of the gap */ char* gapend; /* end of the gap */ +} GapBuf; + +/* gap buffer main data structure */ +typedef struct { + enum { + NORMAL = 0, MODIFIED, OUTDATED, ERRORED + } status; + char* path; /* the path to the open file */ + GapBuf contents; /* underlying sequence data structure */ Log* undo; /* undo list */ Log* redo; /* redo list */ Log* save; /* pointer to last save position */ @@ -35,6 +38,14 @@ typedef struct { Sel selection; /* the currently selected text */ } Buf; +void gapbuf_init(GapBuf* buf); +size_t gapbuf_end(GapBuf* buf); +long gapbuf_save(GapBuf* buf, char* path); +void gapbuf_load(GapBuf* buf, char* path); +char gapbuf_getb(GapBuf* buf, size_t off); +void gapbuf_putb(GapBuf* buf, char b, Sel* p_sel); +void gapbuf_del(GapBuf* buf, size_t off, size_t len); + void buf_init(Buf* buf); void buf_setpath(Buf* buf, char* path); void buf_load(Buf* buf, char* path); diff --git a/src/lib/buf.c b/src/lib/buf.c index 9abd8ba..5402c6b 100644 --- a/src/lib/buf.c +++ b/src/lib/buf.c @@ -8,28 +8,21 @@ #include #include "config.h" -extern void gapbuf_init(Buf* buf); -extern long gapbuf_save(Buf* buf, char* path); -extern void gapbuf_load(Buf* buf, char* path); -extern char gapbuf_getb(Buf* buf, size_t off); -extern void gapbuf_putb(Buf* buf, char b, Sel* p_sel); -extern void gapbuf_del(Buf* buf, size_t off, size_t len); - #ifndef NDEBUG static bool buf_valid(Buf* buf) { return ( - (buf->bufsize > 0) - && (buf->bufstart != NULL) - && (buf->bufend != NULL) - && (buf->gapstart != NULL) - && (buf->gapend != NULL) - && (buf->bufstart < buf->bufend) - && (buf->gapstart <= buf->gapend) - && (buf->gapstart >= buf->bufstart) - && (buf->gapend >= buf->bufstart) - && (buf->gapstart <= buf->bufend) - && (buf->gapend <= buf->bufend) + (buf->contents.bufsize > 0) + && (buf->contents.bufstart != NULL) + && (buf->contents.bufend != NULL) + && (buf->contents.gapstart != NULL) + && (buf->contents.gapend != NULL) + && (buf->contents.bufstart < buf->contents.bufend) + && (buf->contents.gapstart <= buf->contents.gapend) + && (buf->contents.gapstart >= buf->contents.bufstart) + && (buf->contents.gapend >= buf->contents.bufstart) + && (buf->contents.gapstart <= buf->contents.bufend) + && (buf->contents.gapend <= buf->contents.bufend) ); } #endif @@ -54,13 +47,14 @@ static void putch(Buf* buf, char b, Sel* p_sel) { if (b == '\n' && DosLineFeed) { - gapbuf_putb(buf, '\r', p_sel); - gapbuf_putb(buf, '\n', p_sel); + gapbuf_putb(&buf->contents, '\r', p_sel); + gapbuf_putb(&buf->contents, '\n', p_sel); } else { - gapbuf_putb(buf, b, p_sel); + gapbuf_putb(&buf->contents, b, p_sel); } + buf->status = MODIFIED; } } @@ -68,18 +62,8 @@ void buf_init(Buf* buf) { require(buf != NULL); - /* cleanup old data if there is any */ - if (buf->bufstart) - { - free(buf->bufstart); - buf->bufstart = NULL; - free(buf->path); - buf->path = NULL; - buf_logclear(buf); - } - /* reset the state to defaults */ - gapbuf_init(buf); + gapbuf_init(&buf->contents); buf->status = NORMAL; buf->undo = NULL; buf->redo = NULL; @@ -111,14 +95,14 @@ void buf_load(Buf* buf, char* path) path += 2; } buf->path = strdup(path); - gapbuf_load(buf, buf->path); + gapbuf_load(&buf->contents, buf->path); /* reset buffer state */ buf->status = NORMAL; buf_logclear(buf); /* use the EOL style of the first line to determine EOL style */ - DosLineFeed = (gapbuf_getb(buf, buf_eol(buf, 0)) == '\r'); + DosLineFeed = (gapbuf_getb(&buf->contents, buf_eol(buf, 0)) == '\r'); } ensure(buf_valid(buf)); } @@ -149,7 +133,7 @@ static void trim_whitespace(Buf* buf) buf_logstart(buf); while (prev != buf->selection.end) { - int r = gapbuf_getb(buf, buf->selection.end); + int r = gapbuf_getb(&buf->contents, buf->selection.end); /* If we reached a newline, then delete whatever we have selected */ if (r == '\r' || r == '\n') { @@ -189,7 +173,7 @@ int buf_save(Buf* buf, char* path) trim_whitespace(buf); } - long nwrite = gapbuf_save(buf, buf->path); + long nwrite = gapbuf_save(&buf->contents, buf->path); buf->status = (nwrite >= 0 ? NORMAL : ERRORED); if (buf->status == NORMAL) @@ -296,7 +280,8 @@ static void log_swap(Buf* buf, Log** src, Log** dest) /* reinsert deleted bytes */ for (char* s = item->data; s && *s; s++, item->end++) { - gapbuf_putb(buf, *s, &(buf->selection)); + gapbuf_putb(&buf->contents, *s, &(buf->selection)); + buf->status = MODIFIED; } free(item->data); item->data = NULL; @@ -308,7 +293,7 @@ static void log_swap(Buf* buf, Log** src, Log** dest) /* delete the added bytes */ Sel sel = selget(buf); item->data = buf_gets(buf); - gapbuf_del(buf, sel.beg, (item->end - item->beg)); + gapbuf_del(&buf->contents, sel.beg, (item->end - item->beg)); sel.end = sel.beg; buf->selection = sel; item->beg = sel.beg; @@ -415,10 +400,7 @@ void buf_lastins(Buf* buf) ******************************************************************************/ size_t buf_end(Buf* buf) { - require(buf != NULL); - size_t bufsz = buf->bufend - buf->bufstart; - size_t gapsz = buf->gapend - buf->gapstart; - return (bufsz - gapsz); + return gapbuf_end(&buf->contents); } int buf_getrat(Buf* buf, size_t off) @@ -426,13 +408,13 @@ int buf_getrat(Buf* buf, size_t off) require(buf != NULL); size_t rlen = 0; Rune rune = 0; - if (gapbuf_getb(buf, off) == '\r' && gapbuf_getb(buf, off+1) == '\n') + if (gapbuf_getb(&buf->contents, off) == '\r' && gapbuf_getb(&buf->contents, off+1) == '\n') { rune = '\n'; } else { - while ( !utf8decode(&rune, &rlen, gapbuf_getb(buf, off++)) ) + while ( !utf8decode(&rune, &rlen, gapbuf_getb(&buf->contents, off++)) ) { } } @@ -478,7 +460,7 @@ char* buf_gets(Buf* buf) char* str = malloc(nbytes+1); for (size_t i = 0; i < nbytes; i++) { - str[i] = gapbuf_getb(buf, sel.beg + i); + str[i] = gapbuf_getb(&buf->contents, sel.beg + i); } str[nbytes] = '\0'; return str; @@ -503,7 +485,7 @@ void buf_del(Buf* buf) { buf->status = MODIFIED; char* str = buf_gets(buf); - gapbuf_del(buf, sel.beg, nbytes); + gapbuf_del(&buf->contents, sel.beg, nbytes); sel.end = sel.beg = (sel.beg < sel.end ? sel.beg : sel.end); buf->selection = sel; log_add(buf, sel.beg, sel.end, str); @@ -603,7 +585,7 @@ static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str) int ret = 0; for (; *str && mbeg < mend; str++, mbeg++) { - int cmp = *str - gapbuf_getb(buf, mbeg); + int cmp = *str - gapbuf_getb(&buf->contents, mbeg); if (cmp != 0) { ret = cmp; @@ -752,7 +734,7 @@ size_t buf_byrune(Buf* buf, size_t pos, int count) { if (pos > 0 && move < 0) { - if (gapbuf_getb(buf, pos-2) == '\r' && gapbuf_getb(buf, pos-1) == '\n') + if (gapbuf_getb(&buf->contents, pos-2) == '\r' && gapbuf_getb(&buf->contents, pos-1) == '\n') { pos -= 2; } @@ -763,7 +745,7 @@ size_t buf_byrune(Buf* buf, size_t pos, int count) } else if (pos < buf_end(buf) && move > 0) { - if (gapbuf_getb(buf, pos) == '\r' && gapbuf_getb(buf, pos+1) == '\n') + if (gapbuf_getb(&buf->contents, pos) == '\r' && gapbuf_getb(&buf->contents, pos+1) == '\n') { pos += 2; } @@ -843,8 +825,8 @@ bool buf_findstr(Buf* buf, int dir, char* str) size_t nleft = buf_end(buf); for (; (mbeg != start) && nleft; nleft--) { - if ((gapbuf_getb(buf, mbeg) == str[0]) && - (gapbuf_getb(buf, mend-1) == str[len-1]) && + if ((gapbuf_getb(&buf->contents, mbeg) == str[0]) && + (gapbuf_getb(&buf->contents, mend-1) == str[len-1]) && (0 == bytes_match(buf, mbeg, mend, str))) { buf->selection.beg = mbeg, buf->selection.end = mend; diff --git a/src/lib/gapbuf.c b/src/lib/gapbuf.c index 50cbef8..03c93af 100644 --- a/src/lib/gapbuf.c +++ b/src/lib/gapbuf.c @@ -8,6 +8,14 @@ #include #include "config.h" +size_t gapbuf_end(GapBuf* buf) +{ + require(buf != NULL); + size_t bufsz = buf->bufend - buf->bufstart; + size_t gapsz = buf->gapend - buf->gapstart; + return (bufsz - gapsz); +} + static size_t pagealign(size_t sz) { size_t pgsize = sysconf(_SC_PAGE_SIZE); @@ -19,10 +27,10 @@ static size_t pagealign(size_t sz) return sz; } -static void resize(Buf* buf, size_t sz) +static void resize(GapBuf* buf, size_t sz) { /* allocate the new buffer and gap */ - Buf copy = *buf; + GapBuf copy = *buf; copy.bufsize = sz; copy.bufstart = (char*)malloc(copy.bufsize); copy.bufend = copy.bufstart + copy.bufsize; @@ -41,12 +49,12 @@ static void resize(Buf* buf, size_t sz) /* free the buffer and commit the changes */ free(buf->bufstart); - memcpy(buf, ©, sizeof(Buf)); + memcpy(buf, ©, sizeof(GapBuf)); } -static void syncgap(Buf* buf, size_t off) +static void syncgap(GapBuf* buf, size_t off) { - assert(off <= buf_end(buf)); + assert(off <= gapbuf_end(buf)); /* If the buffer is full, resize it before syncing */ if (0 == (buf->gapend - buf->gapstart)) { @@ -71,7 +79,7 @@ static void syncgap(Buf* buf, size_t off) } } -void gapbuf_init(Buf* buf) +void gapbuf_init(GapBuf* buf) { buf->bufsize = 8192; buf->bufstart = malloc(buf->bufsize); @@ -80,7 +88,7 @@ void gapbuf_init(Buf* buf) buf->gapend = buf->bufend; } -long gapbuf_save(Buf* buf, char* path) +long gapbuf_save(GapBuf* buf, char* path) { char* wptr; long fd, nwrite = 0, towrite = 0; @@ -95,8 +103,6 @@ long gapbuf_save(Buf* buf, char* path) while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0)) wptr += nwrite, towrite -= nwrite; close(fd); - /* report success or failure */ - buf->status = (nwrite >= 0 ? NORMAL : ERRORED); } else { @@ -105,7 +111,7 @@ long gapbuf_save(Buf* buf, char* path) return nwrite; } -void gapbuf_load(Buf* buf, char* path) +void gapbuf_load(GapBuf* buf, char* path) { /* load the contents from the file */ int fd, nread; @@ -129,10 +135,10 @@ void gapbuf_load(Buf* buf, char* path) } } -char gapbuf_getb(Buf* buf, size_t off) +char gapbuf_getb(GapBuf* buf, size_t off) { int c = '\n'; // TODO: get rid of this hack - if (off < buf_end(buf)) + if (off < gapbuf_end(buf)) { size_t bsz = (buf->gapstart - buf->bufstart); if (off < bsz) @@ -147,16 +153,15 @@ char gapbuf_getb(Buf* buf, size_t off) return c; } -void gapbuf_putb(Buf* buf, char b, Sel* p_sel) +void gapbuf_putb(GapBuf* buf, char b, Sel* p_sel) { syncgap(buf, p_sel->end); *(buf->gapstart++) = b; p_sel->end = p_sel->end + 1u; p_sel->beg = p_sel->end; - buf->status = MODIFIED; } -void gapbuf_del(Buf* buf, size_t off, size_t len) +void gapbuf_del(GapBuf* buf, size_t off, size_t len) { syncgap(buf, off); buf->gapend += len; diff --git a/src/tide.c b/src/tide.c index 5ecb416..b4b05e6 100644 --- a/src/tide.c +++ b/src/tide.c @@ -60,12 +60,11 @@ static void dumpdata(FILE* f) fprintf(f, "\t.rows:\t\t%p\n", (void*)Regions[i].rows); fprintf(f, "\t.buffer:\n"); fprintf(f, "\t\t.status:\t%d\n", Regions[i].buffer.status); - fprintf(f, "\t\t.modtime:\t%lu\n", (unsigned long)Regions[i].buffer.modtime); - fprintf(f, "\t\t.bufsize:\t%zu\n", Regions[i].buffer.bufsize); - fprintf(f, "\t\t.bufstart:\t%p\n", (void*)Regions[i].buffer.bufstart); - fprintf(f, "\t\t.bufend:\t%p\n", (void*)Regions[i].buffer.bufend); - fprintf(f, "\t\t.gapstart:\t%p\n", (void*)Regions[i].buffer.gapstart); - fprintf(f, "\t\t.gapend:\t%p\n", (void*)Regions[i].buffer.gapend); + fprintf(f, "\t\t.bufsize:\t%zu\n", Regions[i].buffer.contents.bufsize); + fprintf(f, "\t\t.bufstart:\t%p\n", (void*)Regions[i].buffer.contents.bufstart); + fprintf(f, "\t\t.bufend:\t%p\n", (void*)Regions[i].buffer.contents.bufend); + fprintf(f, "\t\t.gapstart:\t%p\n", (void*)Regions[i].buffer.contents.gapstart); + fprintf(f, "\t\t.gapend:\t%p\n", (void*)Regions[i].buffer.contents.gapend); fprintf(f, "\t\t.undo:\t\t%p\n", (void*)Regions[i].buffer.undo); fprintf(f, "\t\t.redo:\t\t%p\n", (void*)Regions[i].buffer.redo); fprintf(f, "\t\t.save:\t\t%p\n", (void*)Regions[i].buffer.save); diff --git a/tests/lib/buf.c b/tests/lib/buf.c index b33af63..6312141 100644 --- a/tests/lib/buf.c +++ b/tests/lib/buf.c @@ -13,6 +13,15 @@ static Buf TestBuf = {0}; static void set_buffer_text(char* str) { + /* cleanup old data if there is any */ + if (TestBuf.contents.bufstart) + { + free(TestBuf.contents.bufstart); + TestBuf.contents.bufstart = NULL; + free(TestBuf.path); + TestBuf.path = NULL; + buf_logclear(&TestBuf); + } buf_init(&TestBuf); buf_puts(&TestBuf, str); } @@ -128,11 +137,11 @@ TEST_SUITE(BufferTests) { buf_init(&TestBuf); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 8192); - CHECK(TestBuf.bufstart != NULL); - CHECK(TestBuf.bufend == TestBuf.bufstart + TestBuf.bufsize); - CHECK(TestBuf.gapstart == TestBuf.bufstart); - CHECK(TestBuf.gapend == TestBuf.bufend); + CHECK(TestBuf.contents.bufsize == 8192); + CHECK(TestBuf.contents.bufstart != NULL); + CHECK(TestBuf.contents.bufend == TestBuf.contents.bufstart + TestBuf.contents.bufsize); + CHECK(TestBuf.contents.gapstart == TestBuf.contents.bufstart); + CHECK(TestBuf.contents.gapend == TestBuf.contents.bufend); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); } @@ -143,11 +152,11 @@ TEST_SUITE(BufferTests) buf_putc(&TestBuf, 'a'); buf_init(&TestBuf); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 8192); - CHECK(TestBuf.bufstart != NULL); - CHECK(TestBuf.bufend == TestBuf.bufstart + TestBuf.bufsize); - CHECK(TestBuf.gapstart == TestBuf.bufstart); - CHECK(TestBuf.gapend == TestBuf.bufend); + CHECK(TestBuf.contents.bufsize == 8192); + CHECK(TestBuf.contents.bufstart != NULL); + CHECK(TestBuf.contents.bufend == TestBuf.contents.bufstart + TestBuf.contents.bufsize); + CHECK(TestBuf.contents.gapstart == TestBuf.contents.bufstart); + CHECK(TestBuf.contents.gapend == TestBuf.contents.bufend); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); } @@ -177,7 +186,7 @@ TEST_SUITE(BufferTests) buf_init(&TestBuf); buf_load(&TestBuf, "testdocs/lorem.txt"); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 61440); + CHECK(TestBuf.contents.bufsize == 61440); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); @@ -188,7 +197,7 @@ TEST_SUITE(BufferTests) buf_init(&TestBuf); buf_load(&TestBuf, "testdocs/waf"); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 98304); + CHECK(TestBuf.contents.bufsize == 98304); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); CHECK(!strcmp(TestBuf.path, "testdocs/waf")); @@ -199,7 +208,7 @@ TEST_SUITE(BufferTests) buf_init(&TestBuf); buf_load(&TestBuf, "./testdocs/lorem.txt"); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 61440); + CHECK(TestBuf.contents.bufsize == 61440); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); @@ -213,7 +222,7 @@ TEST_SUITE(BufferTests) TestBuf.path = "testdocs/lorem.txt"; buf_reload(&TestBuf); CHECK(TestBuf.status != MODIFIED); - CHECK(TestBuf.bufsize == 61440); + CHECK(TestBuf.contents.bufsize == 61440); CHECK(TestBuf.undo == NULL); CHECK(TestBuf.redo == NULL); CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); -- 2.51.0