mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
1.4.0
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fcd020c830
commit
65a5162550
156 changed files with 21888 additions and 18301 deletions
199
range.c
199
range.c
|
@ -6,15 +6,17 @@
|
|||
$Date$
|
||||
created at: Thu Aug 19 17:46:47 JST 1993
|
||||
|
||||
Copyright (C) 1993-1998 Yukihiro Matsumoto
|
||||
Copyright (C) 1993-1999 Yukihiro Matsumoto
|
||||
|
||||
************************************************/
|
||||
|
||||
#include "ruby.h"
|
||||
|
||||
VALUE rb_cRange;
|
||||
static ID id_upto, id_cmp;
|
||||
static ID id_beg, id_end;
|
||||
static ID id_cmp, id_beg, id_end;
|
||||
|
||||
#define EXCL(r) FL_TEST((r), FL_USER1)
|
||||
#define SET_EXCL(r) FL_SET((r), FL_USER1)
|
||||
|
||||
static VALUE
|
||||
range_check(args)
|
||||
|
@ -31,92 +33,119 @@ range_failed()
|
|||
}
|
||||
|
||||
static VALUE
|
||||
range_s_new(klass, beg, end)
|
||||
range_new(klass, beg, end, exclude_end)
|
||||
VALUE klass, beg, end;
|
||||
int exclude_end;
|
||||
{
|
||||
VALUE obj;
|
||||
VALUE args[2];
|
||||
|
||||
args[0] = beg; args[1] = end;
|
||||
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);
|
||||
}
|
||||
|
||||
obj = rb_obj_alloc(klass);
|
||||
if (exclude_end) {
|
||||
SET_EXCL(obj);
|
||||
}
|
||||
|
||||
rb_ivar_set(obj, id_beg, beg);
|
||||
rb_ivar_set(obj, id_end, end);
|
||||
rb_obj_call_init(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_range_new(beg, end)
|
||||
rb_range_new(beg, end, exclude_end)
|
||||
VALUE beg, end;
|
||||
int exclude_end;
|
||||
{
|
||||
return range_s_new(rb_cRange, beg, end);
|
||||
return range_new(rb_cRange, beg, end, exclude_end);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_eqq(rng, obj)
|
||||
VALUE rng, obj;
|
||||
range_s_new(argc, argv, klass)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE klass;
|
||||
{
|
||||
VALUE beg, end, flag;
|
||||
|
||||
rb_scan_args(argc, argv, "21", &beg, &end, &flag);
|
||||
return range_new(klass, beg, end, RTEST(flag));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_exclude_end_p(range)
|
||||
VALUE range;
|
||||
{
|
||||
return EXCL(range)?Qtrue:Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_eqq(range, obj)
|
||||
VALUE range, obj;
|
||||
{
|
||||
VALUE beg, end;
|
||||
|
||||
beg = rb_ivar_get(rng, id_beg);
|
||||
end = rb_ivar_get(rng, id_end);
|
||||
beg = rb_ivar_get(range, id_beg);
|
||||
end = rb_ivar_get(range, id_end);
|
||||
|
||||
if (FIXNUM_P(beg) && FIXNUM_P(obj) && FIXNUM_P(end)) {
|
||||
if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
|
||||
return Qtrue;
|
||||
if (NUM2LONG(beg) <= NUM2LONG(obj)) {
|
||||
if (EXCL(range)) {
|
||||
if (NUM2LONG(obj) < NUM2LONG(end)) return Qtrue;
|
||||
}
|
||||
else {
|
||||
if (NUM2LONG(obj) <= NUM2LONG(end)) return Qtrue;
|
||||
}
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
else {
|
||||
if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj)) &&
|
||||
RTEST(rb_funcall(end, rb_intern(">="), 1, obj))) {
|
||||
return Qtrue;
|
||||
else if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj))) {
|
||||
if (EXCL(range)) {
|
||||
if (RTEST(rb_funcall(end, rb_intern(">"), 1, obj)))
|
||||
return Qtrue;
|
||||
}
|
||||
else {
|
||||
if (RTEST(rb_funcall(end, rb_intern(">="), 1, obj)))
|
||||
return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
struct upto_data {
|
||||
VALUE beg;
|
||||
VALUE end;
|
||||
};
|
||||
|
||||
static VALUE
|
||||
range_upto(data)
|
||||
struct upto_data *data;
|
||||
{
|
||||
return rb_funcall(data->beg, id_upto, 1, data->end);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_each(obj)
|
||||
VALUE obj;
|
||||
range_each(range)
|
||||
VALUE range;
|
||||
{
|
||||
VALUE b, e;
|
||||
|
||||
b = rb_ivar_get(obj, id_beg);
|
||||
e = rb_ivar_get(obj, id_end);
|
||||
b = rb_ivar_get(range, id_beg);
|
||||
e = rb_ivar_get(range, id_end);
|
||||
|
||||
if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
|
||||
rb_fix_upto(b, e);
|
||||
if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
|
||||
long end = FIX2LONG(e);
|
||||
long i;
|
||||
|
||||
if (!EXCL(range)) end += 1;
|
||||
for (i=FIX2LONG(b); i<end; i++) {
|
||||
rb_yield(INT2NUM(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct upto_data data;
|
||||
else { /* generic each */
|
||||
VALUE v = b;
|
||||
ID le = EXCL(range)?'<':rb_intern("<=");
|
||||
ID succ = rb_intern("succ");
|
||||
|
||||
data.beg = b;
|
||||
data.end = e;
|
||||
|
||||
rb_iterate(range_upto, (VALUE)&data, rb_yield, 0);
|
||||
while (rb_funcall(v, le, 1, e)) {
|
||||
rb_yield(v);
|
||||
v = rb_funcall(v, succ, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
return range;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -140,17 +169,54 @@ range_last(obj)
|
|||
}
|
||||
|
||||
VALUE
|
||||
rb_range_beg_end(range, begp, endp)
|
||||
rb_range_beg_len(range, begp, lenp, len, err)
|
||||
VALUE range;
|
||||
int *begp, *endp;
|
||||
long *begp, *lenp;
|
||||
long len;
|
||||
int err;
|
||||
{
|
||||
VALUE beg, end;
|
||||
long beg, end, b, e;
|
||||
|
||||
if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
|
||||
|
||||
beg = rb_ivar_get(range, id_beg); *begp = NUM2INT(beg);
|
||||
end = rb_ivar_get(range, id_end); *endp = NUM2INT(end);
|
||||
beg = b = NUM2LONG(rb_ivar_get(range, id_beg));
|
||||
end = e = NUM2LONG(rb_ivar_get(range, id_end));
|
||||
|
||||
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 || (!EXCL(range) && end == len))
|
||||
end = len;
|
||||
}
|
||||
if (end < 0) {
|
||||
end += len;
|
||||
if (end < 0) {
|
||||
if (beg == 0 && end == -1 && !EXCL(range)) {
|
||||
len = 0;
|
||||
goto length_set;
|
||||
}
|
||||
goto out_of_range;
|
||||
}
|
||||
}
|
||||
len = end - beg;
|
||||
if (!EXCL(range)) len++; /* include end point */
|
||||
if (len < 0) goto out_of_range;
|
||||
|
||||
length_set:
|
||||
*begp = beg;
|
||||
*lenp = len;
|
||||
|
||||
return Qtrue;
|
||||
|
||||
out_of_range:
|
||||
if (err) {
|
||||
rb_raise(rb_eIndexError, "%d..%s%d out of range",
|
||||
b, EXCL(range)?".":"", e);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -161,7 +227,7 @@ range_to_s(range)
|
|||
|
||||
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, "...", EXCL(range)?3:2);
|
||||
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
|
||||
return str;
|
||||
|
@ -175,30 +241,40 @@ range_inspect(range)
|
|||
|
||||
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, "...", EXCL(range)?3:2);
|
||||
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_length(rng)
|
||||
VALUE rng;
|
||||
range_length(range)
|
||||
VALUE range;
|
||||
{
|
||||
VALUE beg, end;
|
||||
VALUE size;
|
||||
|
||||
beg = rb_ivar_get(rng, id_beg);
|
||||
end = rb_ivar_get(rng, id_end);
|
||||
beg = rb_ivar_get(range, id_beg);
|
||||
end = rb_ivar_get(range, id_end);
|
||||
|
||||
if (RTEST(rb_funcall(beg, '>', 1, end))) {
|
||||
return INT2FIX(0);
|
||||
}
|
||||
if (FIXNUM_P(beg) && FIXNUM_P(end)) {
|
||||
if (EXCL(range)) {
|
||||
return INT2NUM(NUM2LONG(end) - NUM2LONG(beg));
|
||||
}
|
||||
else {
|
||||
return INT2NUM(NUM2LONG(end) - NUM2LONG(beg) + 1);
|
||||
}
|
||||
}
|
||||
if (!rb_obj_is_kind_of(beg, rb_cNumeric)) {
|
||||
return rb_enum_length(rng);
|
||||
return rb_enum_length(range);
|
||||
}
|
||||
size = rb_funcall(end, '-', 1, beg);
|
||||
size = rb_funcall(size, '+', 1, INT2FIX(1));
|
||||
if (!EXCL(range)) {
|
||||
size = rb_funcall(size, '+', 1, INT2FIX(1));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -208,7 +284,7 @@ Init_Range()
|
|||
{
|
||||
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_singleton_method(rb_cRange, "new", range_s_new, -1);
|
||||
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);
|
||||
|
@ -218,10 +294,11 @@ Init_Range()
|
|||
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, "exclude_end?", range_exclude_end_p, 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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue