diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2015-08-01 19:42:15 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2015-08-01 19:42:15 +0200 |
| commit | 7c5c6581bca271f41c7ae3ac53107b89249a5fa9 (patch) | |
| tree | c22ae8d18870172d30bd876338d74b4fe0cd2538 | |
| parent | 25beaeb21f3d0b2fcd9b6c612cd2d7cb25291a28 (diff) | |
| download | vis-7c5c6581bca271f41c7ae3ac53107b89249a5fa9.tar.gz vis-7c5c6581bca271f41c7ae3ac53107b89249a5fa9.tar.xz | |
text-motion: fix text_find_{next,prev}
It is after all a stupid O(n*m) algorithm, hence restart after
a failed partial match.
Code like this would benefit from a proper test suite ...
| -rw-r--r-- | text-motions.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/text-motions.c b/text-motions.c index 9d40c33..8b349c2 100644 --- a/text-motions.c +++ b/text-motions.c @@ -50,12 +50,16 @@ size_t text_find_next(Text *txt, size_t pos, const char *s) { if (!s) return pos; size_t len = strlen(s), matched = 0; - Iterator it = text_iterator_get(txt, pos); + Iterator it = text_iterator_get(txt, pos), sit; for (char c; matched < len && text_iterator_byte_get(&it, &c); ) { - if (c == s[matched]) + if (c == s[matched]) { + if (matched == 0) + sit = it; matched++; - else + } else if (matched > 0) { + it = sit; matched = 0; + } text_iterator_byte_next(&it, NULL); } return matched == len ? it.pos - len : pos; @@ -65,15 +69,18 @@ size_t text_find_prev(Text *txt, size_t pos, const char *s) { if (!s) return pos; size_t len = strlen(s), matched = len - 1; - Iterator it = text_iterator_get(txt, pos); + Iterator it = text_iterator_get(txt, pos), sit; if (len == 0) return pos; for (char c; text_iterator_byte_get(&it, &c); ) { if (c == s[matched]) { if (matched == 0) break; + if (matched == len - 1) + sit = it; matched--; - } else { + } else if (matched < len - 1) { + it = sit; matched = len - 1; } text_iterator_byte_prev(&it, NULL); |
