summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-08-22 01:15:19 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-08-22 01:15:19 -0700
commit7edaa71c065af361b6a8d5e41a213fb82ed67579 (patch)
tree0c171bfc6a6416580c5fc9c4a817dcabfc05ea63 /lib.c
parentc1b264c157821352175eee7f5663f2c1782dfc1f (diff)
downloadtxr-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.c86
1 files changed, 84 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index 206cd295..68f95d01 100644
--- a/lib.c
+++ b/lib.c
@@ -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 {