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