summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-06-20 00:09:25 -0700
committerKaz Kylheku <kaz@kylheku.com>2024-06-20 00:09:25 -0700
commit6bd0f5494990a18352de716987460914858d2f82 (patch)
tree8e36724451ab2f6199e387cdfc0daaba75a14b13
parent635aa6b2b6395a1f7c20cd4182f7be261f98b36e (diff)
downloadtxr-6bd0f5494990a18352de716987460914858d2f82.tar.gz
txr-6bd0f5494990a18352de716987460914858d2f82.tar.bz2
txr-6bd0f5494990a18352de716987460914858d2f82.zip
length: support string ranges.
For calculating the length of a range, we can't just do numeric subtractions because it fails for string ranges. * lib.c (length_str_range, length_rng): New static functions. (length): Use length_rng for ranges.
-rw-r--r--lib.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index ff7f0ed2..a1235247 100644
--- a/lib.c
+++ b/lib.c
@@ -553,6 +553,29 @@ static int seq_iter_peek_range_number(seq_iter_t *it, val *pval)
return 0;
}
+static val length_str_range(val from, val to)
+{
+ val self = lit("length");
+
+ if (eql(length_str(from), length_str(to))) {
+ const wchar_t *fs = c_str(from, self);
+ const wchar_t *ts = c_str(to, self);
+ val out = one;
+ cnum i;
+
+ for (i = 0; fs[i]; i++)
+ out = mul(out, num(labs(ts[i] - fs[i]) + 1));
+
+ gc_hint(from);
+ gc_hint(to);
+
+ return out;
+ } else {
+ uw_throwf(type_error_s, lit("~a: ~s..~s are of unequal length"),
+ self, from, to, nao);
+ }
+}
+
static int seq_iter_get_range_str(seq_iter_t *it, val *pval)
{
if (it->ui.vn) {
@@ -13348,6 +13371,21 @@ val copy(val seq)
}
}
+static val length_rng(val rng)
+{
+ val fv = from(rng);
+ val tv = to(rng);
+
+ if (stringp(fv)) {
+ if (!stringp(tv))
+ type_mismatch(lit("length: both fields of ~s must be strings"),
+ rng, nao);
+ return length_str_range(fv, tv);
+ }
+
+ return minus(to(rng), from(rng));
+}
+
val length(val seq)
{
switch (type(seq)) {
@@ -13363,7 +13401,7 @@ val length(val seq)
case VEC:
return length_vec(seq);
case RNG:
- return minus(to(seq), from(seq));
+ return length_rng(seq);
case BUF:
return length_buf(seq);
case COBJ: