Пример #1
0
static VALUE
range_max(VALUE range, SEL sel)
{
    VALUE e = RANGE_END(range);
    int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);

    if (rb_block_given_p() || (EXCL(range) && !nm)) {
	if (sel == NULL) {
	    sel = sel_registerName("max");
	}
	return rb_vm_call_super(range, sel, 0, NULL);
    }
    else {
	VALUE b = RANGE_BEG(range);
	int c = rb_cmpint(rb_objs_cmp(b, e), b, e);

	if (c > 0)
	    return Qnil;
	if (EXCL(range)) {
	    if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
		rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
	    }
	    if (c == 0) {
		return Qnil;
	    }
	    if (FIXNUM_P(e)) {
		return LONG2NUM(FIX2LONG(e) - 1);
	    }
	    VALUE one = INT2FIX(1);
	    return rb_vm_call(e, selMINUS, 1, &one);
	}
	return e;
    }
}
Пример #2
0
static VALUE
range_max(int argc, VALUE *argv, VALUE range)
{
    VALUE e = RANGE_END(range);
    int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);

    if (rb_block_given_p() || (EXCL(range) && !nm) || argc) {
	return rb_call_super(argc, argv);
    }
    else {
	VALUE b = RANGE_BEG(range);
	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

	if (c > 0)
	    return Qnil;
	if (EXCL(range)) {
	    if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
		rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
	    }
	    if (c == 0) return Qnil;
	    if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
		rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
	    }
	    if (FIXNUM_P(e)) {
		return LONG2NUM(FIX2LONG(e) - 1);
	    }
	    return rb_funcall(e, '-', 1, INT2FIX(1));
	}
	return e;
    }
}
Пример #3
0
static VALUE
range_max(VALUE range)
{
    VALUE e = RANGE_END(range);
    int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);

    if (rb_block_given_p() || (EXCL(range) && !ip)) {
	return rb_call_super(0, 0);
    }
    else {
	VALUE b = RANGE_BEG(range);
	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

	if (c > 0)
	    return Qnil;
	if (EXCL(range)) {
	    if (c == 0) return Qnil;
	    if (FIXNUM_P(e)) {
		return LONG2NUM(FIX2LONG(e) - 1);
	    }
	    return rb_funcall(e, '-', 1, INT2FIX(1));
	}
	return e;
    }
}
Пример #4
0
static VALUE
recursive_eql(VALUE range, VALUE obj, int recur)
{
    if (recur) return Qtrue; /* Subtle! */
    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
	return Qfalse;
    if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
	return Qfalse;

    if (EXCL(range) != EXCL(obj))
	return Qfalse;
    return Qtrue;
}
Пример #5
0
static VALUE
range_hash(VALUE range)
{
    long hash = EXCL(range);
    VALUE v;

    v = rb_hash(RANGE_BEG(range));
    hash ^= v << 1;
    v = rb_hash(RANGE_END(range));
    hash ^= v << 9;
    hash ^= EXCL(range) << 24;

    return LONG2FIX(hash);
}
Пример #6
0
static VALUE
range_each(VALUE range, SEL sel)
{
    VALUE beg, end;

    RETURN_ENUMERATOR(range, 0, 0);

    beg = RANGE_BEG(range);
    end = RANGE_END(range);

    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
	long lim = FIX2LONG(end);
	long i;

	if (!EXCL(range))
	    lim += 1;
	for (i = FIX2LONG(beg); i < lim; i++) {
	    rb_yield(LONG2FIX(i));
	    RETURN_IF_BROKEN();
	}
    }
    else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
	VALUE args[2];

	args[0] = rb_sym_to_s(end);
	args[1] = EXCL(range) ? Qtrue : Qfalse;
	rb_objc_block_call(rb_sym_to_s(beg), selUpto, 2, args, sym_each_i, 0);
    }
    else {
	VALUE tmp = rb_check_string_type(beg);

	if (!NIL_P(tmp)) {
	    VALUE args[2];

	    args[0] = end;
	    args[1] = EXCL(range) ? Qtrue : Qfalse;
	    rb_objc_block_call(beg, selUpto, 2, args, rb_yield, 0);
	}
	else {
	    if (!discrete_object_p(beg)) {
		rb_raise(rb_eTypeError, "can't iterate from %s",
			 rb_obj_classname(beg));
	    }
	    range_each_func(range, each_i, NULL);
	}
    }
    return range;
}
Пример #7
0
static VALUE
range_include(VALUE range, SEL sel, VALUE val)
{
    VALUE beg = RANGE_BEG(range);
    VALUE end = RANGE_END(range);
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
	     rb_obj_is_kind_of(end, rb_cNumeric);

    if (nv ||
	!NIL_P(rb_check_to_integer(beg, "to_int")) ||
	!NIL_P(rb_check_to_integer(end, "to_int"))) {
	if (r_le(beg, val)) {
	    if (EXCL(range)) {
		if (r_lt(val, end))
		    return Qtrue;
	    }
	    else {
		if (r_le(val, end))
		    return Qtrue;
	    }
	}
	return Qfalse;
    }
    else if (TYPE(beg) == T_STRING && TYPE(end) == T_STRING &&
	     RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
	if (NIL_P(val)) return Qfalse;
	if (TYPE(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;
		}
	    }
	}
    }
    if (sel == NULL) {
	sel = sel_registerName("include?:");
    }
    return rb_vm_call_super(range, sel, 1, &val);
}
Пример #8
0
static VALUE
range_hash(VALUE range)
{
    st_index_t hash = EXCL(range);
    VALUE v;

    hash = rb_hash_start(hash);
    v = rb_hash(RANGE_BEG(range));
    hash = rb_hash_uint(hash, NUM2LONG(v));
    v = rb_hash(RANGE_END(range));
    hash = rb_hash_uint(hash, NUM2LONG(v));
    hash = rb_hash_uint(hash, EXCL(range) << 24);
    hash = rb_hash_end(hash);

    return LONG2FIX(hash);
}
Пример #9
0
static VALUE
range_include(VALUE range, VALUE val)
{
    VALUE beg = RANGE_BEG(range);
    VALUE end = RANGE_END(range);
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
	     rb_obj_is_kind_of(end, rb_cNumeric);

    if (nv ||
	!NIL_P(rb_check_to_integer(beg, "to_int")) ||
	!NIL_P(rb_check_to_integer(end, "to_int"))) {
	if (r_le(beg, val)) {
	    if (EXCL(range)) {
		if (r_lt(val, end))
		    return Qtrue;
	    }
	    else {
		if (r_le(val, end))
		    return Qtrue;
	    }
	}
	return Qfalse;
    }
    /* TODO: ruby_frame->this_func = rb_intern("include?"); */
    return rb_call_super(1, &val);
}
Пример #10
0
static VALUE
range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
{
    int c;
    VALUE b = RANGE_BEG(range);
    VALUE e = RANGE_END(range);
    VALUE v = b;

    if (EXCL(range)) {
	while (r_lt(v, e)) {
	    (*func) (v, arg);
	    RETURN_IF_BROKEN();
	    v = rb_vm_call(v, selSucc, 0, NULL);
	}
    }
    else {
	while (RTEST(c = r_le(v, e))) {
	    (*func) (v, arg);
	    RETURN_IF_BROKEN();
	    if (c == INT2FIX(0))
		break;
	    v = rb_vm_call(v, selSucc, 0, NULL);
	}
    }
    return range;
}
Пример #11
0
int
rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
{
    VALUE b, e;
    int excl;

    if (rb_obj_is_kind_of(range, rb_cRange)) {
        b = RANGE_BEG(range);
        e = RANGE_END(range);
        excl = EXCL(range);
    }
    else {
	if (!rb_vm_respond_to(range, selBeg, false)) {
	    return 0;
	}
	if (!rb_vm_respond_to(range, selEnd, false)) {
	    return 0;
	}
	b = rb_vm_call(range, selBeg, 0, NULL);
	e = rb_vm_call(range, selEnd, 0, NULL);
	excl = RTEST(rb_vm_call(range, selExcludeEnd, 0, NULL));
    }
    *begp = b;
    *endp = e;
    *exclp = excl;
    return 1;
}
Пример #12
0
static VALUE
inspect_range(VALUE range, VALUE dummy, int recur)
{
    VALUE str, str2;

    if (recur) {
	return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
    }
    str = rb_inspect(RANGE_BEG(range));
    str2 = rb_inspect(RANGE_END(range));
    str = rb_str_dup(str);
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
    rb_str_append(str, str2);
    OBJ_INFECT(str, str2);

    return str;
}
Пример #13
0
void
rb_range_extract(VALUE range, VALUE *begp, VALUE *endp, bool *exclude)
{
    assert(begp != NULL && endp != NULL && exclude != NULL);
    *begp = RANGE_BEG(range);
    *endp = RANGE_END(range);
    *exclude = EXCL(range);
}
Пример #14
0
static VALUE
range_include(VALUE range, VALUE val)
{
    VALUE beg = RANGE_BEG(range);
    VALUE end = RANGE_END(range);
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
	     rb_obj_is_kind_of(end, rb_cNumeric);

    if (nv ||
	!NIL_P(rb_check_to_integer(beg, "to_int")) ||
	!NIL_P(rb_check_to_integer(end, "to_int"))) {
	if (r_le(beg, val)) {
	    if (EXCL(range)) {
		if (r_lt(val, end))
		    return Qtrue;
	    }
	    else {
		if (r_le(val, end))
		    return Qtrue;
	    }
	}
	return Qfalse;
    }
    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;
		}
	    }
	}
    }
    /* TODO: ruby_frame->this_func = rb_intern("include?"); */
    return rb_call_super(1, &val);
}
Пример #15
0
static VALUE
range_size(VALUE range)
{
    VALUE b = RANGE_BEG(range), e = RANGE_END(range);
    if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
	return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
    }
    return Qnil;
}
Пример #16
0
static VALUE
range_eql(VALUE range, VALUE obj)
{
    if (range == obj)
	return Qtrue;
    if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
	return Qfalse;

    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
	return Qfalse;
    if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
	return Qfalse;

    if (EXCL(range) != EXCL(obj))
	return Qfalse;

    return Qtrue;
}
Пример #17
0
static VALUE
recursive_hash(VALUE range, VALUE dummy, int recur)
{
    st_index_t hash = EXCL(range);
    VALUE v;

    hash = rb_hash_start(hash);
    if (!recur) {
	v = rb_hash(RANGE_BEG(range));
	hash = rb_hash_uint(hash, NUM2LONG(v));
	v = rb_hash(RANGE_END(range));
	hash = rb_hash_uint(hash, NUM2LONG(v));
    }
    hash = rb_hash_uint(hash, EXCL(range) << 24);
    hash = rb_hash_end(hash);

    return LONG2FIX(hash);
}
Пример #18
0
VALUE
rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
{
    VALUE b, e;
    long beg, end, excl;

    if (rb_obj_is_kind_of(range, rb_cRange)) {
	b = RANGE_BEG(range);
	e = RANGE_END(range);
	excl = EXCL(range);
    }
    else {
	b = rb_check_to_integer(range, "begin");
	if (NIL_P(b))
	    return Qfalse;
	e = rb_check_to_integer(range, "end");
	if (NIL_P(e))
	    return Qfalse;
	excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
    }
    beg = NUM2LONG(b);
    end = NUM2LONG(e);

    if (beg < 0) {
	beg += len;
	if (beg < 0)
	    goto out_of_range;
    }
    if (err == 0 || err == 2) {
	if (beg > len)
	    goto out_of_range;
	if (end > len)
	    end = len;
    }
    if (end < 0)
	end += len;
    if (!excl)
	end++;			/* include end point */
    len = end - beg;
    if (len < 0)
	len = 0;

    *begp = beg;
    *lenp = len;
    return Qtrue;

  out_of_range:
    if (err) {
	rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
		 b, excl ? "." : "", e);
    }
    return Qnil;
}
Пример #19
0
static VALUE
range_inspect(VALUE range)
{
    VALUE str, str2;

    str = rb_inspect(RANGE_BEG(range));
    str2 = rb_inspect(RANGE_END(range));
    str = rb_str_dup(str);
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
    rb_str_append(str, str2);
    OBJ_INFECT(str, str2);

    return str;
}
Пример #20
0
static VALUE
range_eql(VALUE range, SEL sel, VALUE obj)
{
    if (range == obj) {
	return Qtrue;
    }
    if (!rb_obj_is_kind_of(obj, rb_cRange)) {
	return Qfalse;
    }

    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj))) {
	return Qfalse;
    }
    if (!rb_eql(RANGE_END(range), RANGE_END(obj))) {
	return Qfalse;
    }

    if (EXCL(range) != EXCL(obj)) {
	return Qfalse;
    }

    return Qtrue;
}
Пример #21
0
static VALUE
range_to_s(VALUE range, SEL sel)
{
    VALUE str, str2;

    str = rb_obj_as_string(RANGE_BEG(range));
    str2 = rb_obj_as_string(RANGE_END(range));
    str = rb_str_dup(str);
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
    rb_str_append(str, str2);
    OBJ_INFECT(str, str2);

    return str;
}
Пример #22
0
static VALUE
range_each(VALUE range)
{
    VALUE beg, end;

    RETURN_ENUMERATOR(range, 0, 0);

    beg = RANGE_BEG(range);
    end = RANGE_END(range);

    if (!rb_respond_to(beg, id_succ)) {
	rb_raise(rb_eTypeError, "can't iterate from %s",
		 rb_obj_classname(beg));
    }
    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
	long lim = FIX2LONG(end);
	long i;

	if (!EXCL(range))
	    lim += 1;
	for (i = FIX2LONG(beg); i < lim; i++) {
	    rb_yield(LONG2NUM(i));
	}
    }
    else if (TYPE(beg) == T_STRING) {
	VALUE args[2];

	args[0] = end;
	args[1] = EXCL(range) ? Qtrue : Qfalse;
	rb_block_call(beg, rb_intern("upto"), 2, args, rb_yield, 0);
    }
    else {
	range_each_func(range, each_i, beg, end, NULL);
    }
    return range;
}
Пример #23
0
static VALUE
range_min(VALUE range)
{
    if (rb_block_given_p()) {
	return rb_call_super(0, 0);
    }
    else {
	VALUE b = RANGE_BEG(range);
	VALUE e = RANGE_END(range);
	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

	if (c > 0 || (c == 0 && EXCL(range)))
	    return Qnil;
	return b;
    }
}
Пример #24
0
static VALUE
range_min(VALUE range, SEL sel)
{
    if (rb_block_given_p()) {
	if (sel == NULL) {
	    sel = sel_registerName("min");
	}
	return rb_vm_call_super(range, sel, 0, NULL);
    }
    else {
	VALUE b = RANGE_BEG(range);
	VALUE e = RANGE_END(range);
	int c = rb_cmpint(rb_objs_cmp(b, e), b, e);

	if (c > 0 || (c == 0 && EXCL(range)))
	    return Qnil;
	return b;
    }
}
Пример #25
0
static VALUE
range_min(int argc, VALUE *argv, VALUE range)
{
    if (rb_block_given_p()) {
	return rb_call_super(argc, argv);
    }
    else if (argc != 0) {
	return range_first(argc, argv, range);
    }
    else {
	VALUE b = RANGE_BEG(range);
	VALUE e = RANGE_END(range);
	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

	if (c > 0 || (c == 0 && EXCL(range)))
	    return Qnil;
	return b;
    }
}
Пример #26
0
static VALUE
range_cover(VALUE range, SEL sel, VALUE val)
{
    VALUE beg, end;

    beg = RANGE_BEG(range);
    end = RANGE_END(range);
    if (r_le(beg, val)) {
	if (EXCL(range)) {
	    if (r_lt(val, end))
		return Qtrue;
	}
	else {
	    if (r_le(val, end))
		return Qtrue;
	}
    }
    return Qfalse;
}
Пример #27
0
static void
range_each_func(VALUE range, VALUE (*func) (VALUE, void *), VALUE v, VALUE e,
		void *arg)
{
    int c;

    if (EXCL(range)) {
	while (r_lt(v, e)) {
	    (*func) (v, arg);
	    v = rb_funcall(v, id_succ, 0, 0);
	}
    }
    else {
	while (RTEST(c = r_le(v, e))) {
	    (*func) (v, arg);
	    if (c == INT2FIX(0))
		break;
	    v = rb_funcall(v, id_succ, 0, 0);
	}
    }
}
Пример #28
0
static VALUE
range_step_size(VALUE range, VALUE args, VALUE eobj)
{
    VALUE b = RANGE_BEG(range), e = RANGE_END(range);
    VALUE step = INT2FIX(1);
    if (args) {
	step = RARRAY_AREF(args, 0);
	if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
	    step = rb_to_int(step);
	}
    }
    if (rb_funcall(step, '<', 1, INT2FIX(0))) {
	rb_raise(rb_eArgError, "step can't be negative");
    }
    else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
	rb_raise(rb_eArgError, "step can't be 0");
    }

    if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
	return ruby_num_interval_step_size(b, e, step, EXCL(range));
    }
    return Qnil;
}
Пример #29
0
int
rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
{
    VALUE b, e;
    int excl;

    if (rb_obj_is_kind_of(range, rb_cRange)) {
	b = RANGE_BEG(range);
	e = RANGE_END(range);
	excl = EXCL(range);
    }
    else {
	if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
	if (!rb_respond_to(range, id_end)) return (int)Qfalse;
	b = rb_funcall(range, id_beg, 0);
	e = rb_funcall(range, id_end, 0);
	excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
    }
    *begp = b;
    *endp = e;
    *exclp = excl;
    return (int)Qtrue;
}
Пример #30
0
static void
range_each_func(VALUE range, rb_block_call_func *func, VALUE arg)
{
    int c;
    VALUE b = RANGE_BEG(range);
    VALUE e = RANGE_END(range);
    VALUE v = b;

    if (EXCL(range)) {
	while (r_lt(v, e)) {
	    (*func) (v, arg, 0, 0, 0);
	    v = rb_funcall(v, id_succ, 0, 0);
	}
    }
    else {
	while ((c = r_le(v, e)) != Qfalse) {
	    (*func) (v, arg, 0, 0, 0);
	    if (c == (int)INT2FIX(0))
		break;
	    v = rb_funcall(v, id_succ, 0, 0);
	}
    }
}