summary refs log tree commit diff
path: root/bin/edi
diff options
context:
space:
mode:
Diffstat (limited to 'bin/edi')
-rw-r--r--bin/edi/edi.h3
-rw-r--r--bin/edi/table.c82
2 files changed, 63 insertions, 22 deletions
diff --git a/bin/edi/edi.h b/bin/edi/edi.h
index 3e43e40d..f37ad5ab 100644
--- a/bin/edi/edi.h
+++ b/bin/edi/edi.h
@@ -49,9 +49,10 @@ wchar_t *bufferDest(struct Buffer *buf, size_t len);
 
 struct Table {
 	size_t len;
+	size_t hot;
 	struct Slice *slices;
 };
-static const struct Table TableEmpty = { 0, NULL };
+static const struct Table TableEmpty = { 0, 0, NULL };
 
 struct Table tableInsert(struct Table prev, size_t at, struct Slice ins);
 struct Table tableDelete(struct Table prev, struct Span del);
diff --git a/bin/edi/table.c b/bin/edi/table.c
index c664a102..a5383d56 100644
--- a/bin/edi/table.c
+++ b/bin/edi/table.c
@@ -24,13 +24,13 @@
 static struct Table alloc(size_t cap) {
 	struct Slice *slices = malloc(sizeof(*slices) * cap);
 	if (!slices) err(EX_OSERR, "malloc");
-	return (struct Table) { 0, slices };
+	return (struct Table) { 0, 0, slices };
 }
 
 struct Table tableInsert(struct Table prev, size_t at, struct Slice ins) {
 	if (!prev.len) {
 		struct Table next = alloc(1);
-		next.slices[next.len++] = ins;
+		next.slices[next.hot = next.len++] = ins;
 		return next;
 	}
 
@@ -39,14 +39,14 @@ struct Table tableInsert(struct Table prev, size_t at, struct Slice ins) {
 	for (size_t i = 0; i < prev.len; ++i) {
 		span = spanNext(span, prev.slices[i].len);
 		if (span.at == at) {
-			next.slices[next.len++] = ins;
+			next.slices[next.hot = next.len++] = ins;
 			next.slices[next.len++] = prev.slices[i];
 		} else if (span.at < at && span.to > at) {
 			next.slices[next.len++] = (struct Slice) {
 				prev.slices[i].ptr,
 				at - span.at,
 			};
-			next.slices[next.len++] = ins;
+			next.slices[next.hot = next.len++] = ins;
 			next.slices[next.len++] = (struct Slice) {
 				&prev.slices[i].ptr[at - span.at],
 				prev.slices[i].len - (at - span.at),
@@ -56,7 +56,7 @@ struct Table tableInsert(struct Table prev, size_t at, struct Slice ins) {
 		}
 	}
 	if (span.to == at) {
-		next.slices[next.len++] = ins;
+		next.slices[next.hot = next.len++] = ins;
 	}
 	return next;
 }
@@ -69,12 +69,13 @@ struct Table tableDelete(struct Table prev, struct Span del) {
 		span = spanNext(span, prev.slices[i].len);
 		if (span.at >= del.at && span.to <= del.to) {
 			(void)prev.slices[i];
+			next.hot = next.len;
 		} else if (span.at < del.at && span.to > del.to) {
 			next.slices[next.len++] = (struct Slice) {
 				prev.slices[i].ptr,
 				del.at - span.at,
 			};
-			next.slices[next.len++] = (struct Slice) {
+			next.slices[next.hot = next.len++] = (struct Slice) {
 				&prev.slices[i].ptr[del.to - span.at],
 				prev.slices[i].len - (del.to - span.at),
 			};
@@ -83,8 +84,9 @@ struct Table tableDelete(struct Table prev, struct Span del) {
 				prev.slices[i].ptr,
 				del.at - span.at,
 			};
+			next.hot = next.len;
 		} else if (span.at < del.to && span.to > del.to) {
-			next.slices[next.len++] = (struct Slice) {
+			next.slices[next.hot = next.len++] = (struct Slice) {
 				&prev.slices[i].ptr[del.to - span.at],
 				prev.slices[i].len - (del.to - span.at),
 			};
@@ -98,36 +100,74 @@ struct Table tableDelete(struct Table prev, struct Span del) {
 #ifdef TEST
 #include <assert.h>
 
-static struct Span span(size_t at, size_t to) {
-	return (struct Span) { at, to };
-}
-
 static struct Slice slice(const wchar_t *str) {
 	return (struct Slice) { str, wcslen(str) };
 }
 
-static int eq(struct Table table, const wchar_t *str) {
+static struct Span span(size_t at, size_t to) {
+	return (struct Span) { at, to };
+}
+
+static int eq(const wchar_t *str, struct Table table) {
 	for (size_t i = 0; i < table.len; ++i) {
 		if (wcsncmp(str, table.slices[i].ptr, table.slices[i].len)) {
 			return 0;
 		}
 		str = &str[table.slices[i].len];
 	}
-	return 1;
+	return !str[0];
+}
+
+static int hot(wint_t ch, struct Table table) {
+	if (table.hot == table.len) {
+		return ch == WEOF;
+	} else {
+		return ch == table.slices[table.hot].ptr[0];
+	}
 }
 
 int main() {
 	struct Table abc = tableInsert(TableEmpty, 0, slice(L"ABC"));
-	assert(eq(abc, L"ABC"));
+	assert(eq(L"ABC", abc));
+	assert(hot(L'A', abc));
+
+	struct Table dabc = tableInsert(abc, 0, slice(L"D"));
+	struct Table abcd = tableInsert(abc, 3, slice(L"D"));
+	struct Table adbc = tableInsert(abc, 1, slice(L"D"));
+
+	assert(eq(L"DABC", dabc));
+	assert(eq(L"ABCD", abcd));
+	assert(eq(L"ADBC", adbc));
+
+	assert(hot(L'D', dabc));
+	assert(hot(L'D', abcd));
+	assert(hot(L'D', adbc));
+
+	free(dabc.slices);
+	free(abcd.slices);
+	free(adbc.slices);
+
+	struct Table bc = tableDelete(abc, span(0, 1));
+	struct Table ab = tableDelete(abc, span(2, 3));
+	struct Table ac = tableDelete(abc, span(1, 2));
+	struct Table __ = tableDelete(abc, span(0, 3));
+
+	assert(eq(L"BC", bc));
+	assert(eq(L"AB", ab));
+	assert(eq(L"AC", ac));
+	assert(eq(L"",   __));
+
+	assert(hot(L'B', bc));
+	assert(hot(WEOF, ab));
+	assert(hot(L'C', ac));
+	assert(hot(WEOF, __));
 
-	assert(eq(tableInsert(abc, 0, slice(L"D")), L"DABC"));
-	assert(eq(tableInsert(abc, 3, slice(L"D")), L"ABCD"));
-	assert(eq(tableInsert(abc, 1, slice(L"D")), L"ADBC"));
+	free(bc.slices);
+	free(ab.slices);
+	free(ac.slices);
+	free(__.slices);
 
-	assert(eq(tableDelete(abc, span(0, 1)), L"BC"));
-	assert(eq(tableDelete(abc, span(2, 3)), L"AB"));
-	assert(eq(tableDelete(abc, span(1, 2)), L"AC"));
-	assert(eq(tableDelete(abc, span(0, 3)), L""));
+	free(abc.slices);
 }
 
 #endif