Ruby  1.9.3p429(2013-05-15revision40747)
range.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  range.c -
4 
5  $Author: tarui $
6  created at: Thu Aug 19 17:46:47 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 #include "ruby/encoding.h"
14 #include "internal.h"
15 
18 
19 #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
20 #define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
21 #define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
22 
23 #define EXCL(r) RTEST(RANGE_EXCL(r))
24 #define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
25 
26 static VALUE
28 {
29  rb_raise(rb_eArgError, "bad value for range");
30  return Qnil; /* dummy */
31 }
32 
33 static VALUE
35 {
36  return rb_funcall(args[0], id_cmp, 1, args[1]);
37 }
38 
39 static void
40 range_init(VALUE range, VALUE beg, VALUE end, int exclude_end)
41 {
42  VALUE args[2];
43 
44  args[0] = beg;
45  args[1] = end;
46 
47  if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
48  VALUE v;
49 
50  v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
51  if (NIL_P(v))
52  range_failed();
53  }
54 
55  SET_EXCL(range, exclude_end);
56  RSTRUCT(range)->as.ary[0] = beg;
57  RSTRUCT(range)->as.ary[1] = end;
58 }
59 
60 VALUE
61 rb_range_new(VALUE beg, VALUE end, int exclude_end)
62 {
64 
65  range_init(range, beg, end, exclude_end);
66  return range;
67 }
68 
69 /*
70  * call-seq:
71  * Range.new(start, end, exclusive=false) -> range
72  *
73  * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
74  * parameter is omitted or is <code>false</code>, the <i>range</i> will include
75  * the end object; otherwise, it will be excluded.
76  */
77 
78 static VALUE
80 {
81  VALUE beg, end, flags;
82 
83  rb_scan_args(argc, argv, "21", &beg, &end, &flags);
84  /* Ranges are immutable, so that they should be initialized only once. */
85  if (RANGE_EXCL(range) != Qnil) {
86  rb_name_error(rb_intern("initialize"), "`initialize' called twice");
87  }
88  range_init(range, beg, end, RTEST(flags));
89  return Qnil;
90 }
91 
92 #define range_initialize_copy rb_struct_init_copy /* :nodoc: */
93 
94 /*
95  * call-seq:
96  * rng.exclude_end? -> true or false
97  *
98  * Returns <code>true</code> if <i>rng</i> excludes its end value.
99  */
100 
101 static VALUE
103 {
104  return EXCL(range) ? Qtrue : Qfalse;
105 }
106 
107 static VALUE
109 {
110  if (recur) return Qtrue; /* Subtle! */
111  if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
112  return Qfalse;
113  if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
114  return Qfalse;
115 
116  if (EXCL(range) != EXCL(obj))
117  return Qfalse;
118  return Qtrue;
119 }
120 
121 
122 /*
123  * call-seq:
124  * rng == obj -> true or false
125  *
126  * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
127  * beginning and end items (by comparing them with <code>==</code>), and has
128  * the same <code>exclude_end?</code> setting as <i>rng</i>.
129  *
130  * (0..2) == (0..2) #=> true
131  * (0..2) == Range.new(0,2) #=> true
132  * (0..2) == (0...2) #=> false
133  *
134  */
135 
136 static VALUE
138 {
139  if (range == obj)
140  return Qtrue;
141  if (!rb_obj_is_kind_of(obj, rb_cRange))
142  return Qfalse;
143 
144  return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
145 }
146 
147 static int
149 {
150  VALUE r = rb_funcall(a, id_cmp, 1, b);
151 
152  if (NIL_P(r))
153  return (int)Qfalse;
154  if (rb_cmpint(r, a, b) < 0)
155  return (int)Qtrue;
156  return (int)Qfalse;
157 }
158 
159 static int
161 {
162  int c;
163  VALUE r = rb_funcall(a, id_cmp, 1, b);
164 
165  if (NIL_P(r))
166  return (int)Qfalse;
167  c = rb_cmpint(r, a, b);
168  if (c == 0)
169  return (int)INT2FIX(0);
170  if (c < 0)
171  return (int)Qtrue;
172  return (int)Qfalse;
173 }
174 
175 
176 static VALUE
178 {
179  if (recur) return Qtrue; /* Subtle! */
180  if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
181  return Qfalse;
182  if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
183  return Qfalse;
184 
185  if (EXCL(range) != EXCL(obj))
186  return Qfalse;
187  return Qtrue;
188 }
189 
190 /*
191  * call-seq:
192  * rng.eql?(obj) -> true or false
193  *
194  * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
195  * beginning and end items (by comparing them with #eql?), and has the same
196  * #exclude_end? setting as <i>rng</i>.
197  *
198  * (0..2).eql?(0..2) #=> true
199  * (0..2).eql?(Range.new(0,2)) #=> true
200  * (0..2).eql?(0...2) #=> false
201  *
202  */
203 
204 static VALUE
206 {
207  if (range == obj)
208  return Qtrue;
209  if (!rb_obj_is_kind_of(obj, rb_cRange))
210  return Qfalse;
211  return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
212 }
213 
214 static VALUE
216 {
217  st_index_t hash = EXCL(range);
218  VALUE v;
219 
220  hash = rb_hash_start(hash);
221  if (!recur) {
222  v = rb_hash(RANGE_BEG(range));
223  hash = rb_hash_uint(hash, NUM2LONG(v));
224  v = rb_hash(RANGE_END(range));
225  hash = rb_hash_uint(hash, NUM2LONG(v));
226  }
227  hash = rb_hash_uint(hash, EXCL(range) << 24);
228  hash = rb_hash_end(hash);
229 
230  return LONG2FIX(hash);
231 }
232 
233 /*
234  * call-seq:
235  * rng.hash -> fixnum
236  *
237  * Generate a hash value such that two ranges with the same start and
238  * end points, and the same value for the "exclude end" flag, generate
239  * the same hash value.
240  */
241 
242 static VALUE
244 {
245  return rb_exec_recursive_outer(recursive_hash, range, 0);
246 }
247 
248 static void
250 {
251  int c;
252  VALUE b = RANGE_BEG(range);
253  VALUE e = RANGE_END(range);
254  VALUE v = b;
255 
256  if (EXCL(range)) {
257  while (r_lt(v, e)) {
258  (*func) (v, arg);
259  v = rb_funcall(v, id_succ, 0, 0);
260  }
261  }
262  else {
263  while ((c = r_le(v, e)) != Qfalse) {
264  (*func) (v, arg);
265  if (c == (int)INT2FIX(0))
266  break;
267  v = rb_funcall(v, id_succ, 0, 0);
268  }
269  }
270 }
271 
272 static VALUE
274 {
275  VALUE *iter = arg;
276 
277  if (FIXNUM_P(iter[0])) {
278  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
279  }
280  else {
281  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
282  }
283  if (iter[0] == INT2FIX(0)) {
285  iter[0] = iter[1];
286  }
287  return Qnil;
288 }
289 
290 static VALUE
291 step_i(VALUE i, void *arg)
292 {
293  VALUE *iter = arg;
294 
295  if (FIXNUM_P(iter[0])) {
296  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
297  }
298  else {
299  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
300  }
301  if (iter[0] == INT2FIX(0)) {
302  rb_yield(i);
303  iter[0] = iter[1];
304  }
305  return Qnil;
306 }
307 
308 static int
310 {
311  if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
312  return rb_respond_to(obj, id_succ);
313 }
314 
315 
316 /*
317  * call-seq:
318  * rng.step(n=1) {| obj | block } -> rng
319  * rng.step(n=1) -> an_enumerator
320  *
321  * Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
322  * the range contains numbers, <i>n</i> is added for each iteration. Otherwise
323  * <code>step</code> invokes <code>succ</code> to iterate through range
324  * elements. The following code uses class <code>Xs</code>, which is defined
325  * in the class-level documentation.
326  *
327  * If no block is given, an enumerator is returned instead.
328  *
329  * range = Xs.new(1)..Xs.new(10)
330  * range.step(2) {|x| puts x}
331  * range.step(3) {|x| puts x}
332  *
333  * <em>produces:</em>
334  *
335  * 1 x
336  * 3 xxx
337  * 5 xxxxx
338  * 7 xxxxxxx
339  * 9 xxxxxxxxx
340  * 1 x
341  * 4 xxxx
342  * 7 xxxxxxx
343  * 10 xxxxxxxxxx
344  */
345 
346 
347 static VALUE
349 {
350  VALUE b, e, step, tmp;
351 
352  RETURN_ENUMERATOR(range, argc, argv);
353 
354  b = RANGE_BEG(range);
355  e = RANGE_END(range);
356  if (argc == 0) {
357  step = INT2FIX(1);
358  }
359  else {
360  rb_scan_args(argc, argv, "01", &step);
361  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
362  step = rb_to_int(step);
363  }
364  if (rb_funcall(step, '<', 1, INT2FIX(0))) {
365  rb_raise(rb_eArgError, "step can't be negative");
366  }
367  else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
368  rb_raise(rb_eArgError, "step can't be 0");
369  }
370  }
371 
372  if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
373  long end = FIX2LONG(e);
374  long i, unit = FIX2LONG(step);
375 
376  if (!EXCL(range))
377  end += 1;
378  i = FIX2LONG(b);
379  while (i < end) {
380  rb_yield(LONG2NUM(i));
381  if (i + unit < i) break;
382  i += unit;
383  }
384 
385  }
386  else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
387  VALUE args[2], iter[2];
388 
389  args[0] = rb_sym_to_s(e);
390  args[1] = EXCL(range) ? Qtrue : Qfalse;
391  iter[0] = INT2FIX(1);
392  iter[1] = step;
393  rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
394  }
395  else if (ruby_float_step(b, e, step, EXCL(range))) {
396  /* done */
397  }
398  else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
399  !NIL_P(rb_check_to_integer(b, "to_int")) ||
400  !NIL_P(rb_check_to_integer(e, "to_int"))) {
401  ID op = EXCL(range) ? '<' : rb_intern("<=");
402  VALUE v = b;
403  int i = 0;
404 
405  while (RTEST(rb_funcall(v, op, 1, e))) {
406  rb_yield(v);
407  i++;
408  v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
409  }
410  }
411  else {
412  tmp = rb_check_string_type(b);
413 
414  if (!NIL_P(tmp)) {
415  VALUE args[2], iter[2];
416 
417  b = tmp;
418  args[0] = e;
419  args[1] = EXCL(range) ? Qtrue : Qfalse;
420  iter[0] = INT2FIX(1);
421  iter[1] = step;
422  rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
423  }
424  else {
425  VALUE args[2];
426 
427  if (!discrete_object_p(b)) {
428  rb_raise(rb_eTypeError, "can't iterate from %s",
429  rb_obj_classname(b));
430  }
431  args[0] = INT2FIX(1);
432  args[1] = step;
433  range_each_func(range, step_i, args);
434  }
435  }
436  return range;
437 }
438 
439 static VALUE
440 each_i(VALUE v, void *arg)
441 {
442  rb_yield(v);
443  return Qnil;
444 }
445 
446 static VALUE
448 {
450  return Qnil;
451 }
452 
453 /*
454  * call-seq:
455  * rng.each {| i | block } -> rng
456  * rng.each -> an_enumerator
457  *
458  * Iterates over the elements <i>rng</i>, passing each in turn to the
459  * block. You can only iterate if the start object of the range
460  * supports the +succ+ method (which means that you can't iterate over
461  * ranges of +Float+ objects).
462  *
463  * If no block is given, an enumerator is returned instead.
464  *
465  * (10..15).each do |n|
466  * print n, ' '
467  * end
468  *
469  * <em>produces:</em>
470  *
471  * 10 11 12 13 14 15
472  */
473 
474 static VALUE
476 {
477  VALUE beg, end;
478 
479  RETURN_ENUMERATOR(range, 0, 0);
480 
481  beg = RANGE_BEG(range);
482  end = RANGE_END(range);
483 
484  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
485  long lim = FIX2LONG(end);
486  long i;
487 
488  if (!EXCL(range))
489  lim += 1;
490  for (i = FIX2LONG(beg); i < lim; i++) {
491  rb_yield(LONG2FIX(i));
492  }
493  }
494  else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
495  VALUE args[2];
496 
497  args[0] = rb_sym_to_s(end);
498  args[1] = EXCL(range) ? Qtrue : Qfalse;
499  rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
500  }
501  else {
502  VALUE tmp = rb_check_string_type(beg);
503 
504  if (!NIL_P(tmp)) {
505  VALUE args[2];
506 
507  args[0] = end;
508  args[1] = EXCL(range) ? Qtrue : Qfalse;
509  rb_block_call(tmp, rb_intern("upto"), 2, args, rb_yield, 0);
510  }
511  else {
512  if (!discrete_object_p(beg)) {
513  rb_raise(rb_eTypeError, "can't iterate from %s",
514  rb_obj_classname(beg));
515  }
516  range_each_func(range, each_i, NULL);
517  }
518  }
519  return range;
520 }
521 
522 /*
523  * call-seq:
524  * rng.begin -> obj
525  *
526  * Returns the first object in <i>rng</i>.
527  */
528 
529 static VALUE
531 {
532  return RANGE_BEG(range);
533 }
534 
535 
536 /*
537  * call-seq:
538  * rng.end -> obj
539  *
540  * Returns the object that defines the end of <i>rng</i>.
541  *
542  * (1..10).end #=> 10
543  * (1...10).end #=> 10
544  */
545 
546 
547 static VALUE
549 {
550  return RANGE_END(range);
551 }
552 
553 
554 static VALUE
556 {
557  long n = NUM2LONG(ary[0]);
558 
559  if (n <= 0) {
560  rb_iter_break();
561  }
562  rb_ary_push(ary[1], i);
563  n--;
564  ary[0] = INT2NUM(n);
565  return Qnil;
566 }
567 
568 /*
569  * call-seq:
570  * rng.first -> obj
571  * rng.first(n) -> an_array
572  *
573  * Returns the first object in <i>rng</i>, or the first +n+ elements.
574  */
575 
576 static VALUE
578 {
579  VALUE n, ary[2];
580 
581  if (argc == 0) return RANGE_BEG(range);
582 
583  rb_scan_args(argc, argv, "1", &n);
584  ary[0] = n;
585  ary[1] = rb_ary_new2(NUM2LONG(n));
586  rb_block_call(range, rb_intern("each"), 0, 0, first_i, (VALUE)ary);
587 
588  return ary[1];
589 }
590 
591 
592 /*
593  * call-seq:
594  * rng.last -> obj
595  * rng.last(n) -> an_array
596  *
597  * Returns the last object in <i>rng</i>, or the last +n+ elements.
598  */
599 
600 static VALUE
602 {
603  if (argc == 0) return RANGE_END(range);
604  return rb_ary_last(argc, argv, rb_Array(range));
605 }
606 
607 
608 /*
609  * call-seq:
610  * rng.min -> obj
611  * rng.min {| a,b | block } -> obj
612  *
613  * Returns the minimum value in <i>rng</i>. The second uses
614  * the block to compare values. Returns nil if the first
615  * value in range is larger than the last value.
616  *
617  */
618 
619 
620 static VALUE
622 {
623  if (rb_block_given_p()) {
624  return rb_call_super(0, 0);
625  }
626  else {
627  VALUE b = RANGE_BEG(range);
628  VALUE e = RANGE_END(range);
629  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
630 
631  if (c > 0 || (c == 0 && EXCL(range)))
632  return Qnil;
633  return b;
634  }
635 }
636 
637 /*
638  * call-seq:
639  * rng.max -> obj
640  * rng.max {| a,b | block } -> obj
641  *
642  * Returns the maximum value in <i>rng</i>. The second uses
643  * the block to compare values. Returns nil if the first
644  * value in range is larger than the last value.
645  *
646  */
647 
648 static VALUE
650 {
651  VALUE e = RANGE_END(range);
652  int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
653 
654  if (rb_block_given_p() || (EXCL(range) && !nm)) {
655  return rb_call_super(0, 0);
656  }
657  else {
658  VALUE b = RANGE_BEG(range);
659  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
660 
661  if (c > 0)
662  return Qnil;
663  if (EXCL(range)) {
664  if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
665  rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
666  }
667  if (c == 0) return Qnil;
668  if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
669  rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
670  }
671  if (FIXNUM_P(e)) {
672  return LONG2NUM(FIX2LONG(e) - 1);
673  }
674  return rb_funcall(e, '-', 1, INT2FIX(1));
675  }
676  return e;
677  }
678 }
679 
680 int
681 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
682 {
683  VALUE b, e;
684  int excl;
685 
686  if (rb_obj_is_kind_of(range, rb_cRange)) {
687  b = RANGE_BEG(range);
688  e = RANGE_END(range);
689  excl = EXCL(range);
690  }
691  else {
692  if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
693  if (!rb_respond_to(range, id_end)) return (int)Qfalse;
694  b = rb_funcall(range, id_beg, 0);
695  e = rb_funcall(range, id_end, 0);
696  excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
697  }
698  *begp = b;
699  *endp = e;
700  *exclp = excl;
701  return (int)Qtrue;
702 }
703 
704 VALUE
705 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
706 {
707  long beg, end, origbeg, origend;
708  VALUE b, e;
709  int excl;
710 
711  if (!rb_range_values(range, &b, &e, &excl))
712  return Qfalse;
713  beg = NUM2LONG(b);
714  end = NUM2LONG(e);
715  origbeg = beg;
716  origend = end;
717  if (beg < 0) {
718  beg += len;
719  if (beg < 0)
720  goto out_of_range;
721  }
722  if (err == 0 || err == 2) {
723  if (beg > len)
724  goto out_of_range;
725  if (end > len)
726  end = len;
727  }
728  if (end < 0)
729  end += len;
730  if (!excl)
731  end++; /* include end point */
732  len = end - beg;
733  if (len < 0)
734  len = 0;
735 
736  *begp = beg;
737  *lenp = len;
738  return Qtrue;
739 
740  out_of_range:
741  if (err) {
742  rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
743  origbeg, excl ? "." : "", origend);
744  }
745  return Qnil;
746 }
747 
748 /*
749  * call-seq:
750  * rng.to_s -> string
751  *
752  * Convert this range object to a printable form.
753  */
754 
755 static VALUE
757 {
758  VALUE str, str2;
759 
760  str = rb_obj_as_string(RANGE_BEG(range));
761  str2 = rb_obj_as_string(RANGE_END(range));
762  str = rb_str_dup(str);
763  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
764  rb_str_append(str, str2);
765  OBJ_INFECT(str, str2);
766 
767  return str;
768 }
769 
770 static VALUE
771 inspect_range(VALUE range, VALUE dummy, int recur)
772 {
773  VALUE str, str2;
774 
775  if (recur) {
776  return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
777  }
778  str = rb_inspect(RANGE_BEG(range));
779  str2 = rb_inspect(RANGE_END(range));
780  str = rb_str_dup(str);
781  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
782  rb_str_append(str, str2);
783  OBJ_INFECT(str, str2);
784 
785  return str;
786 }
787 
788 /*
789  * call-seq:
790  * rng.inspect -> string
791  *
792  * Convert this range object to a printable form (using
793  * <code>inspect</code> to convert the start and end
794  * objects).
795  */
796 
797 
798 static VALUE
800 {
801  return rb_exec_recursive(inspect_range, range, 0);
802 }
803 
804 /*
805  * call-seq:
806  * rng === obj -> true or false
807  *
808  * Returns <code>true</code> if <i>obj</i> is an element of
809  * <i>rng</i>, <code>false</code> otherwise. Conveniently,
810  * <code>===</code> is the comparison operator used by
811  * <code>case</code> statements.
812  *
813  * case 79
814  * when 1..50 then print "low\n"
815  * when 51..75 then print "medium\n"
816  * when 76..100 then print "high\n"
817  * end
818  *
819  * <em>produces:</em>
820  *
821  * high
822  */
823 
824 static VALUE
825 range_eqq(VALUE range, VALUE val)
826 {
827  return rb_funcall(range, rb_intern("include?"), 1, val);
828 }
829 
830 
831 /*
832  * call-seq:
833  * rng.member?(val) -> true or false
834  * rng.include?(val) -> true or false
835  *
836  * Returns <code>true</code> if <i>obj</i> is an element of
837  * <i>rng</i>, <code>false</code> otherwise. If beg and end are
838  * numeric, comparison is done according magnitude of values.
839  *
840  * ("a".."z").include?("g") # -> true
841  * ("a".."z").include?("A") # -> false
842  */
843 
844 static VALUE
846 {
847  VALUE beg = RANGE_BEG(range);
848  VALUE end = RANGE_END(range);
849  int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
852 
853  if (nv ||
854  !NIL_P(rb_check_to_integer(beg, "to_int")) ||
855  !NIL_P(rb_check_to_integer(end, "to_int"))) {
856  if (r_le(beg, val)) {
857  if (EXCL(range)) {
858  if (r_lt(val, end))
859  return Qtrue;
860  }
861  else {
862  if (r_le(val, end))
863  return Qtrue;
864  }
865  }
866  return Qfalse;
867  }
868  else if (TYPE(beg) == T_STRING && TYPE(end) == T_STRING &&
869  RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
870  if (NIL_P(val)) return Qfalse;
871  if (TYPE(val) == T_STRING) {
872  if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
873  return Qfalse;
874  else {
875  char b = RSTRING_PTR(beg)[0];
876  char e = RSTRING_PTR(end)[0];
877  char v = RSTRING_PTR(val)[0];
878 
879  if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
880  if (b <= v && v < e) return Qtrue;
881  if (!EXCL(range) && v == e) return Qtrue;
882  return Qfalse;
883  }
884  }
885  }
886  }
887  /* TODO: ruby_frame->this_func = rb_intern("include?"); */
888  return rb_call_super(1, &val);
889 }
890 
891 
892 /*
893  * call-seq:
894  * rng.cover?(val) -> true or false
895  *
896  * Returns <code>true</code> if <i>obj</i> is between beg and end,
897  * i.e <code>beg <= obj <= end</code> (or <i>end</i> exclusive when
898  * <code>exclude_end?</code> is true).
899  *
900  * ("a".."z").cover?("c") #=> true
901  * ("a".."z").cover?("5") #=> false
902  */
903 
904 static VALUE
906 {
907  VALUE beg, end;
908 
909  beg = RANGE_BEG(range);
910  end = RANGE_END(range);
911  if (r_le(beg, val)) {
912  if (EXCL(range)) {
913  if (r_lt(val, end))
914  return Qtrue;
915  }
916  else {
917  if (r_le(val, end))
918  return Qtrue;
919  }
920  }
921  return Qfalse;
922 }
923 
924 static VALUE
926 {
927  VALUE v;
928  NEWOBJ(m, struct RObject);
930 
931  v = (VALUE)m;
932 
933  rb_ivar_set(v, id_excl, RANGE_EXCL(range));
934  rb_ivar_set(v, id_beg, RANGE_BEG(range));
935  rb_ivar_set(v, id_end, RANGE_END(range));
936  return v;
937 }
938 
939 static VALUE
941 {
942  if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
943  rb_raise(rb_eTypeError, "not a dumped range object");
944  }
945 
946  RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
947  RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
948  RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
949  return range;
950 }
951 
952 static VALUE
954 {
955  /* rb_struct_alloc_noinit itself should not be used because
956  * rb_marshal_define_compat uses equality of allocaiton function */
957  return rb_struct_alloc_noinit(klass);
958 }
959 
960 /* A <code>Range</code> represents an interval---a set of values with a
961  * start and an end. Ranges may be constructed using the
962  * <em>s</em><code>..</code><em>e</em> and
963  * <em>s</em><code>...</code><em>e</em> literals, or with
964  * <code>Range::new</code>. Ranges constructed using <code>..</code>
965  * run from the start to the end inclusively. Those created using
966  * <code>...</code> exclude the end value. When used as an iterator,
967  * ranges return each value in the sequence.
968  *
969  * (-1..-5).to_a #=> []
970  * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
971  * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
972  * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
973  *
974  * Ranges can be constructed using objects of any type, as long as the
975  * objects can be compared using their <code><=></code> operator and
976  * they support the <code>succ</code> method to return the next object
977  * in sequence.
978  *
979  * class Xs # represent a string of 'x's
980  * include Comparable
981  * attr :length
982  * def initialize(n)
983  * @length = n
984  * end
985  * def succ
986  * Xs.new(@length + 1)
987  * end
988  * def <=>(other)
989  * @length <=> other.length
990  * end
991  * def to_s
992  * sprintf "%2d #{inspect}", @length
993  * end
994  * def inspect
995  * 'x' * @length
996  * end
997  * end
998  *
999  * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1000  * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1001  * r.member?(Xs.new(5)) #=> true
1002  *
1003  * In the previous code example, class <code>Xs</code> includes the
1004  * <code>Comparable</code> module. This is because
1005  * <code>Enumerable#member?</code> checks for equality using
1006  * <code>==</code>. Including <code>Comparable</code> ensures that the
1007  * <code>==</code> method is defined in terms of the <code><=></code>
1008  * method implemented in <code>Xs</code>.
1009  *
1010  */
1011 
1012 void
1014 {
1015 #undef rb_intern
1016 #define rb_intern(str) rb_intern_const(str)
1017 
1018  id_cmp = rb_intern("<=>");
1019  id_succ = rb_intern("succ");
1020  id_beg = rb_intern("begin");
1021  id_end = rb_intern("end");
1022  id_excl = rb_intern("excl");
1023 
1025  "Range", rb_cObject, range_alloc,
1026  "begin", "end", "excl", NULL);
1027 
1030  rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1031  rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1032  rb_define_method(rb_cRange, "==", range_eq, 1);
1033  rb_define_method(rb_cRange, "===", range_eqq, 1);
1034  rb_define_method(rb_cRange, "eql?", range_eql, 1);
1035  rb_define_method(rb_cRange, "hash", range_hash, 0);
1036  rb_define_method(rb_cRange, "each", range_each, 0);
1037  rb_define_method(rb_cRange, "step", range_step, -1);
1038  rb_define_method(rb_cRange, "begin", range_begin, 0);
1039  rb_define_method(rb_cRange, "end", range_end, 0);
1040  rb_define_method(rb_cRange, "first", range_first, -1);
1041  rb_define_method(rb_cRange, "last", range_last, -1);
1042  rb_define_method(rb_cRange, "min", range_min, 0);
1043  rb_define_method(rb_cRange, "max", range_max, 0);
1044  rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1045  rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1046 
1047  rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1048 
1049  rb_define_method(rb_cRange, "member?", range_include, 1);
1050  rb_define_method(rb_cRange, "include?", range_include, 1);
1051  rb_define_method(rb_cRange, "cover?", range_cover, 1);
1052 }
1053