16
16
static ID id_cmp, id_succ, id_beg, id_end, id_excl;
18
#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
19
#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
18
#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
19
#define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
20
#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
22
#define EXCL(r) RTEST(RANGE_EXCL(r))
23
#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
50
54
SET_EXCL(range, exclude_end);
51
rb_ivar_set(range, id_beg, beg);
52
rb_ivar_set(range, id_end, end);
55
RSTRUCT(range)->as.ary[0] = beg;
56
RSTRUCT(range)->as.ary[1] = end;
78
82
rb_scan_args(argc, argv, "21", &beg, &end, &flags);
79
83
/* Ranges are immutable, so that they should be initialized only once. */
80
if (rb_ivar_defined(range, id_beg)) {
84
if (RANGE_EXCL(range) != Qnil) {
81
85
rb_name_error(rb_intern("initialize"), "`initialize' called twice");
83
87
range_init(range, beg, end, RTEST(flags));
121
125
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
124
if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
128
if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
126
if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
130
if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
129
133
if (EXCL(range) != EXCL(obj))
183
187
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
186
if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
190
if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
188
if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
192
if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
191
195
if (EXCL(range) != EXCL(obj))
290
300
RETURN_ENUMERATOR(range, argc, argv);
292
b = rb_ivar_get(range, id_beg);
293
e = rb_ivar_get(range, id_end);
302
b = RANGE_BEG(range);
303
e = RANGE_END(range);
294
304
if (rb_scan_args(argc, argv, "01", &step) == 0) {
295
305
step = INT2FIX(1);
298
unit = NUM2LONG(step);
308
else if (FIXNUM_P(step)) {
309
unit = NUM2LONG(step);
312
VALUE tmp = rb_to_int(step);
313
unit = rb_cmpint(tmp, step, INT2FIX(0));
300
317
rb_raise(rb_eArgError, "step can't be negative");
303
320
rb_raise(rb_eArgError, "step can't be 0");
304
if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
321
if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
305
322
long end = FIX2LONG(e);
308
325
if (!EXCL(range))
310
for (i = FIX2LONG(b); i < end; i += unit) {
311
329
rb_yield(LONG2NUM(i));
330
if (i + unit < i) break;
315
335
VALUE tmp = rb_check_string_type(b);
317
337
if (!NIL_P(tmp)) {
338
VALUE args[2], iter[2];
323
342
args[1] = EXCL(range) ? Qtrue : Qfalse;
343
iter[0] = INT2FIX(1);
326
345
rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
328
347
else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
383
402
RETURN_ENUMERATOR(range, 0, 0);
385
beg = rb_ivar_get(range, id_beg);
386
end = rb_ivar_get(range, id_end);
404
beg = RANGE_BEG(range);
405
end = RANGE_END(range);
388
407
if (!rb_respond_to(beg, id_succ)) {
389
408
rb_raise(rb_eTypeError, "can't iterate from %s",
443
range_last(VALUE range)
445
return rb_ivar_get(range, id_end);
460
range_end(VALUE range)
462
return RANGE_END(range);
467
first_i(VALUE i, VALUE *ary)
469
long n = NUM2LONG(ary[0]);
474
rb_ary_push(ary[1], i);
483
* rng.first(n) => an_array
485
* Returns the first object in <i>rng</i>, or the first +n+ elements.
489
range_first(int argc, VALUE *argv, VALUE range)
493
if (argc == 0) return RANGE_BEG(range);
495
rb_scan_args(argc, argv, "1", &n);
497
ary[1] = rb_ary_new2(NUM2LONG(n));
498
rb_block_call(range, rb_intern("each"), 0, 0, first_i, (VALUE)ary);
507
* rng.last(n) => an_array
509
* Returns the last object in <i>rng</i>, or the last +n+ elements.
513
range_last(int argc, VALUE *argv, VALUE range)
515
VALUE rb_ary_last(int, VALUE *, VALUE);
517
if (argc == 0) return RANGE_END(range);
518
return rb_ary_last(argc, argv, rb_Array(range));
464
538
return rb_call_super(0, 0);
467
VALUE b = rb_ivar_get(range, id_beg);
468
VALUE e = rb_ivar_get(range, id_end);
541
VALUE b = RANGE_BEG(range);
542
VALUE e = RANGE_END(range);
469
543
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
471
545
if (c > 0 || (c == 0 && EXCL(range)))
490
564
range_max(VALUE range)
492
VALUE e = rb_ivar_get(range, id_end);
566
VALUE e = RANGE_END(range);
493
567
int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);
495
569
if (rb_block_given_p() || (EXCL(range) && !ip)) {
496
570
return rb_call_super(0, 0);
499
VALUE b = rb_ivar_get(range, id_beg);
573
VALUE b = RANGE_BEG(range);
500
574
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
581
str = rb_obj_as_string(rb_ivar_get(range, id_beg));
582
str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
655
str = rb_obj_as_string(RANGE_BEG(range));
656
str2 = rb_obj_as_string(RANGE_END(range));
583
657
str = rb_str_dup(str);
584
658
rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
585
659
rb_str_append(str, str2);
619
str = rb_inspect(rb_ivar_get(range, id_beg));
620
str2 = rb_inspect(rb_ivar_get(range, id_end));
680
str = rb_inspect(RANGE_BEG(range));
681
str2 = rb_inspect(RANGE_END(range));
621
682
str = rb_str_dup(str);
622
683
rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
623
684
rb_str_append(str, str2);
669
730
range_include(VALUE range, VALUE val)
671
VALUE beg = rb_ivar_get(range, id_beg);
672
VALUE end = rb_ivar_get(range, id_end);
732
VALUE beg = RANGE_BEG(range);
733
VALUE end = RANGE_END(range);
673
734
int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
674
735
rb_obj_is_kind_of(beg, rb_cNumeric) ||
675
736
rb_obj_is_kind_of(end, rb_cNumeric);
791
range_dumper(VALUE range)
794
NEWOBJ(m, struct RObject);
795
OBJSETUP(m, rb_cObject, T_OBJECT);
799
rb_ivar_set(v, id_excl, RANGE_EXCL(range));
800
rb_ivar_set(v, id_beg, RANGE_BEG(range));
801
rb_ivar_set(v, id_end, RANGE_END(range));
806
range_loader(VALUE range, VALUE obj)
808
if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
809
rb_raise(rb_eTypeError, "not a dumped range object");
812
RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
813
RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
814
RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
819
range_alloc(VALUE klass)
821
/* rb_struct_alloc_noinit itself should not be used because
822
* rb_marshal_define_compat uses equality of allocaiton function */
823
return rb_struct_alloc_noinit(klass);
730
826
/* A <code>Range</code> represents an interval---a set of values with a
731
827
* start and an end. Ranges may be constructed using the
785
rb_cRange = rb_define_class("Range", rb_cObject);
881
id_cmp = rb_intern("<=>");
882
id_succ = rb_intern("succ");
883
id_beg = rb_intern("begin");
884
id_end = rb_intern("end");
885
id_excl = rb_intern("excl");
887
rb_cRange = rb_struct_define_without_accessor(
888
"Range", rb_cObject, range_alloc,
889
"begin", "end", "excl", NULL);
786
891
rb_include_module(rb_cRange, rb_mEnumerable);
892
rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
787
893
rb_define_method(rb_cRange, "initialize", range_initialize, -1);
788
894
rb_define_method(rb_cRange, "==", range_eq, 1);
789
895
rb_define_method(rb_cRange, "===", range_eqq, 1);
791
897
rb_define_method(rb_cRange, "hash", range_hash, 0);
792
898
rb_define_method(rb_cRange, "each", range_each, 0);
793
899
rb_define_method(rb_cRange, "step", range_step, -1);
794
rb_define_method(rb_cRange, "first", range_first, 0);
795
rb_define_method(rb_cRange, "last", range_last, 0);
796
rb_define_method(rb_cRange, "begin", range_first, 0);
797
rb_define_method(rb_cRange, "end", range_last, 0);
900
rb_define_method(rb_cRange, "begin", range_begin, 0);
901
rb_define_method(rb_cRange, "end", range_end, 0);
902
rb_define_method(rb_cRange, "first", range_first, -1);
903
rb_define_method(rb_cRange, "last", range_last, -1);
798
904
rb_define_method(rb_cRange, "min", range_min, 0);
799
905
rb_define_method(rb_cRange, "max", range_max, 0);
800
906
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
801
907
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
802
rb_define_method(rb_cRange, "to_splat", range_to_splat, 0);
804
909
rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
806
911
rb_define_method(rb_cRange, "member?", range_include, 1);
807
912
rb_define_method(rb_cRange, "include?", range_include, 1);
808
913
rb_define_method(rb_cRange, "cover?", range_cover, 1);
810
id_cmp = rb_intern("<=>");
811
id_succ = rb_intern("succ");
812
id_beg = rb_intern("begin");
813
id_end = rb_intern("end");
814
id_excl = rb_intern("excl");