1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/* Copyright (C) 2018 June McEnroe <june@causal.agency>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <wchar.h>
#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 <assert.h>
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(WEOF == iter(&table, 4).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
|