Ruby  2.1.10p492(2016-04-01revision54464)
range.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  range.c -
4 
5  $Author: usa $
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 #include "id.h"
16 
17 #ifdef HAVE_FLOAT_H
18 #include <float.h>
19 #endif
20 #include <math.h>
21 
24 
25 #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
26 #define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
27 #define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
28 #define RANGE_SET_BEG(r, v) (RSTRUCT_SET(r, 0, v))
29 #define RANGE_SET_END(r, v) (RSTRUCT_SET(r, 1, v))
30 #define RANGE_SET_EXCL(r, v) (RSTRUCT_SET(r, 2, v))
31 #define RBOOL(v) ((v) ? Qtrue : Qfalse)
32 
33 #define EXCL(r) RTEST(RANGE_EXCL(r))
34 
35 static VALUE
37 {
38  rb_raise(rb_eArgError, "bad value for range");
39  return Qnil; /* dummy */
40 }
41 
42 static VALUE
44 {
45  return rb_funcall(args[0], id_cmp, 1, args[1]);
46 }
47 
48 static void
49 range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
50 {
51  VALUE args[2];
52 
53  args[0] = beg;
54  args[1] = end;
55 
56  if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
57  VALUE v;
58 
59  v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
60  if (NIL_P(v))
61  range_failed();
62  }
63 
64  RANGE_SET_EXCL(range, exclude_end);
65  RANGE_SET_BEG(range, beg);
66  RANGE_SET_END(range, end);
67 }
68 
69 VALUE
70 rb_range_new(VALUE beg, VALUE end, int exclude_end)
71 {
73 
74  range_init(range, beg, end, RBOOL(exclude_end));
75  return range;
76 }
77 
78 static void
80 {
81  /* Ranges are immutable, so that they should be initialized only once. */
82  if (RANGE_EXCL(range) != Qnil) {
83  rb_name_error(idInitialize, "`initialize' called twice");
84  }
85 }
86 
87 /*
88  * call-seq:
89  * Range.new(begin, end, exclude_end=false) -> rng
90  *
91  * Constructs a range using the given +begin+ and +end+. If the +exclude_end+
92  * parameter is omitted or is <code>false</code>, the +rng+ will include
93  * the end object; otherwise, it will be excluded.
94  */
95 
96 static VALUE
98 {
99  VALUE beg, end, flags;
100 
101  rb_scan_args(argc, argv, "21", &beg, &end, &flags);
103  range_init(range, beg, end, RBOOL(RTEST(flags)));
104  return Qnil;
105 }
106 
107 /* :nodoc: */
108 static VALUE
110 {
112  rb_struct_init_copy(range, orig);
113  return range;
114 }
115 
116 /*
117  * call-seq:
118  * rng.exclude_end? -> true or false
119  *
120  * Returns <code>true</code> if the range excludes its end value.
121  *
122  * (1..5).exclude_end? #=> false
123  * (1...5).exclude_end? #=> true
124  */
125 
126 static VALUE
128 {
129  return EXCL(range) ? Qtrue : Qfalse;
130 }
131 
132 static VALUE
134 {
135  if (recur) return Qtrue; /* Subtle! */
136  if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
137  return Qfalse;
138  if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
139  return Qfalse;
140 
141  if (EXCL(range) != EXCL(obj))
142  return Qfalse;
143  return Qtrue;
144 }
145 
146 
147 /*
148  * call-seq:
149  * rng == obj -> true or false
150  *
151  * Returns <code>true</code> only if +obj+ is a Range, has equivalent
152  * begin and end items (by comparing them with <code>==</code>), and has
153  * the same #exclude_end? setting as the range.
154  *
155  * (0..2) == (0..2) #=> true
156  * (0..2) == Range.new(0,2) #=> true
157  * (0..2) == (0...2) #=> false
158  *
159  */
160 
161 static VALUE
163 {
164  if (range == obj)
165  return Qtrue;
166  if (!rb_obj_is_kind_of(obj, rb_cRange))
167  return Qfalse;
168 
170 }
171 
172 static int
174 {
175  VALUE r = rb_funcall(a, id_cmp, 1, b);
176 
177  if (NIL_P(r))
178  return (int)Qfalse;
179  if (rb_cmpint(r, a, b) < 0)
180  return (int)Qtrue;
181  return (int)Qfalse;
182 }
183 
184 static int
186 {
187  int c;
188  VALUE r = rb_funcall(a, id_cmp, 1, b);
189 
190  if (NIL_P(r))
191  return (int)Qfalse;
192  c = rb_cmpint(r, a, b);
193  if (c == 0)
194  return (int)INT2FIX(0);
195  if (c < 0)
196  return (int)Qtrue;
197  return (int)Qfalse;
198 }
199 
200 
201 static VALUE
203 {
204  if (recur) return Qtrue; /* Subtle! */
205  if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
206  return Qfalse;
207  if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
208  return Qfalse;
209 
210  if (EXCL(range) != EXCL(obj))
211  return Qfalse;
212  return Qtrue;
213 }
214 
215 /*
216  * call-seq:
217  * rng.eql?(obj) -> true or false
218  *
219  * Returns <code>true</code> only if +obj+ is a Range, has equivalent
220  * begin and end items (by comparing them with <code>eql?</code>),
221  * and has the same #exclude_end? setting as the range.
222  *
223  * (0..2).eql?(0..2) #=> true
224  * (0..2).eql?(Range.new(0,2)) #=> true
225  * (0..2).eql?(0...2) #=> false
226  *
227  */
228 
229 static VALUE
231 {
232  if (range == obj)
233  return Qtrue;
234  if (!rb_obj_is_kind_of(obj, rb_cRange))
235  return Qfalse;
236  return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
237 }
238 
239 /*
240  * call-seq:
241  * rng.hash -> fixnum
242  *
243  * Compute a hash-code for this range. Two ranges with equal
244  * begin and end points (using <code>eql?</code>), and the same
245  * #exclude_end? value will generate the same hash-code.
246  */
247 
248 static VALUE
250 {
252  VALUE v;
253 
255  v = rb_hash(RANGE_BEG(range));
257  v = rb_hash(RANGE_END(range));
259  hash = rb_hash_uint(hash, EXCL(range) << 24);
260  hash = rb_hash_end(hash);
261 
262  return LONG2FIX(hash);
263 }
264 
265 static void
267 {
268  int c;
269  VALUE b = RANGE_BEG(range);
270  VALUE e = RANGE_END(range);
271  VALUE v = b;
272 
273  if (EXCL(range)) {
274  while (r_lt(v, e)) {
275  (*func) (v, arg, 0, 0, 0);
276  v = rb_funcall(v, id_succ, 0, 0);
277  }
278  }
279  else {
280  while ((c = r_le(v, e)) != Qfalse) {
281  (*func) (v, arg, 0, 0, 0);
282  if (c == (int)INT2FIX(0))
283  break;
284  v = rb_funcall(v, id_succ, 0, 0);
285  }
286  }
287 }
288 
289 static VALUE
291 {
292  VALUE *iter = (VALUE *)arg;
293 
294  if (FIXNUM_P(iter[0])) {
295  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
296  }
297  else {
298  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
299  }
300  if (iter[0] == INT2FIX(0)) {
302  iter[0] = iter[1];
303  }
304  return Qnil;
305 }
306 
307 static VALUE
309 {
310  VALUE *iter = (VALUE *)arg;
311 
312  if (FIXNUM_P(iter[0])) {
313  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
314  }
315  else {
316  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
317  }
318  if (iter[0] == INT2FIX(0)) {
319  rb_yield(i);
320  iter[0] = iter[1];
321  }
322  return Qnil;
323 }
324 
325 static int
327 {
328  if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
329  return rb_respond_to(obj, id_succ);
330 }
331 
332 static int
334 {
335  if (FIXNUM_P(obj) || FLONUM_P(obj)) return TRUE;
336  if (SPECIAL_CONST_P(obj)) return FALSE;
337  switch (BUILTIN_TYPE(obj)) {
338  case T_FLOAT:
339  case T_BIGNUM:
340  return TRUE;
341  }
342  if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE;
343  if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE;
344  return FALSE;
345 }
346 
347 static VALUE
349 {
350  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
351  VALUE step = INT2FIX(1);
352  if (args) {
353  step = RARRAY_AREF(args, 0);
354  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
355  step = rb_to_int(step);
356  }
357  }
358  if (rb_funcall(step, '<', 1, INT2FIX(0))) {
359  rb_raise(rb_eArgError, "step can't be negative");
360  }
361  else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
362  rb_raise(rb_eArgError, "step can't be 0");
363  }
364 
366  return ruby_num_interval_step_size(b, e, step, EXCL(range));
367  }
368  return Qnil;
369 }
370 
371 /*
372  * call-seq:
373  * rng.step(n=1) {| obj | block } -> rng
374  * rng.step(n=1) -> an_enumerator
375  *
376  * Iterates over the range, passing each <code>n</code>th element to the block.
377  * If begin and end are numeric, +n+ is added for each iteration.
378  * Otherwise <code>step</code> invokes <code>succ</code> to iterate through
379  * range elements.
380  *
381  * If no block is given, an enumerator is returned instead.
382  *
383  * range = Xs.new(1)..Xs.new(10)
384  * range.step(2) {|x| puts x}
385  * puts
386  * range.step(3) {|x| puts x}
387  *
388  * <em>produces:</em>
389  *
390  * 1 x
391  * 3 xxx
392  * 5 xxxxx
393  * 7 xxxxxxx
394  * 9 xxxxxxxxx
395  *
396  * 1 x
397  * 4 xxxx
398  * 7 xxxxxxx
399  * 10 xxxxxxxxxx
400  *
401  * See Range for the definition of class Xs.
402  */
403 
404 
405 static VALUE
407 {
408  VALUE b, e, step, tmp;
409 
411 
412  b = RANGE_BEG(range);
413  e = RANGE_END(range);
414  if (argc == 0) {
415  step = INT2FIX(1);
416  }
417  else {
418  rb_scan_args(argc, argv, "01", &step);
419  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
420  step = rb_to_int(step);
421  }
422  if (rb_funcall(step, '<', 1, INT2FIX(0))) {
423  rb_raise(rb_eArgError, "step can't be negative");
424  }
425  else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
426  rb_raise(rb_eArgError, "step can't be 0");
427  }
428  }
429 
430  if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
431  long end = FIX2LONG(e);
432  long i, unit = FIX2LONG(step);
433 
434  if (!EXCL(range))
435  end += 1;
436  i = FIX2LONG(b);
437  while (i < end) {
438  rb_yield(LONG2NUM(i));
439  if (i + unit < i) break;
440  i += unit;
441  }
442 
443  }
444  else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
445  VALUE args[2], iter[2];
446 
447  args[0] = rb_sym_to_s(e);
448  args[1] = EXCL(range) ? Qtrue : Qfalse;
449  iter[0] = INT2FIX(1);
450  iter[1] = step;
451  rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
452  }
453  else if (ruby_float_step(b, e, step, EXCL(range))) {
454  /* done */
455  }
456  else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
457  !NIL_P(rb_check_to_integer(b, "to_int")) ||
458  !NIL_P(rb_check_to_integer(e, "to_int"))) {
459  ID op = EXCL(range) ? '<' : idLE;
460  VALUE v = b;
461  int i = 0;
462 
463  while (RTEST(rb_funcall(v, op, 1, e))) {
464  rb_yield(v);
465  i++;
466  v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
467  }
468  }
469  else {
470  tmp = rb_check_string_type(b);
471 
472  if (!NIL_P(tmp)) {
473  VALUE args[2], iter[2];
474 
475  b = tmp;
476  args[0] = e;
477  args[1] = EXCL(range) ? Qtrue : Qfalse;
478  iter[0] = INT2FIX(1);
479  iter[1] = step;
480  rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
481  }
482  else {
483  VALUE args[2];
484 
485  if (!discrete_object_p(b)) {
486  rb_raise(rb_eTypeError, "can't iterate from %s",
487  rb_obj_classname(b));
488  }
489  args[0] = INT2FIX(1);
490  args[1] = step;
492  }
493  }
494  return range;
495 }
496 
497 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
498 union int64_double {
499  int64_t i;
500  double d;
501 };
502 
503 static VALUE
504 int64_as_double_to_num(int64_t i)
505 {
506  union int64_double convert;
507  if (i < 0) {
508  convert.i = -i;
509  return DBL2NUM(-convert.d);
510  }
511  else {
512  convert.i = i;
513  return DBL2NUM(convert.d);
514  }
515 }
516 
517 static int64_t
518 double_as_int64(double d)
519 {
520  union int64_double convert;
521  convert.d = fabs(d);
522  return d < 0 ? -convert.i : convert.i;
523 }
524 #endif
525 
526 static int
528 {
529  VALUE is_int = rb_check_funcall(v, id_integer_p, 0, 0);
530  return RTEST(is_int) && is_int != Qundef;
531 }
532 
533 /*
534  * call-seq:
535  * rng.bsearch {|obj| block } -> value
536  *
537  * By using binary search, finds a value in range which meets the given
538  * condition in O(log n) where n is the size of the range.
539  *
540  * You can use this method in two use cases: a find-minimum mode and
541  * a find-any mode. In either case, the elements of the range must be
542  * monotone (or sorted) with respect to the block.
543  *
544  * In find-minimum mode (this is a good choice for typical use case),
545  * the block must return true or false, and there must be a value x
546  * so that:
547  *
548  * - the block returns false for any value which is less than x, and
549  * - the block returns true for any value which is greater than or
550  * equal to i.
551  *
552  * If x is within the range, this method returns the value x.
553  * Otherwise, it returns nil.
554  *
555  * ary = [0, 4, 7, 10, 12]
556  * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
557  * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
558  * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
559  * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
560  *
561  * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
562  *
563  * In find-any mode (this behaves like libc's bsearch(3)), the block
564  * must return a number, and there must be two values x and y (x <= y)
565  * so that:
566  *
567  * - the block returns a positive number for v if v < x,
568  * - the block returns zero for v if x <= v < y, and
569  * - the block returns a negative number for v if y <= v.
570  *
571  * This method returns any value which is within the intersection of
572  * the given range and x...y (if any). If there is no value that
573  * satisfies the condition, it returns nil.
574  *
575  * ary = [0, 100, 100, 100, 200]
576  * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
577  * (0..4).bsearch {|i| 300 - ary[i] } #=> nil
578  * (0..4).bsearch {|i| 50 - ary[i] } #=> nil
579  *
580  * You must not mix the two modes at a time; the block must always
581  * return either true/false, or always return a number. It is
582  * undefined which value is actually picked up at each iteration.
583  */
584 
585 static VALUE
587 {
588  VALUE beg, end;
589  int smaller, satisfied = 0;
590 
591  /* Implementation notes:
592  * Floats are handled by mapping them to 64 bits integers.
593  * Apart from sign issues, floats and their 64 bits integer have the
594  * same order, assuming they are represented as exponent followed
595  * by the mantissa. This is true with or without implicit bit.
596  *
597  * Finding the average of two ints needs to be careful about
598  * potential overflow (since float to long can use 64 bits)
599  * as well as the fact that -1/2 can be 0 or -1 in C89.
600  *
601  * Note that -0.0 is mapped to the same int as 0.0 as we don't want
602  * (-1...0.0).bsearch to yield -0.0.
603  */
604 
605 #define BSEARCH_CHECK(val) \
606  do { \
607  VALUE v = rb_yield(val); \
608  if (FIXNUM_P(v)) { \
609  if (FIX2INT(v) == 0) return val; \
610  smaller = FIX2INT(v) < 0; \
611  } \
612  else if (v == Qtrue) { \
613  satisfied = 1; \
614  smaller = 1; \
615  } \
616  else if (v == Qfalse || v == Qnil) { \
617  smaller = 0; \
618  } \
619  else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
620  int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
621  if (!cmp) return val; \
622  smaller = cmp < 0; \
623  } \
624  else { \
625  rb_raise(rb_eTypeError, "wrong argument type %s" \
626  " (must be numeric, true, false or nil)", \
627  rb_obj_classname(v)); \
628  } \
629  } while (0)
630 
631 #define BSEARCH(conv) \
632  do { \
633  RETURN_ENUMERATOR(range, 0, 0); \
634  if (EXCL(range)) high--; \
635  org_high = high; \
636  while (low < high) { \
637  mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
638  : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
639  BSEARCH_CHECK(conv(mid)); \
640  if (smaller) { \
641  high = mid; \
642  } \
643  else { \
644  low = mid + 1; \
645  } \
646  } \
647  if (low == org_high) { \
648  BSEARCH_CHECK(conv(low)); \
649  if (!smaller) return Qnil; \
650  } \
651  if (!satisfied) return Qnil; \
652  return conv(low); \
653  } while (0)
654 
655 
656  beg = RANGE_BEG(range);
657  end = RANGE_END(range);
658 
659  if (FIXNUM_P(beg) && FIXNUM_P(end)) {
660  long low = FIX2LONG(beg);
661  long high = FIX2LONG(end);
662  long mid, org_high;
663  BSEARCH(INT2FIX);
664  }
665 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
666  else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
667  int64_t low = double_as_int64(RFLOAT_VALUE(rb_Float(beg)));
668  int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end)));
669  int64_t mid, org_high;
670  BSEARCH(int64_as_double_to_num);
671  }
672 #endif
673  else if (is_integer_p(beg) && is_integer_p(end)) {
674  VALUE low = rb_to_int(beg);
675  VALUE high = rb_to_int(end);
676  VALUE mid, org_high;
677  RETURN_ENUMERATOR(range, 0, 0);
678  if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1));
679  org_high = high;
680 
681  while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
682  mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
683  BSEARCH_CHECK(mid);
684  if (smaller) {
685  high = mid;
686  }
687  else {
688  low = rb_funcall(mid, '+', 1, INT2FIX(1));
689  }
690  }
691  if (rb_equal(low, org_high)) {
692  BSEARCH_CHECK(low);
693  if (!smaller) return Qnil;
694  }
695  if (!satisfied) return Qnil;
696  return low;
697  }
698  else {
699  rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
700  }
701  return range;
702 }
703 
704 static VALUE
706 {
707  rb_yield(v);
708  return Qnil;
709 }
710 
711 static VALUE
713 {
715  return Qnil;
716 }
717 
718 /*
719  * call-seq:
720  * rng.size -> num
721  *
722  * Returns the number of elements in the range. Both the begin and the end of
723  * the Range must be Numeric, otherwise nil is returned.
724  *
725  * (10..20).size #=> 11
726  * ('a'..'z').size #=> nil
727  * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
728  */
729 
730 static VALUE
732 {
733  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
735  return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
736  }
737  return Qnil;
738 }
739 
740 static VALUE
742 {
743  return range_size(range);
744 }
745 
746 /*
747  * call-seq:
748  * rng.each {| i | block } -> rng
749  * rng.each -> an_enumerator
750  *
751  * Iterates over the elements of range, passing each in turn to the
752  * block.
753  *
754  * The +each+ method can only be used if the begin object of the range
755  * supports the +succ+ method. A TypeError is raised if the object
756  * does not have +succ+ method defined (like Float).
757  *
758  * If no block is given, an enumerator is returned instead.
759  *
760  * (10..15).each {|n| print n, ' ' }
761  * # prints: 10 11 12 13 14 15
762  *
763  * (2.5..5).each {|n| print n, ' ' }
764  * # raises: TypeError: can't iterate from Float
765  */
766 
767 static VALUE
769 {
770  VALUE beg, end;
771 
773 
774  beg = RANGE_BEG(range);
775  end = RANGE_END(range);
776 
777  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
778  long lim = FIX2LONG(end);
779  long i;
780 
781  if (!EXCL(range))
782  lim += 1;
783  for (i = FIX2LONG(beg); i < lim; i++) {
784  rb_yield(LONG2FIX(i));
785  }
786  }
787  else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
788  VALUE args[2];
789 
790  args[0] = rb_sym_to_s(end);
791  args[1] = EXCL(range) ? Qtrue : Qfalse;
792  rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
793  }
794  else {
795  VALUE tmp = rb_check_string_type(beg);
796 
797  if (!NIL_P(tmp)) {
798  VALUE args[2];
799 
800  args[0] = end;
801  args[1] = EXCL(range) ? Qtrue : Qfalse;
802  rb_block_call(tmp, rb_intern("upto"), 2, args, each_i, 0);
803  }
804  else {
805  if (!discrete_object_p(beg)) {
806  rb_raise(rb_eTypeError, "can't iterate from %s",
807  rb_obj_classname(beg));
808  }
810  }
811  }
812  return range;
813 }
814 
815 /*
816  * call-seq:
817  * rng.begin -> obj
818  *
819  * Returns the object that defines the beginning of the range.
820  *
821  * (1..10).begin #=> 1
822  */
823 
824 static VALUE
826 {
827  return RANGE_BEG(range);
828 }
829 
830 
831 /*
832  * call-seq:
833  * rng.end -> obj
834  *
835  * Returns the object that defines the end of the range.
836  *
837  * (1..10).end #=> 10
838  * (1...10).end #=> 10
839  */
840 
841 
842 static VALUE
844 {
845  return RANGE_END(range);
846 }
847 
848 
849 static VALUE
851 {
852  VALUE *ary = (VALUE *)cbarg;
853  long n = NUM2LONG(ary[0]);
854 
855  if (n <= 0) {
856  rb_iter_break();
857  }
858  rb_ary_push(ary[1], i);
859  n--;
860  ary[0] = INT2NUM(n);
861  return Qnil;
862 }
863 
864 /*
865  * call-seq:
866  * rng.first -> obj
867  * rng.first(n) -> an_array
868  *
869  * Returns the first object in the range, or an array of the first +n+
870  * elements.
871  *
872  * (10..20).first #=> 10
873  * (10..20).first(3) #=> [10, 11, 12]
874  */
875 
876 static VALUE
878 {
879  VALUE n, ary[2];
880 
881  if (argc == 0) return RANGE_BEG(range);
882 
883  rb_scan_args(argc, argv, "1", &n);
884  ary[0] = n;
885  ary[1] = rb_ary_new2(NUM2LONG(n));
886  rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
887 
888  return ary[1];
889 }
890 
891 
892 /*
893  * call-seq:
894  * rng.last -> obj
895  * rng.last(n) -> an_array
896  *
897  * Returns the last object in the range,
898  * or an array of the last +n+ elements.
899  *
900  * Note that with no arguments +last+ will return the object that defines
901  * the end of the range even if #exclude_end? is +true+.
902  *
903  * (10..20).last #=> 20
904  * (10...20).last #=> 20
905  * (10..20).last(3) #=> [18, 19, 20]
906  * (10...20).last(3) #=> [17, 18, 19]
907  */
908 
909 static VALUE
911 {
912  if (argc == 0) return RANGE_END(range);
913  return rb_ary_last(argc, argv, rb_Array(range));
914 }
915 
916 
917 /*
918  * call-seq:
919  * rng.min -> obj
920  * rng.min {| a,b | block } -> obj
921  *
922  * Returns the minimum value in the range. Returns +nil+ if the begin
923  * value of the range is larger than the end value.
924  *
925  * Can be given an optional block to override the default comparison
926  * method <code>a <=> b</code>.
927  *
928  * (10..20).min #=> 10
929  */
930 
931 
932 static VALUE
934 {
935  if (rb_block_given_p()) {
936  return rb_call_super(0, 0);
937  }
938  else {
939  VALUE b = RANGE_BEG(range);
940  VALUE e = RANGE_END(range);
941  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
942 
943  if (c > 0 || (c == 0 && EXCL(range)))
944  return Qnil;
945  return b;
946  }
947 }
948 
949 /*
950  * call-seq:
951  * rng.max -> obj
952  * rng.max {| a,b | block } -> obj
953  *
954  * Returns the maximum value in the range. Returns +nil+ if the begin
955  * value of the range larger than the end value.
956  *
957  * Can be given an optional block to override the default comparison
958  * method <code>a <=> b</code>.
959  *
960  * (10..20).max #=> 20
961  */
962 
963 static VALUE
965 {
966  VALUE e = RANGE_END(range);
967  int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
968 
969  if (rb_block_given_p() || (EXCL(range) && !nm)) {
970  return rb_call_super(0, 0);
971  }
972  else {
973  VALUE b = RANGE_BEG(range);
974  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
975 
976  if (c > 0)
977  return Qnil;
978  if (EXCL(range)) {
979  if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
980  rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
981  }
982  if (c == 0) return Qnil;
983  if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
984  rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
985  }
986  if (FIXNUM_P(e)) {
987  return LONG2NUM(FIX2LONG(e) - 1);
988  }
989  return rb_funcall(e, '-', 1, INT2FIX(1));
990  }
991  return e;
992  }
993 }
994 
995 int
996 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
997 {
998  VALUE b, e;
999  int excl;
1000 
1002  b = RANGE_BEG(range);
1003  e = RANGE_END(range);
1004  excl = EXCL(range);
1005  }
1006  else {
1007  if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
1008  if (!rb_respond_to(range, id_end)) return (int)Qfalse;
1009  b = rb_funcall(range, id_beg, 0);
1010  e = rb_funcall(range, id_end, 0);
1011  excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
1012  }
1013  *begp = b;
1014  *endp = e;
1015  *exclp = excl;
1016  return (int)Qtrue;
1017 }
1018 
1019 VALUE
1020 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
1021 {
1022  long beg, end, origbeg, origend;
1023  VALUE b, e;
1024  int excl;
1025 
1026  if (!rb_range_values(range, &b, &e, &excl))
1027  return Qfalse;
1028  beg = NUM2LONG(b);
1029  end = NUM2LONG(e);
1030  origbeg = beg;
1031  origend = end;
1032  if (beg < 0) {
1033  beg += len;
1034  if (beg < 0)
1035  goto out_of_range;
1036  }
1037  if (end < 0)
1038  end += len;
1039  if (!excl)
1040  end++; /* include end point */
1041  if (err == 0 || err == 2) {
1042  if (beg > len)
1043  goto out_of_range;
1044  if (end > len)
1045  end = len;
1046  }
1047  len = end - beg;
1048  if (len < 0)
1049  len = 0;
1050 
1051  *begp = beg;
1052  *lenp = len;
1053  return Qtrue;
1054 
1055  out_of_range:
1056  if (err) {
1057  rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
1058  origbeg, excl ? "." : "", origend);
1059  }
1060  return Qnil;
1061 }
1062 
1063 /*
1064  * call-seq:
1065  * rng.to_s -> string
1066  *
1067  * Convert this range object to a printable form (using #to_s to convert the
1068  * begin and end objects).
1069  */
1070 
1071 static VALUE
1073 {
1074  VALUE str, str2;
1075 
1077  str2 = rb_obj_as_string(RANGE_END(range));
1078  str = rb_str_dup(str);
1079  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1080  rb_str_append(str, str2);
1081  OBJ_INFECT(str, range);
1082 
1083  return str;
1084 }
1085 
1086 static VALUE
1088 {
1089  VALUE str, str2;
1090 
1091  if (recur) {
1092  return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
1093  }
1094  str = rb_inspect(RANGE_BEG(range));
1095  str2 = rb_inspect(RANGE_END(range));
1096  str = rb_str_dup(str);
1097  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1098  rb_str_append(str, str2);
1099  OBJ_INFECT(str, range);
1100 
1101  return str;
1102 }
1103 
1104 /*
1105  * call-seq:
1106  * rng.inspect -> string
1107  *
1108  * Convert this range object to a printable form (using
1109  * <code>inspect</code> to convert the begin and end
1110  * objects).
1111  */
1112 
1113 
1114 static VALUE
1116 {
1118 }
1119 
1120 /*
1121  * call-seq:
1122  * rng === obj -> true or false
1123  *
1124  * Returns <code>true</code> if +obj+ is an element of the range,
1125  * <code>false</code> otherwise. Conveniently, <code>===</code> is the
1126  * comparison operator used by <code>case</code> statements.
1127  *
1128  * case 79
1129  * when 1..50 then print "low\n"
1130  * when 51..75 then print "medium\n"
1131  * when 76..100 then print "high\n"
1132  * end
1133  *
1134  * <em>produces:</em>
1135  *
1136  * high
1137  */
1138 
1139 static VALUE
1141 {
1142  return rb_funcall(range, rb_intern("include?"), 1, val);
1143 }
1144 
1145 
1146 /*
1147  * call-seq:
1148  * rng.member?(obj) -> true or false
1149  * rng.include?(obj) -> true or false
1150  *
1151  * Returns <code>true</code> if +obj+ is an element of
1152  * the range, <code>false</code> otherwise. If begin and end are
1153  * numeric, comparison is done according to the magnitude of the values.
1154  *
1155  * ("a".."z").include?("g") #=> true
1156  * ("a".."z").include?("A") #=> false
1157  * ("a".."z").include?("cc") #=> false
1158  */
1159 
1160 static VALUE
1162 {
1163  VALUE beg = RANGE_BEG(range);
1164  VALUE end = RANGE_END(range);
1165  int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1166  linear_object_p(beg) || linear_object_p(end);
1167 
1168  if (nv ||
1169  !NIL_P(rb_check_to_integer(beg, "to_int")) ||
1170  !NIL_P(rb_check_to_integer(end, "to_int"))) {
1171  if (r_le(beg, val)) {
1172  if (EXCL(range)) {
1173  if (r_lt(val, end))
1174  return Qtrue;
1175  }
1176  else {
1177  if (r_le(val, end))
1178  return Qtrue;
1179  }
1180  }
1181  return Qfalse;
1182  }
1183  else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
1184  RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
1185  if (NIL_P(val)) return Qfalse;
1186  if (RB_TYPE_P(val, T_STRING)) {
1187  if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
1188  return Qfalse;
1189  else {
1190  char b = RSTRING_PTR(beg)[0];
1191  char e = RSTRING_PTR(end)[0];
1192  char v = RSTRING_PTR(val)[0];
1193 
1194  if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
1195  if (b <= v && v < e) return Qtrue;
1196  if (!EXCL(range) && v == e) return Qtrue;
1197  return Qfalse;
1198  }
1199  }
1200  }
1201  }
1202  /* TODO: ruby_frame->this_func = rb_intern("include?"); */
1203  return rb_call_super(1, &val);
1204 }
1205 
1206 
1207 /*
1208  * call-seq:
1209  * rng.cover?(obj) -> true or false
1210  *
1211  * Returns <code>true</code> if +obj+ is between the begin and end of
1212  * the range.
1213  *
1214  * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1215  * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1216  *
1217  * ("a".."z").cover?("c") #=> true
1218  * ("a".."z").cover?("5") #=> false
1219  * ("a".."z").cover?("cc") #=> true
1220  */
1221 
1222 static VALUE
1224 {
1225  VALUE beg, end;
1226 
1227  beg = RANGE_BEG(range);
1228  end = RANGE_END(range);
1229  if (r_le(beg, val)) {
1230  if (EXCL(range)) {
1231  if (r_lt(val, end))
1232  return Qtrue;
1233  }
1234  else {
1235  if (r_le(val, end))
1236  return Qtrue;
1237  }
1238  }
1239  return Qfalse;
1240 }
1241 
1242 static VALUE
1244 {
1245  VALUE v;
1247 
1248  v = (VALUE)m;
1249 
1253  return v;
1254 }
1255 
1256 static VALUE
1258 {
1259  if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
1260  rb_raise(rb_eTypeError, "not a dumped range object");
1261  }
1262 
1267  return range;
1268 }
1269 
1270 static VALUE
1272 {
1273  /* rb_struct_alloc_noinit itself should not be used because
1274  * rb_marshal_define_compat uses equality of allocation function */
1275  return rb_struct_alloc_noinit(klass);
1276 }
1277 
1278 /* A <code>Range</code> represents an interval---a set of values with a
1279  * beginning and an end. Ranges may be constructed using the
1280  * <em>s</em><code>..</code><em>e</em> and
1281  * <em>s</em><code>...</code><em>e</em> literals, or with
1282  * Range::new. Ranges constructed using <code>..</code>
1283  * run from the beginning to the end inclusively. Those created using
1284  * <code>...</code> exclude the end value. When used as an iterator,
1285  * ranges return each value in the sequence.
1286  *
1287  * (-1..-5).to_a #=> []
1288  * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
1289  * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
1290  * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
1291  *
1292  * == Custom Objects in Ranges
1293  *
1294  * Ranges can be constructed using any objects that can be compared
1295  * using the <code><=></code> operator.
1296  * Methods that treat the range as a sequence (#each and methods inherited
1297  * from Enumerable) expect the begin object to implement a
1298  * <code>succ</code> method to return the next object in sequence.
1299  * The #step and #include? methods require the begin
1300  * object to implement <code>succ</code> or to be numeric.
1301  *
1302  * In the <code>Xs</code> class below both <code><=></code> and
1303  * <code>succ</code> are implemented so <code>Xs</code> can be used
1304  * to construct ranges. Note that the Comparable module is included
1305  * so the <code>==</code> method is defined in terms of <code><=></code>.
1306  *
1307  * class Xs # represent a string of 'x's
1308  * include Comparable
1309  * attr :length
1310  * def initialize(n)
1311  * @length = n
1312  * end
1313  * def succ
1314  * Xs.new(@length + 1)
1315  * end
1316  * def <=>(other)
1317  * @length <=> other.length
1318  * end
1319  * def to_s
1320  * sprintf "%2d #{inspect}", @length
1321  * end
1322  * def inspect
1323  * 'x' * @length
1324  * end
1325  * end
1326  *
1327  * An example of using <code>Xs</code> to construct a range:
1328  *
1329  * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1330  * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1331  * r.member?(Xs.new(5)) #=> true
1332  *
1333  */
1334 
1335 void
1337 {
1338 #undef rb_intern
1339 #define rb_intern(str) rb_intern_const(str)
1340 
1341  id_cmp = rb_intern("<=>");
1342  id_succ = rb_intern("succ");
1343  id_beg = rb_intern("begin");
1344  id_end = rb_intern("end");
1345  id_excl = rb_intern("excl");
1346  id_integer_p = rb_intern("integer?");
1347  id_div = rb_intern("div");
1348 
1350  "Range", rb_cObject, range_alloc,
1351  "begin", "end", "excl", NULL);
1352 
1355  rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1356  rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1357  rb_define_method(rb_cRange, "==", range_eq, 1);
1358  rb_define_method(rb_cRange, "===", range_eqq, 1);
1359  rb_define_method(rb_cRange, "eql?", range_eql, 1);
1360  rb_define_method(rb_cRange, "hash", range_hash, 0);
1361  rb_define_method(rb_cRange, "each", range_each, 0);
1362  rb_define_method(rb_cRange, "step", range_step, -1);
1363  rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
1364  rb_define_method(rb_cRange, "begin", range_begin, 0);
1365  rb_define_method(rb_cRange, "end", range_end, 0);
1366  rb_define_method(rb_cRange, "first", range_first, -1);
1367  rb_define_method(rb_cRange, "last", range_last, -1);
1368  rb_define_method(rb_cRange, "min", range_min, 0);
1369  rb_define_method(rb_cRange, "max", range_max, 0);
1370  rb_define_method(rb_cRange, "size", range_size, 0);
1371  rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1372  rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1373 
1374  rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1375 
1376  rb_define_method(rb_cRange, "member?", range_include, 1);
1377  rb_define_method(rb_cRange, "include?", range_include, 1);
1378  rb_define_method(rb_cRange, "cover?", range_cover, 1);
1379 }
VALUE rb_hash(VALUE obj)
Definition: hash.c:106
#define T_OBJECT
Definition: ruby.h:477
static int is_integer_p(VALUE v)
Definition: range.c:527
#define RANGE_BEG(r)
Definition: range.c:25
#define FALSE
Definition: nkf.h:174
#define INT2NUM(x)
Definition: ruby.h:1296
void Init_Range(void)
Definition: range.c:1336
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:996
static VALUE range_max(VALUE range)
Definition: range.c:964
#define FIXNUM_FLAG
Definition: ruby.h:430
static VALUE range_dumper(VALUE range)
Definition: range.c:1243
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2139
static VALUE range_include(VALUE range, VALUE val)
Definition: range.c:1161
#define Qtrue
Definition: ruby.h:426
static VALUE each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
Definition: range.c:705
#define RBOOL(v)
Definition: range.c:31
st_index_t rb_hash_end(st_index_t)
static int linear_object_p(VALUE obj)
Definition: range.c:333
static ID id_succ
Definition: range.c:23
Definition: id.h:81
static VALUE range_bsearch(VALUE range)
Definition: range.c:586
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:707
static VALUE range_loader(VALUE range, VALUE obj)
Definition: range.c:1257
static void range_modify(VALUE range)
Definition: range.c:79
static VALUE sym_each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
Definition: range.c:712
VALUE rb_ary_last(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1337
VALUE rb_eTypeError
Definition: error.c:548
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:235
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:900
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static ID id_excl
Definition: range.c:23
static VALUE step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
Definition: range.c:308
static VALUE inspect_range(VALUE range, VALUE dummy, int recur)
Definition: range.c:1087
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:781
VALUE rb_to_int(VALUE)
Definition: object.c:2700
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
#define EXCL(r)
Definition: range.c:33
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4992
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:646
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:808
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
st_data_t st_index_t
Definition: st.h:48
#define RGENGC_WB_PROTECTED_OBJECT
Definition: ruby.h:723
static VALUE range_to_s(VALUE range)
Definition: range.c:1072
#define FIXNUM_P(f)
Definition: ruby.h:347
VALUE rb_Float(VALUE)
Definition: object.c:2918
VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end)
Definition: range.c:70
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2686
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2909
VALUE rb_eRangeError
Definition: error.c:552
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
#define rb_ary_new2
Definition: intern.h:90
static void range_each_func(VALUE range, rb_block_call_func *func, VALUE arg)
Definition: range.c:266
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:967
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1519
static VALUE recursive_eql(VALUE range, VALUE obj, int recur)
Definition: range.c:202
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1672
static VALUE range_eql(VALUE range, VALUE obj)
Definition: range.c:230
static VALUE range_size(VALUE range)
Definition: range.c:731
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1521
void rb_iter_break(void)
Definition: vm.c:1154
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:799
static VALUE range_step(int argc, VALUE *argv, VALUE range)
Definition: range.c:406
VALUE rb_Array(VALUE)
Definition: object.c:3038
static VALUE range_initialize_copy(VALUE range, VALUE orig)
Definition: range.c:109
int rb_block_given_p(void)
Definition: eval.c:712
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1561
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5003
#define BSEARCH(conv)
static ID id_div
Definition: range.c:23
static VALUE range_enum_size(VALUE range, VALUE args, VALUE eobj)
Definition: range.c:741
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1011
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1822
#define NIL_P(v)
Definition: ruby.h:438
#define ISASCII(c)
Definition: ruby.h:1774
static VALUE range_initialize(int argc, VALUE *argv, VALUE range)
Definition: range.c:97
static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
Definition: range.c:850
#define FLONUM_P(x)
Definition: ruby.h:367
#define T_FLOAT
Definition: ruby.h:481
int argc
Definition: ruby.c:131
#define Qfalse
Definition: ruby.h:425
static VALUE range_step_size(VALUE range, VALUE args, VALUE eobj)
Definition: range.c:348
#define T_BIGNUM
Definition: ruby.h:487
#define range(low, item, hi)
Definition: date_strftime.c:21
#define BSEARCH_CHECK(val)
#define rb_str_new2
Definition: intern.h:840
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1804
int err
Definition: win32.c:114
static VALUE range_first(int argc, VALUE *argv, VALUE range)
Definition: range.c:877
VALUE rb_sym_to_s(VALUE)
Definition: string.c:8481
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1791
static ID id_cmp
Definition: range.c:23
static ID id_end
Definition: range.c:23
#define RSTRING_LEN(str)
Definition: ruby.h:841
#define rb_intern(str)
VALUE rb_yield(VALUE)
Definition: vm_eval.c:948
#define TRUE
Definition: nkf.h:175
static VALUE range_check(VALUE *args)
Definition: range.c:43
static VALUE range_min(VALUE range)
Definition: range.c:933
static VALUE range_hash(VALUE range)
Definition: range.c:249
VALUE rb_mEnumerable
Definition: enum.c:20
int rb_eql(VALUE, VALUE)
Definition: object.c:100
static void range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
Definition: range.c:49
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
static VALUE range_exclude_end_p(VALUE range)
Definition: range.c:127
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
unsigned long ID
Definition: ruby.h:89
#define Qnil
Definition: ruby.h:427
static int discrete_object_p(VALUE obj)
Definition: range.c:326
#define RANGE_END(r)
Definition: range.c:26
#define RANGE_SET_END(r, v)
Definition: range.c:29
#define BUILTIN_TYPE(x)
Definition: ruby.h:502
unsigned long VALUE
Definition: ruby.h:88
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:237
#define RBASIC(obj)
Definition: ruby.h:1116
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1576
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:410
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:275
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1583
static VALUE sym_step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
Definition: range.c:290
VALUE rb_str_dup(VALUE)
Definition: string.c:1062
#define RANGE_SET_EXCL(r, v)
Definition: range.c:30
#define LONG2NUM(x)
Definition: ruby.h:1317
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1651
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:1020
static VALUE recursive_equal(VALUE range, VALUE obj, int recur)
Definition: range.c:133
#define recur(fmt)
#define RSTRING_PTR(str)
Definition: ruby.h:845
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
static VALUE range_end(VALUE range)
Definition: range.c:843
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
static VALUE range_inspect(VALUE range)
Definition: range.c:1115
#define INT2FIX(i)
Definition: ruby.h:231
static int r_lt(VALUE a, VALUE b)
Definition: range.c:173
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
static VALUE range_begin(VALUE range)
Definition: range.c:825
VALUE rb_cRange
Definition: range.c:22
static VALUE range_last(int argc, VALUE *argv, VALUE range)
Definition: range.c:910
static ID id_beg
Definition: range.c:23
#define FL_WB_PROTECTED
Definition: ruby.h:1134
VALUE rb_check_string_type(VALUE)
Definition: string.c:1678
#define RANGE_EXCL(r)
Definition: range.c:27
#define LONG2FIX(i)
Definition: ruby.h:232
#define RTEST(v)
Definition: ruby.h:437
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:115
#define T_STRING
Definition: ruby.h:482
#define OBJ_INFECT(x, s)
Definition: ruby.h:1188
st_index_t rb_hash_uint(st_index_t, st_index_t)
static VALUE range_alloc(VALUE klass)
Definition: range.c:1271
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
static VALUE range_each(VALUE range)
Definition: range.c:768
Definition: ruby.h:762
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:288
VALUE rb_inspect(VALUE)
Definition: object.c:470
VALUE rb_str_intern(VALUE)
Definition: string.c:7467
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1165
static VALUE range_eqq(VALUE range, VALUE val)
Definition: range.c:1140
static VALUE range_eq(VALUE range, VALUE obj)
Definition: range.c:162
#define SYMBOL_P(x)
Definition: ruby.h:354
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:345
#define Qundef
Definition: ruby.h:428
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1595
static int r_le(VALUE a, VALUE b)
Definition: range.c:185
static VALUE range_cover(VALUE range, VALUE val)
Definition: range.c:1223
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2297
static ID id_integer_p
Definition: range.c:23
#define RANGE_SET_BEG(r, v)
Definition: range.c:28
VALUE rb_eArgError
Definition: error.c:549
#define NUM2LONG(x)
Definition: ruby.h:600
static VALUE range_failed(void)
Definition: range.c:36
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1296
char ** argv
Definition: ruby.c:132
#define DBL2NUM(dbl)
Definition: ruby.h:815