diff options
author | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-19 15:18:50 +0000 |
---|---|---|
committer | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-19 15:18:50 +0000 |
commit | 7f95eed19e22cb9a4867819355fe4ab99f85fd16 (patch) | |
tree | 988295914fd4e93cf415ec614a9f0a9923e71299 /string.c | |
parent | 3a5d1e4b775deee8c8731a97048b752a33b35922 (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.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -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) { |