summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-19 15:18:50 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-19 15:18:50 +0000
commit7f95eed19e22cb9a4867819355fe4ab99f85fd16 (patch)
tree988295914fd4e93cf415ec614a9f0a9923e71299 /string.c
parent3a5d1e4b775deee8c8731a97048b752a33b35922 (diff)
Introduce endless range [Feature#12912]
Typical usages: ``` p ary[1..] # drop the first element; identical to ary[1..-1] (1..).each {|n|...} # iterate forever from 1; identical to 1.step{...} ``` git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63192 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/string.c b/string.c
index 29457c0fb3..ad9ba6f355 100644
--- a/string.c
+++ b/string.c
@@ -4325,6 +4325,50 @@ str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALUE a
return beg;
}
+VALUE
+rb_str_upto_endless_each(VALUE beg, VALUE (*each)(VALUE, VALUE), VALUE arg)
+{
+ VALUE current;
+ ID succ;
+
+ CONST_ID(succ, "succ");
+ /* both edges are all digits */
+ if (is_ascii_string(beg) && ISDIGIT(RSTRING_PTR(beg)[0]) &&
+ all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
+ VALUE b, args[2], fmt = rb_fstring_cstr("%.*d");
+ int width = RSTRING_LENINT(beg);
+ b = rb_str_to_inum(beg, 10, FALSE);
+ if (FIXNUM_P(b)) {
+ long bi = FIX2LONG(b);
+ rb_encoding *usascii = rb_usascii_encoding();
+
+ while (FIXABLE(bi)) {
+ (*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg);
+ bi++;
+ }
+ b = LONG2NUM(bi);
+ }
+ args[0] = INT2FIX(width);
+ while (1) {
+ args[1] = b;
+ (*each)(rb_str_format(numberof(args), args, fmt), arg);
+ b = rb_funcallv(b, succ, 0, 0);
+ }
+ }
+ /* normal case */
+ current = rb_str_dup(beg);
+ while (1) {
+ VALUE next = rb_funcallv(current, succ, 0, 0);
+ (*each)(current, arg);
+ current = next;
+ StringValue(current);
+ if (RSTRING_LEN(current) == 0)
+ break;
+ }
+
+ return beg;
+}
+
static int
include_range_i(VALUE str, VALUE arg)
{