From a7eb76606f0cda9d74478e545605358986e52d5a Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 5 Jun 2018 15:47:11 -0400 Subject: Implement bidirectional iterators in edi Also I'm calling them vecs now. No one can stop me. --- bin/edi.c | 185 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 97 insertions(+), 88 deletions(-) (limited to 'bin') diff --git a/bin/edi.c b/bin/edi.c index ecb19c30..f78b668e 100644 --- a/bin/edi.c +++ b/bin/edi.c @@ -24,11 +24,10 @@ #include #include #include -#include +#include static struct Span { - size_t at; - size_t to; + size_t at, to; } Span(size_t at, size_t to) { return (struct Span) { at, to }; } @@ -46,27 +45,27 @@ static bool spanTailIn(struct Span a, struct Span b) { return a.to > b.at && a.to < b.to; } -static struct Seg { +static struct Vec { char *ptr; size_t len; -} Seg(char *ptr, size_t len) { - return (struct Seg) { ptr, len }; +} Vec(char *ptr, size_t len) { + return (struct Vec) { ptr, len }; } -static struct Seg segHead(struct Seg seg, size_t at) { - return Seg(seg.ptr, at); +static struct Vec vecHead(struct Vec vec, size_t at) { + return Vec(vec.ptr, at); } -static struct Seg segTail(struct Seg seg, size_t at) { - return Seg(seg.ptr + at, seg.len - at); +static struct Vec vecTail(struct Vec vec, size_t at) { + return Vec(vec.ptr + at, vec.len - at); } static struct Table { - struct Table *next; - struct Table *prev; + struct Table *next, *prev; + struct Span span; size_t len; - struct Seg seg[]; + struct Vec vec[]; } *Table(size_t cap) { - size_t size = sizeof(struct Table) + cap * sizeof(struct Seg); + size_t size = sizeof(struct Table) + cap * sizeof(struct Vec); struct Table *table = malloc(size); if (!table) err(EX_OSERR, "malloc"); memset(table, 0, size); @@ -74,51 +73,51 @@ static struct Table { } static struct TableIter { - size_t len; - struct Seg *seg; + size_t next, prev; + struct Vec *vec; struct Span span; } TableIter(struct Table *table) { - if (table->len) { - return (struct TableIter) { - table->len, - &table->seg[0], - Span(0, table->seg[0].len), - }; - } else { - return (struct TableIter) { 0, NULL, Span(0, 0) }; - } + if (!table->len) return (struct TableIter) { 0, 0, NULL, Span(0, 0) }; + return (struct TableIter) { + table->len, 0, + &table->vec[0], + Span(0, table->vec[0].len), + }; } - static void tableNext(struct TableIter *it) { - it->len--; - it->seg++; - it->span = Span(it->span.to, it->span.to + it->seg->len); + it->next--; + it->prev++; + if (it->next) { + it->vec++; + it->span = Span(it->span.to, it->span.to + it->vec->len); + } } - -static struct Seg *tableAt(struct Table *table, size_t at) { - for (struct TableIter it = TableIter(table); it.len; tableNext(&it)) { - if (it.span.at == at) return it.seg; +static void tablePrev(struct TableIter *it) { + it->next++; + it->prev--; + if (it->prev) { + it->vec--; + it->span = Span(it->span.at - it->vec->len, it->span.at); } - return NULL; } -static struct Table *tableInsert(struct Table *prev, size_t at, struct Seg seg) { +static struct Table *tableInsert(struct Table *prev, size_t at, struct Vec vec) { struct Table *next = Table(prev->len + 2); if (!prev->len) { - next->seg[next->len++] = seg; + next->vec[next->len++] = vec; return next; } - struct Span span = Span(at, at + seg.len); - for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) { + struct Span span = Span(at, at + vec.len); + for (struct TableIter it = TableIter(prev); it.next; tableNext(&it)) { if (it.span.at == at) { - next->seg[next->len++] = seg; - next->seg[next->len++] = *it.seg; + next->vec[next->len++] = vec; + next->vec[next->len++] = *it.vec; } else if (spanHeadIn(span, it.span)) { - next->seg[next->len++] = segHead(*it.seg, at - it.span.at); - next->seg[next->len++] = seg; - next->seg[next->len++] = segTail(*it.seg, at - it.span.at); + next->vec[next->len++] = vecHead(*it.vec, at - it.span.at); + next->vec[next->len++] = vec; + next->vec[next->len++] = vecTail(*it.vec, at - it.span.at); } else { - next->seg[next->len++] = *it.seg; + next->vec[next->len++] = *it.vec; } } return next; @@ -126,51 +125,58 @@ static struct Table *tableInsert(struct Table *prev, size_t at, struct Seg seg) static struct Table *tableDelete(struct Table *prev, struct Span span) { struct Table *next = Table(prev->len + 1); - for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) { + for (struct TableIter it = TableIter(prev); it.next; tableNext(&it)) { if (spanIn(it.span, span) || spanEqual(it.span, span)) { // drop } else if (spanIn(span, it.span)) { - next->seg[next->len++] = segHead(*it.seg, span.at - it.span.at); - next->seg[next->len++] = segTail(*it.seg, span.to - it.span.at); + next->vec[next->len++] = vecHead(*it.vec, span.at - it.span.at); + next->vec[next->len++] = vecTail(*it.vec, span.to - it.span.at); } else if (spanHeadIn(span, it.span)) { - next->seg[next->len++] = segHead(*it.seg, span.at - it.span.at); + next->vec[next->len++] = vecHead(*it.vec, span.at - it.span.at); } else if (spanTailIn(span, it.span)) { - next->seg[next->len++] = segTail(*it.seg, span.to - it.span.at); + next->vec[next->len++] = vecTail(*it.vec, span.to - it.span.at); } else { - next->seg[next->len++] = *it.seg; + next->vec[next->len++] = *it.vec; } } return next; } -static struct CharIter { - struct TableIter in; - struct Seg seg; - size_t at; - wchar_t ch; +static struct VecIter { + size_t next, prev; + char *ptr; int len; -} CharIter(struct Table *table, size_t at) { - struct TableIter in; - for (in = TableIter(table); in.len; tableNext(&in)) { - if (at >= in.span.at && at < in.span.to) break; - } - struct CharIter it = { in, segTail(*in.seg, at - in.span.at), at, 0, 0 }; - it.len = mbtowc(&it.ch, it.seg.ptr, it.seg.len); - if (it.len < 0) err(EX_DATAERR, "mbtowc"); + wchar_t ch; +} VecIter(struct Vec vec, size_t at) { + struct VecIter it = { + vec.len - at, at, + vec.ptr + at, + 0, 0, + }; + it.len = mbtowc(&it.ch, it.ptr, it.next); + if (it.len < 0) errx(EX_DATAERR, "mbtowc"); return it; } - -static void charNext(struct CharIter *it) { - it->seg.ptr += it->len; - it->seg.len -= it->len; - it->at += it->len; - if (!it->seg.len && it->in.len) { - tableNext(&it->in); - it->seg = *it->in.seg; - it->at = it->in.span.at; +static void vecNext(struct VecIter *it) { + it->next -= it->len; + it->prev += it->len; + if (it->next) { + it->ptr += it->len; + it->len = mbtowc(&it->ch, it->ptr, it->next); + if (it->len < 0) errx(EX_DATAERR, "mbtowc"); + } +} +static void vecPrev(struct VecIter *it) { + it->next += it->len; + it->prev -= it->len; + if (it->prev) { + for (int n = 1; n < MB_CUR_MAX; ++n) { + it->len = mbtowc(&it->ch, it->ptr - n, n); + if (it->len > 0) break; + } + if (it->len < 0) errx(EX_DATAERR, "mbtowc"); + it->ptr -= it->len; } - it->len = mbtowc(&it->ch, it->seg.ptr, it->seg.len); - if (it->len < 0) err(EX_DATAERR, "mbtowc"); } static void curse(void) { @@ -189,28 +195,31 @@ static void curseChar(wchar_t ch, attr_t attr, short color) { add_wch(&cc); } -static void draw(struct Table *table, size_t at, struct Span cursor) { +static void draw(struct Table *table) { move(0, 0); - int y, x; - for (struct CharIter it = CharIter(table, at); it.seg.len; charNext(&it)) { - if (it.at == cursor.at) getyx(stdscr, y, x); - attr_t attr = A_NORMAL; - if (it.at >= cursor.at && it.at < cursor.to) attr = A_REVERSE; - curseChar(it.ch, attr, 0); + struct VecIter it; + for (it = VecIter(table->vec[0], 0); it.next; vecNext(&it)) { + curseChar(it.ch, A_NORMAL, 0); + } + for (; it.prev; vecPrev(&it)) { + curseChar(it.ch, A_NORMAL, 0); + } + for (; it.next; vecNext(&it)) { + curseChar(it.ch, A_NORMAL, 0); } - move(y, x); } int main() { struct Table *table = Table(0); - table = tableInsert(table, 0, Seg("Hello, world!\nGoodbye, world!\n", 30)); - table = tableDelete(table, Span(1, 5)); - table = tableInsert(table, 1, Seg("owdy", 4)); - table = tableDelete(table, Span(3, 6)); - table = tableInsert(table, 3, Seg(" do", 3)); + table = tableInsert(table, 0, Vec("«…»", 7)); + //table = tableInsert(table, 0, Vec("Hello, world!\nGoodbye, world!\n", 30)); + //table = tableDelete(table, Span(1, 5)); + //table = tableInsert(table, 1, Vec("owdy", 4)); + //table = tableDelete(table, Span(3, 6)); + //table = tableInsert(table, 3, Vec(" Ω", 3)); curse(); - draw(table, 0, Span(1, 3)); + draw(table); getch(); endwin(); } -- cgit 1.4.1