From 80e0ef3a8167dddc8434e981a5df5925e667919e Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 15 May 2015 12:39:56 +0000 Subject: [PATCH] range.c: move String specific code * range.c (range_include): call rb_str_include_range_p on String. * string.c (str_upto_each): extract from rb_str_upto. * string.c (rb_str_include_range_p): move String specific code from Range#include? in range.c. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50502 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- range.c | 23 +++------------ string.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 81 insertions(+), 28 deletions(-) diff --git a/range.c b/range.c index cfb8c24fab..8f48cd9089 100644 --- a/range.c +++ b/range.c @@ -174,7 +174,7 @@ range_eq(VALUE range, VALUE obj) /* compares _a_ and _b_ and returns: * < 0: a < b * = 0: a = b - * > 0: a > b or not-comparable + * > 0: a > b or non-comparable */ static int r_less(VALUE a, VALUE b) @@ -1165,24 +1165,9 @@ range_include(VALUE range, VALUE val) !NIL_P(rb_check_to_integer(end, "to_int"))) { return r_cover_p(range, beg, end, val); } - else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) && - RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) { - if (NIL_P(val)) return Qfalse; - if (RB_TYPE_P(val, T_STRING)) { - if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1) - return Qfalse; - else { - char b = RSTRING_PTR(beg)[0]; - char e = RSTRING_PTR(end)[0]; - char v = RSTRING_PTR(val)[0]; - - if (ISASCII(b) && ISASCII(e) && ISASCII(v)) { - if (b <= v && v < e) return Qtrue; - if (!EXCL(range) && v == e) return Qtrue; - return Qfalse; - } - } - } + else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) { + VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive); + return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range)); } /* TODO: ruby_frame->this_func = rb_intern("include?"); */ return rb_call_super(1, &val); diff --git a/string.c b/string.c index 80541e4b8b..943c18c140 100644 --- a/string.c +++ b/string.c @@ -3459,6 +3459,15 @@ all_digits_p(const char *s, long len) return 1; } +static VALUE str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALUE); + +static int +str_upto_i(VALUE str, VALUE arg) +{ + rb_yield(str); + return 0; +} + /* * call-seq: * str.upto(other_str, exclusive=false) {|s| block } -> str @@ -3495,14 +3504,20 @@ static VALUE rb_str_upto(int argc, VALUE *argv, VALUE beg) { VALUE end, exclusive; - VALUE current, after_end; - ID succ; - int n, excl, ascii; - rb_encoding *enc; rb_scan_args(argc, argv, "11", &end, &exclusive); RETURN_ENUMERATOR(beg, argc, argv); - excl = RTEST(exclusive); + return str_upto_each(beg, end, RTEST(exclusive), str_upto_i, Qnil); +} + +static VALUE +str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALUE arg) +{ + VALUE current, after_end; + ID succ; + int n, ascii; + rb_encoding *enc; + CONST_ID(succ, "succ"); StringValue(end); enc = rb_enc_check(beg, end); @@ -3514,7 +3529,7 @@ rb_str_upto(int argc, VALUE *argv, VALUE beg) if (c > e || (excl && c == e)) return beg; for (;;) { - rb_yield(rb_enc_str_new(&c, 1, enc)); + if ((*each)(rb_enc_str_new(&c, 1, enc), arg)) break; if (!excl && c == e) break; c++; if (excl && c == e) break; @@ -3538,7 +3553,7 @@ rb_str_upto(int argc, VALUE *argv, VALUE beg) while (bi <= ei) { if (excl && bi == ei) break; - rb_yield(rb_enc_sprintf(usascii, "%.*ld", width, bi)); + if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break; bi++; } } @@ -3549,7 +3564,7 @@ rb_str_upto(int argc, VALUE *argv, VALUE beg) args[0] = INT2FIX(width); while (rb_funcall(b, op, 1, e)) { args[1] = b; - rb_yield(rb_str_format(numberof(args), args, fmt)); + if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break; b = rb_funcallv(b, succ, 0, 0); } } @@ -3565,7 +3580,7 @@ rb_str_upto(int argc, VALUE *argv, VALUE beg) VALUE next = Qnil; if (excl || !rb_str_equal(current, end)) next = rb_funcallv(current, succ, 0, 0); - rb_yield(current); + if ((*each)(current, arg)) break; if (NIL_P(next)) break; current = next; StringValue(current); @@ -3577,6 +3592,59 @@ rb_str_upto(int argc, VALUE *argv, VALUE beg) return beg; } +static int +include_range_i(VALUE str, VALUE arg) +{ + VALUE *argp = (VALUE *)arg; + if (!rb_equal(str, *argp)) return 0; + *argp = Qnil; + return 1; +} + +VALUE +rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive) +{ + beg = rb_str_new_frozen(beg); + StringValue(end); + end = rb_str_new_frozen(end); + if (NIL_P(val)) return Qfalse; + val = rb_check_string_type(val); + if (NIL_P(val)) return Qfalse; + if (rb_enc_asciicompat(STR_ENC_GET(beg)) && + rb_enc_asciicompat(STR_ENC_GET(end)) && + rb_enc_asciicompat(STR_ENC_GET(val))) { + const char *bp = RSTRING_PTR(beg); + const char *ep = RSTRING_PTR(end); + const char *vp = RSTRING_PTR(val); + if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) { + if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1) + return Qfalse; + else { + char b = *bp; + char e = *ep; + char v = *vp; + + if (ISASCII(b) && ISASCII(e) && ISASCII(v)) { + if (b <= v && v < e) return Qtrue; + if (!RTEST(exclusive) && v == e) return Qtrue; + return Qfalse; + } + } + } +#if 0 + /* both edges are all digits */ + if (ISDIGIT(*bp) && ISDIGIT(*ep) && + all_digits_p(bp, RSTRING_LEN(beg)) && + all_digits_p(ep, RSTRING_LEN(end))) { + /* TODO */ + } +#endif + } + str_upto_each(beg, end, RTEST(exclusive), include_range_i, (VALUE)&val); + + return NIL_P(val) ? Qtrue : Qfalse; +} + static VALUE rb_str_subpat(VALUE str, VALUE re, VALUE backref) {