From f8da655d5b8154940540a1de62122b7639cf235e Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Wed, 21 Nov 2018 23:41:15 -0500 Subject: Add Iter for edi --- bin/edi/Makefile | 2 ++ bin/edi/buffer.c | 1 - bin/edi/edi.c | 6 ++-- bin/edi/edi.h | 19 ++++++++-- bin/edi/file.c | 1 - bin/edi/iter.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/edi/table.c | 7 +--- 7 files changed, 130 insertions(+), 14 deletions(-) create mode 100644 bin/edi/iter.c diff --git a/bin/edi/Makefile b/bin/edi/Makefile index 8ad154c6..2c98d9f2 100644 --- a/bin/edi/Makefile +++ b/bin/edi/Makefile @@ -4,10 +4,12 @@ LDLIBS = -lcursesw OBJS += buffer.o OBJS += edi.o OBJS += file.o +OBJS += iter.o OBJS += log.o OBJS += table.o TESTS += buffer.t +TESTS += iter.t TESTS += table.t all: tags edi test diff --git a/bin/edi/buffer.c b/bin/edi/buffer.c index 7297f411..5950317e 100644 --- a/bin/edi/buffer.c +++ b/bin/edi/buffer.c @@ -34,7 +34,6 @@ struct Buffer bufferAlloc(size_t cap) { struct Block *block = blockAlloc(NULL, cap); return (struct Buffer) { .cap = cap, - .len = 0, .slice = { block->chars, 0 }, .block = block, }; diff --git a/bin/edi/edi.c b/bin/edi/edi.c index c8cd2a44..fb6e3929 100644 --- a/bin/edi/edi.c +++ b/bin/edi/edi.c @@ -30,10 +30,8 @@ int main(int argc, char *argv[]) { fileRead(&file); const struct Table *table = &file.log.states[file.log.state].table; - for (size_t i = 0; i < table->len; ++i) { - for (size_t j = 0; j < table->slices[i].len; ++j) { - printf("%lc", table->slices[i].ptr[j]); - } + for (struct Iter it = iter(table, 0); it.ch != WEOF; it = iterNext(it)) { + printf("%lc", it.ch); } fileFree(&file); diff --git a/bin/edi/edi.h b/bin/edi/edi.h index 3425b235..6891b866 100644 --- a/bin/edi/edi.h +++ b/bin/edi/edi.h @@ -17,11 +17,15 @@ #include #include -static inline struct Span { +struct Span { size_t at, to; -} spanNext(struct Span span, size_t len) { +}; +static inline struct Span spanNext(struct Span span, size_t len) { return (struct Span) { span.to, span.to + len }; } +static inline struct Span spanPrev(struct Span span, size_t len) { + return (struct Span) { span.at - len, span.at }; +} struct Slice { const wchar_t *ptr; @@ -55,6 +59,17 @@ struct Table tableInsert(const struct Table *prev, size_t at, struct Slice ins); struct Table tableDelete(const struct Table *prev, struct Span del); void tableUpdate(struct Table *table, struct Slice ins); +struct Iter { + const struct Table *table; + struct Span span; + size_t slice; + size_t at; + wint_t ch; +}; +struct Iter iter(const struct Table *table, size_t at); +struct Iter iterNext(struct Iter it); +struct Iter iterPrev(struct Iter it); + struct Log { size_t cap, len; size_t state; diff --git a/bin/edi/file.c b/bin/edi/file.c index 9f85d1da..55b7d679 100644 --- a/bin/edi/file.c +++ b/bin/edi/file.c @@ -34,7 +34,6 @@ struct File fileAlloc(char *path) { .path = path, .buf = bufferAlloc(BufCap), .log = logAlloc(LogCap), - .clean = 0, }; if (!path) logPush(&file.log, TableEmpty); return file; diff --git a/bin/edi/iter.c b/bin/edi/iter.c new file mode 100644 index 00000000..cfbefc89 --- /dev/null +++ b/bin/edi/iter.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2018 June McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "edi.h" + +struct Iter iter(const struct Table *table, size_t at) { + struct Span span = { 0, 0 }; + size_t slice; + for (slice = 0; slice < table->len; ++slice) { + span = spanNext(span, table->slices[slice].len); + if (span.at <= at && span.to > at) break; + } + return (struct Iter) { + .table = table, + .span = span, + .slice = slice, + .at = (at < span.to ? at : span.to), + .ch = (at < span.to ? table->slices[slice].ptr[at - span.at] : WEOF), + }; +} + +struct Iter iterNext(struct Iter it) { + if (it.at == it.span.to && it.ch == WEOF) return it; + it.at++; + if (it.at == it.span.to) { + if (it.slice + 1 == it.table->len) { + it.ch = WEOF; + return it; + } + it.slice++; + it.span = spanNext(it.span, it.table->slices[it.slice].len); + } + it.ch = it.table->slices[it.slice].ptr[it.at - it.span.at]; + return it; +} + +struct Iter iterPrev(struct Iter it) { + if (it.at > it.span.to && it.ch == WEOF) return it; + it.at--; + if (it.at > it.span.to) { + it.ch = WEOF; + return it; + } + if (it.at < it.span.at) { + it.slice--; + it.span = spanPrev(it.span, it.table->slices[it.slice].len); + } + it.ch = it.table->slices[it.slice].ptr[it.at - it.span.at]; + return it; +} + +#ifdef TEST +#include + +int main() { + struct Slice slices[2] = { + { L"AB", 2 }, + { L"CD", 2 }, + }; + struct Table table = { .len = 2, .slices = slices }; + + assert(L'A' == iter(&table, 0).ch); + assert(L'B' == iter(&table, 1).ch); + assert(L'C' == iter(&table, 2).ch); + assert(L'D' == iter(&table, 3).ch); + + assert(L'B' == iterNext(iter(&table, 0)).ch); + assert(L'C' == iterNext(iter(&table, 1)).ch); + assert(L'D' == iterNext(iter(&table, 2)).ch); + assert(WEOF == iterNext(iter(&table, 5)).ch); + + assert(WEOF == iterPrev(iter(&table, 0)).ch); + assert(L'A' == iterPrev(iter(&table, 1)).ch); + assert(L'B' == iterPrev(iter(&table, 2)).ch); + assert(L'C' == iterPrev(iter(&table, 3)).ch); + + struct Iter it = iter(&table, 3); + it = iterNext(it); + it = iterNext(it); + assert(WEOF == it.ch); + it = iterPrev(it); + assert(L'D' == it.ch); + + it = iter(&table, 0); + it = iterPrev(it); + it = iterPrev(it); + assert(WEOF == it.ch); + it = iterNext(it); + assert(L'A' == it.ch); +} + +#endif diff --git a/bin/edi/table.c b/bin/edi/table.c index 593766a4..7905d7d7 100644 --- a/bin/edi/table.c +++ b/bin/edi/table.c @@ -24,12 +24,7 @@ struct Table tableAlloc(size_t cap) { struct Slice *slices = malloc(sizeof(*slices) * cap); if (!slices) err(EX_OSERR, "malloc"); - return (struct Table) { - .cap = cap, - .len = 0, - .ins = 0, - .slices = slices, - }; + return (struct Table) { .cap = cap, .slices = slices }; } void tableFree(struct Table *table) { -- cgit 1.4.1