Ruby  2.0.0p648(2015-12-16revision53162)
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
258 range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
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
282 sym_step_i(VALUE i, void *arg)
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
689 sym_each_i(VALUE v, void *arg)
690 {
692  return Qnil;
693 }
694 
695 /*
696  * call-seq:
697  * rng.size -> num
698  *
699  * Returns the number of elements in the range. Both the begin and the end of
700  * the Range must be Numeric, otherwise nil is returned.
701  *
702  * (10..20).size #=> 11
703  * ('a'..'z').size #=> nil
704  * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
705  */
706 
707 static VALUE
709 {
710  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
712  return num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
713  }
714  return Qnil;
715 }
716 
717 /*
718  * call-seq:
719  * rng.each {| i | block } -> rng
720  * rng.each -> an_enumerator
721  *
722  * Iterates over the elements of range, passing each in turn to the
723  * block.
724  *
725  * The +each+ method can only be used if the begin object of the range
726  * supports the +succ+ method. A TypeError is raised if the object
727  * does not have +succ+ method defined (like Float).
728  *
729  * If no block is given, an enumerator is returned instead.
730  *
731  * (10..15).each {|n| print n, ' ' }
732  * # prints: 10 11 12 13 14 15
733  *
734  * (2.5..5).each {|n| print n, ' ' }
735  * # raises: TypeError: can't iterate from Float
736  */
737 
738 static VALUE
740 {
741  VALUE beg, end;
742 
743  RETURN_SIZED_ENUMERATOR(range, 0, 0, range_size);
744 
745  beg = RANGE_BEG(range);
746  end = RANGE_END(range);
747 
748  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
749  long lim = FIX2LONG(end);
750  long i;
751 
752  if (!EXCL(range))
753  lim += 1;
754  for (i = FIX2LONG(beg); i < lim; i++) {
755  rb_yield(LONG2FIX(i));
756  }
757  }
758  else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
759  VALUE args[2];
760 
761  args[0] = rb_sym_to_s(end);
762  args[1] = EXCL(range) ? Qtrue : Qfalse;
763  rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
764  }
765  else {
766  VALUE tmp = rb_check_string_type(beg);
767 
768  if (!NIL_P(tmp)) {
769  VALUE args[2];
770 
771  args[0] = end;
772  args[1] = EXCL(range) ? Qtrue : Qfalse;
773  rb_block_call(tmp, rb_intern("upto"), 2, args, rb_yield, 0);
774  }
775  else {
776  if (!discrete_object_p(beg)) {
777  rb_raise(rb_eTypeError, "can't iterate from %s",
778  rb_obj_classname(beg));
779  }
780  range_each_func(range, each_i, NULL);
781  }
782  }
783  return range;
784 }
785 
786 /*
787  * call-seq:
788  * rng.begin -> obj
789  *
790  * Returns the object that defines the beginning of the range.
791  *
792  * (1..10).begin #=> 1
793  */
794 
795 static VALUE
797 {
798  return RANGE_BEG(range);
799 }
800 
801 
802 /*
803  * call-seq:
804  * rng.end -> obj
805  *
806  * Returns the object that defines the end of the range.
807  *
808  * (1..10).end #=> 10
809  * (1...10).end #=> 10
810  */
811 
812 
813 static VALUE
815 {
816  return RANGE_END(range);
817 }
818 
819 
820 static VALUE
822 {
823  long n = NUM2LONG(ary[0]);
824 
825  if (n <= 0) {
826  rb_iter_break();
827  }
828  rb_ary_push(ary[1], i);
829  n--;
830  ary[0] = INT2NUM(n);
831  return Qnil;
832 }
833 
834 /*
835  * call-seq:
836  * rng.first -> obj
837  * rng.first(n) -> an_array
838  *
839  * Returns the first object in the range, or an array of the first +n+
840  * elements.
841  *
842  * (10..20).first #=> 10
843  * (10..20).first(3) #=> [10, 11, 12]
844  */
845 
846 static VALUE
848 {
849  VALUE n, ary[2];
850 
851  if (argc == 0) return RANGE_BEG(range);
852 
853  rb_scan_args(argc, argv, "1", &n);
854  ary[0] = n;
855  ary[1] = rb_ary_new2(NUM2LONG(n));
856  rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
857 
858  return ary[1];
859 }
860 
861 
862 /*
863  * call-seq:
864  * rng.last -> obj
865  * rng.last(n) -> an_array
866  *
867  * Returns the last object in the range,
868  * or an array of the last +n+ elements.
869  *
870  * Note that with no arguments +last+ will return the object that defines
871  * the end of the range even if #exclude_end? is +true+.
872  *
873  * (10..20).last #=> 20
874  * (10...20).last #=> 20
875  * (10..20).last(3) #=> [18, 19, 20]
876  * (10...20).last(3) #=> [17, 18, 19]
877  */
878 
879 static VALUE
881 {
882  if (argc == 0) return RANGE_END(range);
883  return rb_ary_last(argc, argv, rb_Array(range));
884 }
885 
886 
887 /*
888  * call-seq:
889  * rng.min -> obj
890  * rng.min {| a,b | block } -> obj
891  *
892  * Returns the minimum value in the range. Returns +nil+ if the begin
893  * value of the range is larger than the end value.
894  *
895  * Can be given an optional block to override the default comparison
896  * method <code>a <=> b</code>.
897  *
898  * (10..20).min #=> 10
899  */
900 
901 
902 static VALUE
904 {
905  if (rb_block_given_p()) {
906  return rb_call_super(0, 0);
907  }
908  else {
909  VALUE b = RANGE_BEG(range);
910  VALUE e = RANGE_END(range);
911  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
912 
913  if (c > 0 || (c == 0 && EXCL(range)))
914  return Qnil;
915  return b;
916  }
917 }
918 
919 /*
920  * call-seq:
921  * rng.max -> obj
922  * rng.max {| a,b | block } -> obj
923  *
924  * Returns the maximum value in the range. Returns +nil+ if the begin
925  * value of the range larger than the end value.
926  *
927  * Can be given an optional block to override the default comparison
928  * method <code>a <=> b</code>.
929  *
930  * (10..20).max #=> 20
931  */
932 
933 static VALUE
935 {
936  VALUE e = RANGE_END(range);
937  int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
938 
939  if (rb_block_given_p() || (EXCL(range) && !nm)) {
940  return rb_call_super(0, 0);
941  }
942  else {
943  VALUE b = RANGE_BEG(range);
944  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
945 
946  if (c > 0)
947  return Qnil;
948  if (EXCL(range)) {
949  if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
950  rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
951  }
952  if (c == 0) return Qnil;
953  if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
954  rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
955  }
956  if (FIXNUM_P(e)) {
957  return LONG2NUM(FIX2LONG(e) - 1);
958  }
959  return rb_funcall(e, '-', 1, INT2FIX(1));
960  }
961  return e;
962  }
963 }
964 
965 int
966 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
967 {
968  VALUE b, e;
969  int excl;
970 
971  if (rb_obj_is_kind_of(range, rb_cRange)) {
972  b = RANGE_BEG(range);
973  e = RANGE_END(range);
974  excl = EXCL(range);
975  }
976  else {
977  if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
978  if (!rb_respond_to(range, id_end)) return (int)Qfalse;
979  b = rb_funcall(range, id_beg, 0);
980  e = rb_funcall(range, id_end, 0);
981  excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
982  }
983  *begp = b;
984  *endp = e;
985  *exclp = excl;
986  return (int)Qtrue;
987 }
988 
989 VALUE
990 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
991 {
992  long beg, end, origbeg, origend;
993  VALUE b, e;
994  int excl;
995 
996  if (!rb_range_values(range, &b, &e, &excl))
997  return Qfalse;
998  beg = NUM2LONG(b);
999  end = NUM2LONG(e);
1000  origbeg = beg;
1001  origend = end;
1002  if (beg < 0) {
1003  beg += len;
1004  if (beg < 0)
1005  goto out_of_range;
1006  }
1007  if (end < 0)
1008  end += len;
1009  if (!excl)
1010  end++; /* include end point */
1011  if (err == 0 || err == 2) {
1012  if (beg > len)
1013  goto out_of_range;
1014  if (end > len)
1015  end = len;
1016  }
1017  len = end - beg;
1018  if (len < 0)
1019  len = 0;
1020 
1021  *begp = beg;
1022  *lenp = len;
1023  return Qtrue;
1024 
1025  out_of_range:
1026  if (err) {
1027  rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
1028  origbeg, excl ? "." : "", origend);
1029  }
1030  return Qnil;
1031 }
1032 
1033 /*
1034  * call-seq:
1035  * rng.to_s -> string
1036  *
1037  * Convert this range object to a printable form (using #to_s to convert the
1038  * begin and end objects).
1039  */
1040 
1041 static VALUE
1043 {
1044  VALUE str, str2;
1045 
1046  str = rb_obj_as_string(RANGE_BEG(range));
1047  str2 = rb_obj_as_string(RANGE_END(range));
1048  str = rb_str_dup(str);
1049  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1050  rb_str_append(str, str2);
1051  OBJ_INFECT(str, str2);
1052 
1053  return str;
1054 }
1055 
1056 static VALUE
1057 inspect_range(VALUE range, VALUE dummy, int recur)
1058 {
1059  VALUE str, str2;
1060 
1061  if (recur) {
1062  return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
1063  }
1064  str = rb_inspect(RANGE_BEG(range));
1065  str2 = rb_inspect(RANGE_END(range));
1066  str = rb_str_dup(str);
1067  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1068  rb_str_append(str, str2);
1069  OBJ_INFECT(str, str2);
1070 
1071  return str;
1072 }
1073 
1074 /*
1075  * call-seq:
1076  * rng.inspect -> string
1077  *
1078  * Convert this range object to a printable form (using
1079  * <code>inspect</code> to convert the begin and end
1080  * objects).
1081  */
1082 
1083 
1084 static VALUE
1086 {
1087  return rb_exec_recursive(inspect_range, range, 0);
1088 }
1089 
1090 /*
1091  * call-seq:
1092  * rng === obj -> true or false
1093  *
1094  * Returns <code>true</code> if +obj+ is an element of the range,
1095  * <code>false</code> otherwise. Conveniently, <code>===</code> is the
1096  * comparison operator used by <code>case</code> statements.
1097  *
1098  * case 79
1099  * when 1..50 then print "low\n"
1100  * when 51..75 then print "medium\n"
1101  * when 76..100 then print "high\n"
1102  * end
1103  *
1104  * <em>produces:</em>
1105  *
1106  * high
1107  */
1108 
1109 static VALUE
1111 {
1112  return rb_funcall(range, rb_intern("include?"), 1, val);
1113 }
1114 
1115 
1116 /*
1117  * call-seq:
1118  * rng.member?(obj) -> true or false
1119  * rng.include?(obj) -> true or false
1120  *
1121  * Returns <code>true</code> if +obj+ is an element of
1122  * the range, <code>false</code> otherwise. If begin and end are
1123  * numeric, comparison is done according to the magnitude of the values.
1124  *
1125  * ("a".."z").include?("g") #=> true
1126  * ("a".."z").include?("A") #=> false
1127  * ("a".."z").include?("cc") #=> false
1128  */
1129 
1130 static VALUE
1132 {
1133  VALUE beg = RANGE_BEG(range);
1134  VALUE end = RANGE_END(range);
1135  int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1138 
1139  if (nv ||
1140  !NIL_P(rb_check_to_integer(beg, "to_int")) ||
1141  !NIL_P(rb_check_to_integer(end, "to_int"))) {
1142  if (r_le(beg, val)) {
1143  if (EXCL(range)) {
1144  if (r_lt(val, end))
1145  return Qtrue;
1146  }
1147  else {
1148  if (r_le(val, end))
1149  return Qtrue;
1150  }
1151  }
1152  return Qfalse;
1153  }
1154  else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
1155  RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
1156  if (NIL_P(val)) return Qfalse;
1157  if (RB_TYPE_P(val, T_STRING)) {
1158  if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
1159  return Qfalse;
1160  else {
1161  char b = RSTRING_PTR(beg)[0];
1162  char e = RSTRING_PTR(end)[0];
1163  char v = RSTRING_PTR(val)[0];
1164 
1165  if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
1166  if (b <= v && v < e) return Qtrue;
1167  if (!EXCL(range) && v == e) return Qtrue;
1168  return Qfalse;
1169  }
1170  }
1171  }
1172  }
1173  /* TODO: ruby_frame->this_func = rb_intern("include?"); */
1174  return rb_call_super(1, &val);
1175 }
1176 
1177 
1178 /*
1179  * call-seq:
1180  * rng.cover?(obj) -> true or false
1181  *
1182  * Returns <code>true</code> if +obj+ is between the begin and end of
1183  * the range.
1184  *
1185  * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1186  * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1187  *
1188  * ("a".."z").cover?("c") #=> true
1189  * ("a".."z").cover?("5") #=> false
1190  * ("a".."z").cover?("cc") #=> true
1191  */
1192 
1193 static VALUE
1195 {
1196  VALUE beg, end;
1197 
1198  beg = RANGE_BEG(range);
1199  end = RANGE_END(range);
1200  if (r_le(beg, val)) {
1201  if (EXCL(range)) {
1202  if (r_lt(val, end))
1203  return Qtrue;
1204  }
1205  else {
1206  if (r_le(val, end))
1207  return Qtrue;
1208  }
1209  }
1210  return Qfalse;
1211 }
1212 
1213 static VALUE
1215 {
1216  VALUE v;
1217  NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT);
1218 
1219  v = (VALUE)m;
1220 
1221  rb_ivar_set(v, id_excl, RANGE_EXCL(range));
1222  rb_ivar_set(v, id_beg, RANGE_BEG(range));
1223  rb_ivar_set(v, id_end, RANGE_END(range));
1224  return v;
1225 }
1226 
1227 static VALUE
1229 {
1230  if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
1231  rb_raise(rb_eTypeError, "not a dumped range object");
1232  }
1233 
1234  RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
1235  RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
1236  RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
1237  return range;
1238 }
1239 
1240 static VALUE
1242 {
1243  /* rb_struct_alloc_noinit itself should not be used because
1244  * rb_marshal_define_compat uses equality of allocaiton function */
1245  return rb_struct_alloc_noinit(klass);
1246 }
1247 
1248 /* A <code>Range</code> represents an interval---a set of values with a
1249  * beginning and an end. Ranges may be constructed using the
1250  * <em>s</em><code>..</code><em>e</em> and
1251  * <em>s</em><code>...</code><em>e</em> literals, or with
1252  * Range::new. Ranges constructed using <code>..</code>
1253  * run from the beginning to the end inclusively. Those created using
1254  * <code>...</code> exclude the end value. When used as an iterator,
1255  * ranges return each value in the sequence.
1256  *
1257  * (-1..-5).to_a #=> []
1258  * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
1259  * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
1260  * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
1261  *
1262  * == Custom Objects in Ranges
1263  *
1264  * Ranges can be constructed using any objects that can be compared
1265  * using the <code><=></code> operator.
1266  * Methods that treat the range as a sequence (#each and methods inherited
1267  * from Enumerable) expect the begin object to implement a
1268  * <code>succ</code> method to return the next object in sequence.
1269  * The #step and #include? methods require the begin
1270  * object to implement <code>succ</code> or to be numeric.
1271  *
1272  * In the <code>Xs</code> class below both <code><=></code> and
1273  * <code>succ</code> are implemented so <code>Xs</code> can be used
1274  * to construct ranges. Note that the Comparable module is included
1275  * so the <code>==</code> method is defined in terms of <code><=></code>.
1276  *
1277  * class Xs # represent a string of 'x's
1278  * include Comparable
1279  * attr :length
1280  * def initialize(n)
1281  * @length = n
1282  * end
1283  * def succ
1284  * Xs.new(@length + 1)
1285  * end
1286  * def <=>(other)
1287  * @length <=> other.length
1288  * end
1289  * def to_s
1290  * sprintf "%2d #{inspect}", @length
1291  * end
1292  * def inspect
1293  * 'x' * @length
1294  * end
1295  * end
1296  *
1297  * An example of using <code>Xs</code> to construct a range:
1298  *
1299  * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1300  * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1301  * r.member?(Xs.new(5)) #=> true
1302  *
1303  */
1304 
1305 void
1307 {
1308 #undef rb_intern
1309 #define rb_intern(str) rb_intern_const(str)
1310 
1311  id_cmp = rb_intern("<=>");
1312  id_succ = rb_intern("succ");
1313  id_beg = rb_intern("begin");
1314  id_end = rb_intern("end");
1315  id_excl = rb_intern("excl");
1316  id_integer_p = rb_intern("integer?");
1317  id_div = rb_intern("div");
1318 
1320  "Range", rb_cObject, range_alloc,
1321  "begin", "end", "excl", NULL);
1322 
1325  rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1326  rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1327  rb_define_method(rb_cRange, "==", range_eq, 1);
1328  rb_define_method(rb_cRange, "===", range_eqq, 1);
1329  rb_define_method(rb_cRange, "eql?", range_eql, 1);
1330  rb_define_method(rb_cRange, "hash", range_hash, 0);
1331  rb_define_method(rb_cRange, "each", range_each, 0);
1332  rb_define_method(rb_cRange, "step", range_step, -1);
1333  rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
1334  rb_define_method(rb_cRange, "begin", range_begin, 0);
1335  rb_define_method(rb_cRange, "end", range_end, 0);
1336  rb_define_method(rb_cRange, "first", range_first, -1);
1337  rb_define_method(rb_cRange, "last", range_last, -1);
1338  rb_define_method(rb_cRange, "min", range_min, 0);
1339  rb_define_method(rb_cRange, "max", range_max, 0);
1340  rb_define_method(rb_cRange, "size", range_size, 0);
1341  rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1342  rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1343 
1344  rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1345 
1346  rb_define_method(rb_cRange, "member?", range_include, 1);
1347  rb_define_method(rb_cRange, "include?", range_include, 1);
1348  rb_define_method(rb_cRange, "cover?", range_cover, 1);
1349 }
VALUE rb_hash(VALUE obj)
Definition: hash.c:66
#define T_OBJECT
Definition: ruby.h:485
static int is_integer_p(VALUE v)
Definition: range.c:504
#define RANGE_BEG(r)
Definition: range.c:25
#define FALSE
Definition: nkf.h:174
#define INT2NUM(x)
Definition: ruby.h:1178
void Init_Range(void)
Definition: range.c:1306
int i
Definition: win32ole.c:784
#define RSTRUCT(obj)
Definition: ruby.h:1105
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:966
static VALUE range_max(VALUE range)
Definition: range.c:934
#define FIXNUM_FLAG
Definition: ruby.h:438
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4904
static VALUE range_dumper(VALUE range)
Definition: range.c:1214
static VALUE range_step_size(VALUE range, VALUE args)
Definition: range.c:325
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1967
static VALUE range_include(VALUE range, VALUE val)
Definition: range.c:1131
#define Qtrue
Definition: ruby.h:434
st_index_t rb_hash_end(st_index_t)
static ID id_succ
Definition: range.c:23
Definition: id.h:68
static VALUE range_bsearch(VALUE range)
Definition: range.c:563
static VALUE range_loader(VALUE range, VALUE obj)
Definition: range.c:1228
VALUE rb_ary_last(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1245
VALUE rb_eTypeError
Definition: error.c:516
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:240
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
static ID id_excl
Definition: range.c:23
static VALUE inspect_range(VALUE range, VALUE dummy, int recur)
Definition: range.c:1057
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
VALUE rb_to_int(VALUE)
Definition: object.c:2482
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1788
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1116
#define EXCL(r)
Definition: range.c:29
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4881
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:593
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:684
static VALUE sym_step_i(VALUE i, void *arg)
Definition: range.c:282
st_data_t st_index_t
Definition: st.h:63
#define SET_EXCL(r, v)
Definition: range.c:30
static VALUE range_to_s(VALUE range)
Definition: range.c:1042
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
Definition: vm_eval.c:1120
#define FIXNUM_P(f)
Definition: ruby.h:355
VALUE rb_Float(VALUE)
Definition: object.c:2700
VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end)
Definition: range.c:67
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2468
static VALUE recursive_hash(VALUE range, VALUE dummy, int recur)
Definition: range.c:224
#define range_initialize_copy
Definition: range.c:98
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:97
VALUE rb_eRangeError
Definition: error.c:520
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:904
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:683
static VALUE recursive_eql(VALUE range, VALUE obj, int recur)
Definition: range.c:186
int args
Definition: win32ole.c:785
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1537
static VALUE range_eql(VALUE range, VALUE obj)
Definition: range.c:214
static VALUE range_size(VALUE range)
Definition: range.c:708
void rb_iter_break(void)
Definition: vm.c:1028
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
static VALUE range_step(int argc, VALUE *argv, VALUE range)
Definition: range.c:383
VALUE rb_Array(VALUE)
Definition: object.c:2820
static VALUE step_i(VALUE i, void *arg)
Definition: range.c:300
int rb_block_given_p(void)
Definition: eval.c:672
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1426
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4892
#define BSEARCH(conv)
static ID id_div
Definition: range.c:23
VALUE rb_obj_as_string(VALUE)
Definition: string.c:895
#define NIL_P(v)
Definition: ruby.h:446
static VALUE first_i(VALUE i, VALUE *ary)
Definition: range.c:821
#define ISASCII(c)
Definition: ruby.h:1629
static VALUE range_initialize(int argc, VALUE *argv, VALUE range)
Definition: range.c:85
#define T_FLOAT
Definition: ruby.h:489
int argc
Definition: ruby.c:130
#define Qfalse
Definition: ruby.h:433
#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
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1740
int err
Definition: win32.c:87
static VALUE range_first(int argc, VALUE *argv, VALUE range)
Definition: range.c:847
VALUE rb_sym_to_s(VALUE)
Definition: string.c:7924
static void range_each_func(VALUE range, VALUE(*func)(VALUE, void *), void *arg)
Definition: range.c:258
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1803
static ID id_cmp
Definition: range.c:23
static ID id_end
Definition: range.c:23
#define RSTRING_LEN(str)
Definition: ruby.h:862
#define rb_intern(str)
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
static VALUE range_check(VALUE *args)
Definition: range.c:40
static VALUE range_min(VALUE range)
Definition: range.c:903
VALUE rb_check_funcall(VALUE, ID, int, VALUE *)
Definition: vm_eval.c:408
static VALUE range_hash(VALUE range)
Definition: range.c:252
VALUE rb_mEnumerable
Definition: enum.c:20
int rb_eql(VALUE, VALUE)
Definition: object.c:67
VALUE num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1829
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:1570
static VALUE range_exclude_end_p(VALUE range)
Definition: range.c:111
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1128
unsigned long ID
Definition: ruby.h:105
#define Qnil
Definition: ruby.h:435
static int discrete_object_p(VALUE obj)
Definition: range.c:318
#define RANGE_END(r)
Definition: range.c:26
unsigned long VALUE
Definition: ruby.h:104
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:215
#define RBASIC(obj)
Definition: ruby.h:1094
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1441
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:273
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1448
VALUE rb_str_dup(VALUE)
Definition: string.c:946
#define LONG2NUM(x)
Definition: ruby.h:1199
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1598
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:990
static VALUE recursive_equal(VALUE range, VALUE obj, int recur)
Definition: range.c:117
#define recur(fmt)
#define RSTRING_PTR(str)
Definition: ruby.h:866
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:56
static VALUE range_end(VALUE range)
Definition: range.c:814
#define RFLOAT_VALUE(v)
Definition: ruby.h:836
static VALUE range_inspect(VALUE range)
Definition: range.c:1085
#define INT2FIX(i)
Definition: ruby.h:241
static int r_lt(VALUE a, VALUE b)
Definition: range.c:157
static VALUE range_begin(VALUE range)
Definition: range.c:796
VALUE rb_cRange
Definition: range.c:22
static VALUE range_last(int argc, VALUE *argv, VALUE range)
Definition: range.c:880
static ID id_beg
Definition: range.c:23
#define RARRAY_PTR(a)
Definition: ruby.h:904
VALUE rb_check_string_type(VALUE)
Definition: string.c:1509
#define RANGE_EXCL(r)
Definition: range.c:27
#define LONG2FIX(i)
Definition: ruby.h:242
#define RTEST(v)
Definition: ruby.h:445
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:113
#define T_STRING
Definition: ruby.h:490
#define OBJ_INFECT(x, s)
Definition: ruby.h:1157
st_index_t rb_hash_uint(st_index_t, st_index_t)
v
Definition: win32ole.c:798
static VALUE range_alloc(VALUE klass)
Definition: range.c:1241
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:220
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:739
Definition: ruby.h:709
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:246
VALUE rb_inspect(VALUE)
Definition: object.c:411
VALUE rb_str_intern(VALUE)
Definition: string.c:7229
static VALUE range_eqq(VALUE range, VALUE val)
Definition: range.c:1110
static VALUE range_eq(VALUE range, VALUE obj)
Definition: range.c:146
#define SYMBOL_P(x)
Definition: ruby.h:362
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:353
#define Qundef
Definition: ruby.h:436
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1460
static int r_le(VALUE a, VALUE b)
Definition: range.c:169
static VALUE range_cover(VALUE range, VALUE val)
Definition: range.c:1194
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2125
VALUE rb_str_new2(const char *)
static ID id_integer_p
Definition: range.c:23
VALUE rb_eArgError
Definition: error.c:517
#define NUM2LONG(x)
Definition: ruby.h:592
static VALUE range_failed(void)
Definition: range.c:33
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1416
char ** argv
Definition: ruby.c:131
#define DBL2NUM(dbl)
Definition: ruby.h:837