diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-08-22 01:15:19 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-08-22 01:15:19 -0700 |
commit | 7edaa71c065af361b6a8d5e41a213fb82ed67579 (patch) | |
tree | 0c171bfc6a6416580c5fc9c4a817dcabfc05ea63 /lib.c | |
parent | c1b264c157821352175eee7f5663f2c1782dfc1f (diff) | |
download | txr-7edaa71c065af361b6a8d5e41a213fb82ed67579.tar.gz txr-7edaa71c065af361b6a8d5e41a213fb82ed67579.tar.bz2 txr-7edaa71c065af361b6a8d5e41a213fb82ed67579.zip |
iter-begin: string range support.
Ranges like "AAA".."ZZZ" are now possible.
* lib.c (seq_iter_get_range_str, seq_iter_peek_range_str,
seq_iter_get_rev_range_str): New static functions.
(seq_iter_init_with_info): Support string ranges via above
new functions. Range direction test is now done with less
and equal rather than lt and gt.
* tests/012/iter.tl: New file.
* txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 86 |
1 files changed, 84 insertions, 2 deletions
@@ -545,6 +545,42 @@ static int seq_iter_peek_range_bignum(seq_iter_t *it, val *pval) return 0; } +static int seq_iter_get_range_str(seq_iter_t *it, val *pval) +{ + if (it->ui.vn) { + val init = from(it->inf.obj); + val len = length_str(init); + val next = copy_str(it->ui.vn); + cnum l = c_num(len, nil); + wchar_t *nx = strip_qual(wchar_t *, c_str(next, nil)); + const wchar_t *in = c_str(init, nil); + const wchar_t *bn = c_str(it->ul.vbound, nil); + + *pval = it->ui.vn; + + for (; l > 0; l--) { + if (++nx[l - 1] <= bn[l - 1]) + break; + nx[l - 1] = in[l - 1]; + } + + it->ui.vn = if2(l > 0, next); + + return 1; + } + + return 0; +} + +static int seq_iter_peek_range_str(seq_iter_t *it, val *pval) +{ + if (it->ui.vn) { + *pval = it->ui.vn; + return 1; + } + return 0; +} + static int seq_iter_get_rev_range_cnum(seq_iter_t *it, val *pval) { if (it->ui.cn > it->ul.cbound) { @@ -599,6 +635,32 @@ static int seq_iter_peek_rev_range_bignum(seq_iter_t *it, val *pval) return 0; } +static int seq_iter_get_rev_range_str(seq_iter_t *it, val *pval) +{ + if (it->ui.vn) { + val init = from(it->inf.obj); + val len = length_str(init); + val next = copy_str(it->ui.vn); + cnum l = c_num(len, nil); + wchar_t *nx = strip_qual(wchar_t *, c_str(next, nil)); + const wchar_t *in = c_str(init, nil); + const wchar_t *bn = c_str(it->ul.vbound, nil); + + *pval = it->ui.vn; + + for (; l > 0; l--) { + if (--nx[l - 1] >= bn[l - 1]) + break; + nx[l - 1] = in[l - 1]; + } + + it->ui.vn = if2(l > 0, next); + + return 1; + } + + return 0; +} static int seq_iter_get_chr(seq_iter_t *it, val *pval) { @@ -815,7 +877,7 @@ void seq_iter_init_with_info(val self, seq_iter_t *it, break; } - if (lt(rf, rt)) switch (type(rf)) { + if (less(rf, rt)) switch (type(rf)) { case NUM: it->ui.cn = c_num(rf, self); it->ul.cbound = c_num(rt, self); @@ -834,9 +896,19 @@ void seq_iter_init_with_info(val self, seq_iter_t *it, it->get = seq_iter_get_range_bignum; it->peek = seq_iter_peek_range_bignum; break; + case LIT: + case STR: + case LSTR: + it->ui.vn = copy_str(rf); + it->ul.vbound = rt; + it->get = seq_iter_get_range_str; + it->peek = seq_iter_peek_range_str; + if (eql(length_str(rf), length_str(rt))) + break; + /* fallthrough */ default: unsup_obj(self, it->inf.obj); - } else if (gt(rf, rt)) switch (type(rf)) { + } else if (!equal(rf, rt)) switch (type(rf)) { case NUM: it->ui.cn = c_num(rf, self); it->ul.cbound = c_num(rt, self); @@ -855,6 +927,16 @@ void seq_iter_init_with_info(val self, seq_iter_t *it, it->get = seq_iter_get_rev_range_bignum; it->peek = seq_iter_peek_rev_range_bignum; break; + case LIT: + case STR: + case LSTR: + it->ui.vn = copy_str(rf); + it->ul.vbound = rt; + it->get = seq_iter_get_rev_range_str; + it->peek = seq_iter_peek_range_str; + if (eql(length_str(rf), length_str(rt))) + break; + /* fallthrough */ default: unsup_obj(self, it->inf.obj); } else { |