summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/edi.c125
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);
 	}
 }