diff options
-rw-r--r-- | bin/edi.c | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/bin/edi.c b/bin/edi.c index 39fb7fa3..326d4d1a 100644 --- a/bin/edi.c +++ b/bin/edi.c @@ -28,38 +28,39 @@ static struct Span { return (struct Span) { at, to }; } -static bool spanStartsIn(struct Span a, struct Span b) { - return a.at >= b.at && a.at < b.to; +static bool spanEqual(struct Span a, struct Span b) { + return a.at == b.at && a.to == b.to; } -static bool spanEndsIn(struct Span a, struct Span b) { - return a.to > b.at && a.to <= b.to; +static bool spanIn(struct Span a, struct Span b) { + return a.at > b.at && a.to < b.to; } -static bool spanContains(struct Span a, struct Span b) { - return a.at <= b.at && a.to >= b.to; +static bool spanHeadIn(struct Span a, struct Span b) { + return a.at > b.at && a.at < b.to; +} +static bool spanTailIn(struct Span a, struct Span b) { + return a.to > b.at && a.to < b.to; } static struct Seg { - struct Span span; - char *data; -} Seg(struct Span span, char *data) { - return (struct Seg) { span, data }; + char *ptr; + size_t len; +} Seg(char *ptr, size_t len) { + return (struct Seg) { ptr, len }; } -static struct Seg segBefore(struct Seg seg, size_t at) { - return Seg(Span(seg.span.at, at), seg.data); +static struct Seg segHead(struct Seg seg, size_t at) { + return Seg(seg.ptr, at); } -static struct Seg segAfter(struct Seg seg, size_t at) { - return Seg(Span(at, seg.span.to), seg.data + (at - seg.span.at)); +static struct Seg segTail(struct Seg seg, size_t at) { + return Seg(seg.ptr + at, seg.len - at); } -struct Table { +static struct Table { struct Table *next; struct Table *prev; size_t len; struct Seg seg[]; -}; - -static struct Table *tableNew(size_t cap) { +} *Table(size_t cap) { size_t size = sizeof(struct Table) + cap * sizeof(struct Seg); struct Table *table = malloc(size); if (!table) err(EX_OSERR, "malloc"); @@ -67,67 +68,85 @@ static struct Table *tableNew(size_t cap) { return table; } -static void tableAdd(struct Table *table, struct Seg seg) { - // FIXME: Make this clearer. - size_t len = seg.span.to - seg.span.at; +static struct TableIter { + size_t len; + struct Seg *seg; + struct Span span; +} TableIter(struct Table *table) { if (table->len) { - struct Seg last = table->seg[table->len - 1]; - seg.span = Span(last.span.to, last.span.to + len); + return (struct TableIter) { + table->len, + &table->seg[0], + Span(0, table->seg[0].len), + }; } else { - seg.span = Span(0, len); + return (struct TableIter) { 0, NULL, Span(0, 0) }; + } +} + +static void tableNext(struct TableIter *it) { + it->len--; + it->seg++; + it->span = Span(it->span.to, it->span.to + it->seg->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; } - table->seg[table->len++] = seg; + return NULL; } -static struct Table *tableInsert(struct Table *prev, struct Seg seg) { - struct Table *next = tableNew(prev->len + 2); +static struct Table *tableInsert(struct Table *prev, size_t at, struct Seg seg) { + struct Table *next = Table(prev->len + 2); if (!prev->len) { - tableAdd(next, seg); + next->seg[next->len++] = seg; return next; } - for (size_t i = 0; i < prev->len; ++i) { - if (seg.span.at == prev->seg[i].span.at) { - tableAdd(next, seg); - tableAdd(next, prev->seg[i]); - } else if (spanStartsIn(seg.span, prev->seg[i].span)) { - tableAdd(next, segBefore(prev->seg[i], seg.span.at)); - tableAdd(next, seg); - tableAdd(next, segAfter(prev->seg[i], seg.span.at)); + struct Span span = Span(at, at + seg.len); + for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) { + if (it.span.at == at) { + next->seg[next->len++] = seg; + next->seg[next->len++] = *it.seg; + } 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); } else { - tableAdd(next, prev->seg[i]); + next->seg[next->len++] = *it.seg; } } return next; } static struct Table *tableDelete(struct Table *prev, struct Span span) { - struct Table *next = tableNew(prev->len + 1); - for (size_t i = 0; i < prev->len; ++i) { - if (spanContains(span, prev->seg[i].span)) { + struct Table *next = Table(prev->len + 1); + for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) { + if (spanIn(it.span, span) || spanEqual(it.span, span)) { // drop - } else if (spanContains(prev->seg[i].span, span)) { - tableAdd(next, segBefore(prev->seg[i], span.at)); - tableAdd(next, segAfter(prev->seg[i], span.to)); - } else if (spanStartsIn(span, prev->seg[i].span)) { - tableAdd(next, segBefore(prev->seg[i], span.at)); - } else if (spanEndsIn(span, prev->seg[i].span)) { - tableAdd(next, segAfter(prev->seg[i], span.to)); + } 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); + } else if (spanHeadIn(span, it.span)) { + next->seg[next->len++] = segHead(*it.seg, span.at - it.span.at); + } else if (spanTailIn(span, it.span)) { + next->seg[next->len++] = segTail(*it.seg, span.to - it.span.at); } else { - tableAdd(next, prev->seg[i]); + next->seg[next->len++] = *it.seg; } } return next; } int main() { - struct Table *table = tableNew(0); - table = tableInsert(table, Seg(Span(0, 13), "Hello, world!")); + struct Table *table = Table(0); + table = tableInsert(table, 0, Seg("Hello, world!\n", 14)); table = tableDelete(table, Span(1, 5)); - table = tableInsert(table, Seg(Span(1, 5), "owdy")); + table = tableInsert(table, 1, Seg("owdy", 5)); table = tableDelete(table, Span(3, 6)); - table = tableInsert(table, Seg(Span(3, 6), " do")); + table = tableInsert(table, 3, Seg(" do", 3)); for (size_t i = 0; i < table->len; ++i) { - printf("%.*s", table->seg[i].span.to - table->seg[i].span.at, table->seg[i].data); + printf("%.*s", (int)table->seg[i].len, table->seg[i].ptr); } } |