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/iter.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 bin/edi/iter.c (limited to 'bin/edi/iter.c') 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 -- cgit 1.4.1