1998-01-16 07:13:05 -05:00
|
|
|
/************************************************
|
|
|
|
|
|
|
|
range.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
$Date$
|
|
|
|
created at: Thu Aug 19 17:46:47 JST 1993
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
Copyright (C) 1993-1998 Yukihiro Matsumoto
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
************************************************/
|
|
|
|
|
|
|
|
#include "ruby.h"
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE rb_cRange;
|
|
|
|
static ID id_upto, id_cmp;
|
|
|
|
static ID id_beg, id_end;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static VALUE
|
|
|
|
range_check(args)
|
|
|
|
VALUE *args;
|
|
|
|
{
|
|
|
|
rb_funcall(args[0], id_cmp, 1, args[1]);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_failed()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "bad value for range");
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
static VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
range_s_new(klass, beg, end)
|
|
|
|
VALUE klass, beg, end;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
VALUE obj;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
|
|
|
|
VALUE args[2];
|
|
|
|
|
|
|
|
args[0] = beg; args[1] = end;
|
|
|
|
rb_rescue(range_check, (VALUE)args, range_failed, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
obj = rb_obj_alloc(klass);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ivar_set(obj, id_beg, beg);
|
|
|
|
rb_ivar_set(obj, id_end, end);
|
|
|
|
rb_obj_call_init(obj);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_range_new(beg, end)
|
|
|
|
VALUE beg, end;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
return range_s_new(rb_cRange, beg, end);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_eqq(rng, obj)
|
|
|
|
VALUE rng, obj;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE beg, end;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
beg = rb_ivar_get(rng, id_beg);
|
|
|
|
end = rb_ivar_get(rng, id_end);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (FIXNUM_P(beg) && FIXNUM_P(obj) && FIXNUM_P(end)) {
|
|
|
|
if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
|
|
|
|
return Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj)) &&
|
|
|
|
RTEST(rb_funcall(end, rb_intern(">="), 1, obj))) {
|
|
|
|
return Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct upto_data {
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE beg;
|
|
|
|
VALUE end;
|
1998-01-16 07:13:05 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_upto(data)
|
|
|
|
struct upto_data *data;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
return rb_funcall(data->beg, id_upto, 1, data->end);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_each(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
VALUE b, e;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
b = rb_ivar_get(obj, id_beg);
|
|
|
|
e = rb_ivar_get(obj, id_end);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_fix_upto(b, e);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
struct upto_data data;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
data.beg = b;
|
|
|
|
data.end = e;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_iterate(range_upto, (VALUE)&data, rb_yield, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_first(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
VALUE b;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
b = rb_ivar_get(obj, id_beg);
|
1998-01-16 07:13:05 -05:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_last(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
VALUE e;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
e = rb_ivar_get(obj, id_end);
|
1998-01-16 07:13:05 -05:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_range_beg_end(range, begp, endp)
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE range;
|
|
|
|
int *begp, *endp;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE beg, end;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
beg = rb_ivar_get(range, id_beg); *begp = NUM2INT(beg);
|
|
|
|
end = rb_ivar_get(range, id_end); *endp = NUM2INT(end);
|
|
|
|
return Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_to_s(range)
|
|
|
|
VALUE range;
|
|
|
|
{
|
|
|
|
VALUE str, str2;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
str = rb_obj_as_string(rb_ivar_get(range, id_beg));
|
|
|
|
str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
|
|
|
|
rb_str_cat(str, "..", 2);
|
|
|
|
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_inspect(range)
|
|
|
|
VALUE range;
|
|
|
|
{
|
|
|
|
VALUE str, str2;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
str = rb_inspect(rb_ivar_get(range, id_beg));
|
|
|
|
str2 = rb_inspect(rb_ivar_get(range, id_end));
|
|
|
|
rb_str_cat(str, "..", 2);
|
|
|
|
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
range_length(rng)
|
|
|
|
VALUE rng;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE beg, end;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE size;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
beg = rb_ivar_get(rng, id_beg);
|
|
|
|
end = rb_ivar_get(rng, id_end);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (RTEST(rb_funcall(beg, '>', 1, end))) {
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
if (!rb_obj_is_kind_of(beg, rb_cNumeric)) {
|
|
|
|
return rb_enum_length(rng);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
size = rb_funcall(end, '-', 1, beg);
|
1998-01-16 07:13:05 -05:00
|
|
|
size = rb_funcall(size, '+', 1, INT2FIX(1));
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Init_Range()
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_cRange = rb_define_class("Range", rb_cObject);
|
|
|
|
rb_include_module(rb_cRange, rb_mEnumerable);
|
|
|
|
rb_define_singleton_method(rb_cRange, "new", range_s_new, 2);
|
|
|
|
rb_define_method(rb_cRange, "===", range_eqq, 1);
|
|
|
|
rb_define_method(rb_cRange, "each", range_each, 0);
|
|
|
|
rb_define_method(rb_cRange, "first", range_first, 0);
|
|
|
|
rb_define_method(rb_cRange, "last", range_last, 0);
|
|
|
|
rb_define_method(rb_cRange, "begin", range_first, 0);
|
|
|
|
rb_define_method(rb_cRange, "end", range_last, 0);
|
|
|
|
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
|
|
|
|
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cRange, "length", range_length, 0);
|
|
|
|
rb_define_method(rb_cRange, "size", range_length, 0);
|
|
|
|
|
|
|
|
id_upto = rb_intern("upto");
|
|
|
|
id_cmp = rb_intern("<=>");
|
|
|
|
id_beg = rb_intern("begin");
|
|
|
|
id_end = rb_intern("end");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|