1 /**********************************************************************
6 created at: Thu Aug 19 17:46:47 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
10 **********************************************************************/
12 #include "ruby/ruby.h"
13 #include "ruby/encoding.h"
16 static ID id_cmp
, id_succ
, id_beg
, id_end
, id_excl
;
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)
28 rb_raise(rb_eArgError
, "bad value for range");
29 return Qnil
; /* dummy */
33 range_check(VALUE
*args
)
35 return rb_funcall(args
[0], id_cmp
, 1, args
[1]);
39 range_init(VALUE range
, VALUE beg
, VALUE end
, int exclude_end
)
46 if (!FIXNUM_P(beg
) || !FIXNUM_P(end
)) {
49 v
= rb_rescue(range_check
, (VALUE
)args
, range_failed
, 0);
54 SET_EXCL(range
, exclude_end
);
55 RSTRUCT(range
)->as
.ary
[0] = beg
;
56 RSTRUCT(range
)->as
.ary
[1] = end
;
60 rb_range_new(VALUE beg
, VALUE end
, int exclude_end
)
62 VALUE range
= rb_obj_alloc(rb_cRange
);
64 range_init(range
, beg
, end
, exclude_end
);
70 * Range.new(start, end, exclusive=false) => range
72 * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
73 * parameter is omitted or is <code>false</code>, the <i>range</i> will include
74 * the end object; otherwise, it will be excluded.
78 range_initialize(int argc
, VALUE
*argv
, VALUE range
)
80 VALUE beg
, end
, flags
;
82 rb_scan_args(argc
, argv
, "21", &beg
, &end
, &flags
);
83 /* Ranges are immutable, so that they should be initialized only once. */
84 if (RANGE_EXCL(range
) != Qnil
) {
85 rb_name_error(rb_intern("initialize"), "`initialize' called twice");
87 range_init(range
, beg
, end
, RTEST(flags
));
94 * rng.exclude_end? => true or false
96 * Returns <code>true</code> if <i>rng</i> excludes its end value.
100 range_exclude_end_p(VALUE range
)
102 return EXCL(range
) ? Qtrue
: Qfalse
;
108 * rng == obj => true or false
110 * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
111 * beginning and end items (by comparing them with <code>==</code>), and has
112 * the same #exclude_end? setting as <i>rng</t>.
114 * (0..2) == (0..2) #=> true
115 * (0..2) == Range.new(0,2) #=> true
116 * (0..2) == (0...2) #=> false
121 range_eq(VALUE range
, VALUE obj
)
125 if (!rb_obj_is_instance_of(obj
, rb_obj_class(range
)))
128 if (!rb_equal(RANGE_BEG(range
), RANGE_BEG(obj
)))
130 if (!rb_equal(RANGE_END(range
), RANGE_END(obj
)))
133 if (EXCL(range
) != EXCL(obj
))
140 r_lt(VALUE a
, VALUE b
)
142 VALUE r
= rb_funcall(a
, id_cmp
, 1, b
);
146 if (rb_cmpint(r
, a
, b
) < 0)
152 r_le(VALUE a
, VALUE b
)
155 VALUE r
= rb_funcall(a
, id_cmp
, 1, b
);
159 c
= rb_cmpint(r
, a
, b
);
170 * rng.eql?(obj) => true or false
172 * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
173 * beginning and end items (by comparing them with #eql?), and has the same
174 * #exclude_end? setting as <i>rng</i>.
176 * (0..2) == (0..2) #=> true
177 * (0..2) == Range.new(0,2) #=> true
178 * (0..2) == (0...2) #=> false
183 range_eql(VALUE range
, VALUE obj
)
187 if (!rb_obj_is_instance_of(obj
, rb_obj_class(range
)))
190 if (!rb_eql(RANGE_BEG(range
), RANGE_BEG(obj
)))
192 if (!rb_eql(RANGE_END(range
), RANGE_END(obj
)))
195 if (EXCL(range
) != EXCL(obj
))
205 * Generate a hash value such that two ranges with the same start and
206 * end points, and the same value for the "exclude end" flag, generate
207 * the same hash value.
211 range_hash(VALUE range
)
213 long hash
= EXCL(range
);
216 v
= rb_hash(RANGE_BEG(range
));
218 v
= rb_hash(RANGE_END(range
));
220 hash
^= EXCL(range
) << 24;
222 return LONG2FIX(hash
);
226 range_each_func(VALUE range
, VALUE (*func
) (VALUE
, void *), void *arg
)
229 VALUE b
= RANGE_BEG(range
);
230 VALUE e
= RANGE_END(range
);
236 v
= rb_funcall(v
, id_succ
, 0, 0);
240 while (RTEST(c
= r_le(v
, e
))) {
244 v
= rb_funcall(v
, id_succ
, 0, 0);
250 step_i(VALUE i
, void *arg
)
254 if (FIXNUM_P(iter
[0])) {
255 iter
[0] -= INT2FIX(1) & ~FIXNUM_FLAG
;
258 iter
[0] = rb_funcall(iter
[0], '-', 1, INT2FIX(1));
260 if (iter
[0] == INT2FIX(0)) {
269 * rng.step(n=1) {| obj | block } => rng
271 * Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
272 * the range contains numbers, <i>n</i> is added for each iteration. Otherwise
273 * <code>step</code> invokes <code>succ</code> to iterate through range
274 * elements. The following code uses class <code>Xs</code>, which is defined
275 * in the class-level documentation.
277 * range = Xs.new(1)..Xs.new(10)
278 * range.step(2) {|x| puts x}
279 * range.step(3) {|x| puts x}
296 range_step(int argc
, VALUE
*argv
, VALUE range
)
298 VALUE b
, e
, step
, tmp
;
300 RETURN_ENUMERATOR(range
, argc
, argv
);
302 b
= RANGE_BEG(range
);
303 e
= RANGE_END(range
);
308 rb_scan_args(argc
, argv
, "01", &step
);
309 if (!rb_obj_is_kind_of(step
, rb_cNumeric
)) {
310 step
= rb_to_int(step
);
312 if (rb_funcall(step
, '<', 1, INT2FIX(0))) {
313 rb_raise(rb_eArgError
, "step can't be negative");
315 else if (!rb_funcall(step
, '>', 1, INT2FIX(0))) {
316 rb_raise(rb_eArgError
, "step can't be 0");
320 if (FIXNUM_P(b
) && FIXNUM_P(e
) && FIXNUM_P(step
)) { /* fixnums are special */
321 long end
= FIX2LONG(e
);
322 long i
, unit
= FIX2LONG(step
);
328 rb_yield(LONG2NUM(i
));
329 if (i
+ unit
< i
) break;
334 else if (rb_obj_is_kind_of(b
, rb_cNumeric
) ||
335 !NIL_P(rb_check_to_integer(b
, "to_int")) ||
336 !NIL_P(rb_check_to_integer(e
, "to_int"))) {
337 ID op
= EXCL(range
) ? '<' : rb_intern("<=");
339 while (RTEST(rb_funcall(b
, op
, 1, e
))) {
341 b
= rb_funcall(b
, '+', 1, step
);
345 tmp
= rb_check_string_type(b
);
348 VALUE args
[2], iter
[2];
352 args
[1] = EXCL(range
) ? Qtrue
: Qfalse
;
353 iter
[0] = INT2FIX(1);
355 rb_block_call(b
, rb_intern("upto"), 2, args
, step_i
, (VALUE
)iter
);
360 if (!rb_respond_to(b
, id_succ
)) {
361 rb_raise(rb_eTypeError
, "can't iterate from %s",
362 rb_obj_classname(b
));
364 args
[0] = INT2FIX(1);
366 range_each_func(range
, step_i
, args
);
373 each_i(VALUE v
, void *arg
)
381 * rng.each {| i | block } => rng
383 * Iterates over the elements <i>rng</i>, passing each in turn to the
384 * block. You can only iterate if the start object of the range
385 * supports the +succ+ method (which means that you can't iterate over
386 * ranges of +Float+ objects).
388 * (10..15).each do |n|
398 range_each(VALUE range
)
402 RETURN_ENUMERATOR(range
, 0, 0);
404 beg
= RANGE_BEG(range
);
405 end
= RANGE_END(range
);
407 if (!rb_respond_to(beg
, id_succ
)) {
408 rb_raise(rb_eTypeError
, "can't iterate from %s",
409 rb_obj_classname(beg
));
411 if (FIXNUM_P(beg
) && FIXNUM_P(end
)) { /* fixnums are special */
412 long lim
= FIX2LONG(end
);
417 for (i
= FIX2LONG(beg
); i
< lim
; i
++) {
418 rb_yield(LONG2FIX(i
));
421 else if (TYPE(beg
) == T_STRING
) {
425 args
[1] = EXCL(range
) ? Qtrue
: Qfalse
;
426 rb_block_call(beg
, rb_intern("upto"), 2, args
, rb_yield
, 0);
429 range_each_func(range
, each_i
, NULL
);
438 * Returns the first object in <i>rng</i>.
442 range_begin(VALUE range
)
444 return RANGE_BEG(range
);
452 * Returns the object that defines the end of <i>rng</i>.
455 * (1...10).end #=> 10
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
));
525 * rng.min {| a,b | block } => obj
527 * Returns the minimum value in <i>rng</i>. The second uses
528 * the block to compare values. Returns nil if the first
529 * value in range is larger than the last value.
535 range_min(VALUE range
)
537 if (rb_block_given_p()) {
538 return rb_call_super(0, 0);
541 VALUE b
= RANGE_BEG(range
);
542 VALUE e
= RANGE_END(range
);
543 int c
= rb_cmpint(rb_funcall(b
, id_cmp
, 1, e
), b
, e
);
545 if (c
> 0 || (c
== 0 && EXCL(range
)))
554 * rng.max {| a,b | block } => obj
556 * Returns the maximum value in <i>rng</i>. The second uses
557 * the block to compare values. Returns nil if the first
558 * value in range is larger than the last value.
564 range_max(VALUE range
)
566 VALUE e
= RANGE_END(range
);
567 int ip
= FIXNUM_P(e
) || rb_obj_is_kind_of(e
, rb_cInteger
);
569 if (rb_block_given_p() || (EXCL(range
) && !ip
)) {
570 return rb_call_super(0, 0);
573 VALUE b
= RANGE_BEG(range
);
574 int c
= rb_cmpint(rb_funcall(b
, id_cmp
, 1, e
), b
, e
);
579 if (c
== 0) return Qnil
;
581 return LONG2NUM(FIX2LONG(e
) - 1);
583 return rb_funcall(e
, '-', 1, INT2FIX(1));
590 rb_range_beg_len(VALUE range
, long *begp
, long *lenp
, long len
, int err
)
595 if (rb_obj_is_kind_of(range
, rb_cRange
)) {
596 b
= RANGE_BEG(range
);
597 e
= RANGE_END(range
);
601 if (!rb_respond_to(range
, id_beg
)) return Qfalse
;
602 if (!rb_respond_to(range
, id_end
)) return Qfalse
;
603 b
= rb_funcall(range
, id_beg
, 0);
604 e
= rb_funcall(range
, id_end
, 0);
605 excl
= RTEST(rb_funcall(range
, rb_intern("exclude_end?"), 0));
615 if (err
== 0 || err
== 2) {
624 end
++; /* include end point */
635 rb_raise(rb_eRangeError
, "%ld..%s%ld out of range",
636 b
, excl
? "." : "", e
);
645 * Convert this range object to a printable form.
649 range_to_s(VALUE range
)
653 str
= rb_obj_as_string(RANGE_BEG(range
));
654 str2
= rb_obj_as_string(RANGE_END(range
));
655 str
= rb_str_dup(str
);
656 rb_str_cat(str
, "...", EXCL(range
) ? 3 : 2);
657 rb_str_append(str
, str2
);
658 OBJ_INFECT(str
, str2
);
665 * rng.inspect => string
667 * Convert this range object to a printable form (using
668 * <code>inspect</code> to convert the start and end
674 range_inspect(VALUE range
)
678 str
= rb_inspect(RANGE_BEG(range
));
679 str2
= rb_inspect(RANGE_END(range
));
680 str
= rb_str_dup(str
);
681 rb_str_cat(str
, "...", EXCL(range
) ? 3 : 2);
682 rb_str_append(str
, str2
);
683 OBJ_INFECT(str
, str2
);
690 * rng === obj => true or false
692 * Returns <code>true</code> if <i>obj</i> is an element of
693 * <i>rng</i>, <code>false</code> otherwise. Conveniently,
694 * <code>===</code> is the comparison operator used by
695 * <code>case</code> statements.
698 * when 1..50 then print "low\n"
699 * when 51..75 then print "medium\n"
700 * when 76..100 then print "high\n"
709 range_eqq(VALUE range
, VALUE val
)
711 return rb_funcall(range
, rb_intern("include?"), 1, val
);
717 * rng.member?(val) => true or false
718 * rng.include?(val) => true or false
720 * Returns <code>true</code> if <i>obj</i> is an element of
721 * <i>rng</i>, <code>false</code> otherwise. If beg and end are
722 * numeric, comparison is done according magnitude of values.
724 * ("a".."z").include?("g") # => true
725 * ("a".."z").include?("A") # => false
729 range_include(VALUE range
, VALUE val
)
731 VALUE beg
= RANGE_BEG(range
);
732 VALUE end
= RANGE_END(range
);
733 int nv
= FIXNUM_P(beg
) || FIXNUM_P(end
) ||
734 rb_obj_is_kind_of(beg
, rb_cNumeric
) ||
735 rb_obj_is_kind_of(end
, rb_cNumeric
);
738 !NIL_P(rb_check_to_integer(beg
, "to_int")) ||
739 !NIL_P(rb_check_to_integer(end
, "to_int"))) {
740 if (r_le(beg
, val
)) {
752 else if (TYPE(beg
) == T_STRING
&& TYPE(end
) == T_STRING
&&
753 RSTRING_LEN(beg
) == 1 && RSTRING_LEN(end
) == 1) {
754 if (NIL_P(val
)) return Qfalse
;
755 if (TYPE(val
) == T_STRING
) {
756 if (RSTRING_LEN(val
) == 0 || RSTRING_LEN(val
) > 1)
759 char b
= RSTRING_PTR(beg
)[0];
760 char e
= RSTRING_PTR(end
)[0];
761 char v
= RSTRING_PTR(val
)[0];
763 if (ISASCII(b
) && ISASCII(e
) && ISASCII(v
)) {
764 if (b
<= v
&& v
< e
) return Qtrue
;
765 if (!EXCL(range
) && v
== e
) return Qtrue
;
771 /* TODO: ruby_frame->this_func = rb_intern("include?"); */
772 return rb_call_super(1, &val
);
778 * rng.cover?(val) => true or false
780 * Returns <code>true</code> if <i>obj</i> is between beg and end,
781 * i.e <code>beg <= obj <= end</code> (or <i>end</i> exclusive when
782 * <code>exclude_end?</code> is true).
784 * ("a".."z").cover?("c") #=> true
785 * ("a".."z").cover?("5") #=> false
789 range_cover(VALUE range
, VALUE val
)
793 beg
= RANGE_BEG(range
);
794 end
= RANGE_END(range
);
795 if (r_le(beg
, val
)) {
809 range_dumper(VALUE range
)
812 NEWOBJ(m
, struct RObject
);
813 OBJSETUP(m
, rb_cObject
, T_OBJECT
);
817 rb_ivar_set(v
, id_excl
, RANGE_EXCL(range
));
818 rb_ivar_set(v
, id_beg
, RANGE_BEG(range
));
819 rb_ivar_set(v
, id_end
, RANGE_END(range
));
824 range_loader(VALUE range
, VALUE obj
)
826 if (TYPE(obj
) != T_OBJECT
|| RBASIC(obj
)->klass
!= rb_cObject
) {
827 rb_raise(rb_eTypeError
, "not a dumped range object");
830 RSTRUCT(range
)->as
.ary
[0] = rb_ivar_get(obj
, id_beg
);
831 RSTRUCT(range
)->as
.ary
[1] = rb_ivar_get(obj
, id_end
);
832 RSTRUCT(range
)->as
.ary
[2] = rb_ivar_get(obj
, id_excl
);
837 range_alloc(VALUE klass
)
839 /* rb_struct_alloc_noinit itself should not be used because
840 * rb_marshal_define_compat uses equality of allocaiton function */
841 return rb_struct_alloc_noinit(klass
);
844 /* A <code>Range</code> represents an interval---a set of values with a
845 * start and an end. Ranges may be constructed using the
846 * <em>s</em><code>..</code><em>e</em> and
847 * <em>s</em><code>...</code><em>e</em> literals, or with
848 * <code>Range::new</code>. Ranges constructed using <code>..</code>
849 * run from the start to the end inclusively. Those created using
850 * <code>...</code> exclude the end value. When used as an iterator,
851 * ranges return each value in the sequence.
853 * (-1..-5).to_a #=> []
854 * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
855 * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
856 * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
858 * Ranges can be constructed using objects of any type, as long as the
859 * objects can be compared using their <code><=></code> operator and
860 * they support the <code>succ</code> method to return the next object
863 * class Xs # represent a string of 'x's
870 * Xs.new(@length + 1)
873 * @length <=> other.length
876 * sprintf "%2d #{inspect}", @length
883 * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
884 * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
885 * r.member?(Xs.new(5)) #=> true
887 * In the previous code example, class <code>Xs</code> includes the
888 * <code>Comparable</code> module. This is because
889 * <code>Enumerable#member?</code> checks for equality using
890 * <code>==</code>. Including <code>Comparable</code> ensures that the
891 * <code>==</code> method is defined in terms of the <code><=></code>
892 * method implemented in <code>Xs</code>.
899 id_cmp
= rb_intern("<=>");
900 id_succ
= rb_intern("succ");
901 id_beg
= rb_intern("begin");
902 id_end
= rb_intern("end");
903 id_excl
= rb_intern("excl");
905 rb_cRange
= rb_struct_define_without_accessor(
906 "Range", rb_cObject
, range_alloc
,
907 "begin", "end", "excl", NULL
);
909 rb_include_module(rb_cRange
, rb_mEnumerable
);
910 rb_marshal_define_compat(rb_cRange
, rb_cObject
, range_dumper
, range_loader
);
911 rb_define_method(rb_cRange
, "initialize", range_initialize
, -1);
912 rb_define_method(rb_cRange
, "==", range_eq
, 1);
913 rb_define_method(rb_cRange
, "===", range_eqq
, 1);
914 rb_define_method(rb_cRange
, "eql?", range_eql
, 1);
915 rb_define_method(rb_cRange
, "hash", range_hash
, 0);
916 rb_define_method(rb_cRange
, "each", range_each
, 0);
917 rb_define_method(rb_cRange
, "step", range_step
, -1);
918 rb_define_method(rb_cRange
, "begin", range_begin
, 0);
919 rb_define_method(rb_cRange
, "end", range_end
, 0);
920 rb_define_method(rb_cRange
, "first", range_first
, -1);
921 rb_define_method(rb_cRange
, "last", range_last
, -1);
922 rb_define_method(rb_cRange
, "min", range_min
, 0);
923 rb_define_method(rb_cRange
, "max", range_max
, 0);
924 rb_define_method(rb_cRange
, "to_s", range_to_s
, 0);
925 rb_define_method(rb_cRange
, "inspect", range_inspect
, 0);
927 rb_define_method(rb_cRange
, "exclude_end?", range_exclude_end_p
, 0);
929 rb_define_method(rb_cRange
, "member?", range_include
, 1);
930 rb_define_method(rb_cRange
, "include?", range_include
, 1);
931 rb_define_method(rb_cRange
, "cover?", range_cover
, 1);