Ruby  2.1.4p265(2014-10-27revision48166)
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 #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);
102  range_modify(range);
103  range_init(range, beg, end, RBOOL(RTEST(flags)));
104  return Qnil;
105 }
106 
107 /* :nodoc: */
108 static VALUE
110 {
111  range_modify(range);
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 
169  return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
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 {
251  st_index_t hash = EXCL(range);
252  VALUE v;
253 
254  hash = rb_hash_start(hash);
255  v = rb_hash(RANGE_BEG(range));
256  hash = rb_hash_uint(hash, NUM2LONG(v));
257  v = rb_hash(RANGE_END(range));
258  hash = rb_hash_uint(hash, NUM2LONG(v));
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 VALUE
334 {
335  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
336  VALUE step = INT2FIX(1);
337  if (args) {
338  step = RARRAY_AREF(args, 0);
339  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
340  step = rb_to_int(step);
341  }
342  }
343  if (rb_funcall(step, '<', 1, INT2FIX(0))) {
344  rb_raise(rb_eArgError, "step can't be negative");
345  }
346  else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
347  rb_raise(rb_eArgError, "step can't be 0");
348  }
349 
351  return ruby_num_interval_step_size(b, e, step, EXCL(range));
352  }
353  return Qnil;
354 }
355 
356 /*
357  * call-seq:
358  * rng.step(n=1) {| obj | block } -> rng
359  * rng.step(n=1) -> an_enumerator
360  *
361  * Iterates over the range, passing each <code>n</code>th element to the block.
362  * If begin and end are numeric, +n+ is added for each iteration.
363  * Otherwise <code>step</code> invokes <code>succ</code> to iterate through
364  * range elements.
365  *
366  * If no block is given, an enumerator is returned instead.
367  *
368  * range = Xs.new(1)..Xs.new(10)
369  * range.step(2) {|x| puts x}
370  * puts
371  * range.step(3) {|x| puts x}
372  *
373  * <em>produces:</em>
374  *
375  * 1 x
376  * 3 xxx
377  * 5 xxxxx
378  * 7 xxxxxxx
379  * 9 xxxxxxxxx
380  *
381  * 1 x
382  * 4 xxxx
383  * 7 xxxxxxx
384  * 10 xxxxxxxxxx
385  *
386  * See Range for the definition of class Xs.
387  */
388 
389 
390 static VALUE
392 {
393  VALUE b, e, step, tmp;
394 
395  RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);
396 
397  b = RANGE_BEG(range);
398  e = RANGE_END(range);
399  if (argc == 0) {
400  step = INT2FIX(1);
401  }
402  else {
403  rb_scan_args(argc, argv, "01", &step);
404  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
405  step = rb_to_int(step);
406  }
407  if (rb_funcall(step, '<', 1, INT2FIX(0))) {
408  rb_raise(rb_eArgError, "step can't be negative");
409  }
410  else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
411  rb_raise(rb_eArgError, "step can't be 0");
412  }
413  }
414 
415  if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
416  long end = FIX2LONG(e);
417  long i, unit = FIX2LONG(step);
418 
419  if (!EXCL(range))
420  end += 1;
421  i = FIX2LONG(b);
422  while (i < end) {
423  rb_yield(LONG2NUM(i));
424  if (i + unit < i) break;
425  i += unit;
426  }
427 
428  }
429  else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
430  VALUE args[2], iter[2];
431 
432  args[0] = rb_sym_to_s(e);
433  args[1] = EXCL(range) ? Qtrue : Qfalse;
434  iter[0] = INT2FIX(1);
435  iter[1] = step;
436  rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
437  }
438  else if (ruby_float_step(b, e, step, EXCL(range))) {
439  /* done */
440  }
441  else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
442  !NIL_P(rb_check_to_integer(b, "to_int")) ||
443  !NIL_P(rb_check_to_integer(e, "to_int"))) {
444  ID op = EXCL(range) ? '<' : idLE;
445  VALUE v = b;
446  int i = 0;
447 
448  while (RTEST(rb_funcall(v, op, 1, e))) {
449  rb_yield(v);
450  i++;
451  v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
452  }
453  }
454  else {
455  tmp = rb_check_string_type(b);
456 
457  if (!NIL_P(tmp)) {
458  VALUE args[2], iter[2];
459 
460  b = tmp;
461  args[0] = e;
462  args[1] = EXCL(range) ? Qtrue : Qfalse;
463  iter[0] = INT2FIX(1);
464  iter[1] = step;
465  rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
466  }
467  else {
468  VALUE args[2];
469 
470  if (!discrete_object_p(b)) {
471  rb_raise(rb_eTypeError, "can't iterate from %s",
472  rb_obj_classname(b));
473  }
474  args[0] = INT2FIX(1);
475  args[1] = step;
476  range_each_func(range, step_i, (VALUE)args);
477  }
478  }
479  return range;
480 }
481 
482 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
483 union int64_double {
484  int64_t i;
485  double d;
486 };
487 
488 static VALUE
489 int64_as_double_to_num(int64_t i)
490 {
491  union int64_double convert;
492  if (i < 0) {
493  convert.i = -i;
494  return DBL2NUM(-convert.d);
495  }
496  else {
497  convert.i = i;
498  return DBL2NUM(convert.d);
499  }
500 }
501 
502 static int64_t
503 double_as_int64(double d)
504 {
505  union int64_double convert;
506  convert.d = fabs(d);
507  return d < 0 ? -convert.i : convert.i;
508 }
509 #endif
510 
511 static int
513 {
514  VALUE is_int = rb_check_funcall(v, id_integer_p, 0, 0);
515  return RTEST(is_int) && is_int != Qundef;
516 }
517 
518 /*
519  * call-seq:
520  * rng.bsearch {|obj| block } -> value
521  *
522  * By using binary search, finds a value in range which meets the given
523  * condition in O(log n) where n is the size of the range.
524  *
525  * You can use this method in two use cases: a find-minimum mode and
526  * a find-any mode. In either case, the elements of the range must be
527  * monotone (or sorted) with respect to the block.
528  *
529  * In find-minimum mode (this is a good choice for typical use case),
530  * the block must return true or false, and there must be a value x
531  * so that:
532  *
533  * - the block returns false for any value which is less than x, and
534  * - the block returns true for any value which is greater than or
535  * equal to i.
536  *
537  * If x is within the range, this method returns the value x.
538  * Otherwise, it returns nil.
539  *
540  * ary = [0, 4, 7, 10, 12]
541  * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
542  * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
543  * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
544  * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
545  *
546  * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
547  *
548  * In find-any mode (this behaves like libc's bsearch(3)), the block
549  * must return a number, and there must be two values x and y (x <= y)
550  * so that:
551  *
552  * - the block returns a positive number for v if v < x,
553  * - the block returns zero for v if x <= v < y, and
554  * - the block returns a negative number for v if y <= v.
555  *
556  * This method returns any value which is within the intersection of
557  * the given range and x...y (if any). If there is no value that
558  * satisfies the condition, it returns nil.
559  *
560  * ary = [0, 100, 100, 100, 200]
561  * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
562  * (0..4).bsearch {|i| 300 - ary[i] } #=> nil
563  * (0..4).bsearch {|i| 50 - ary[i] } #=> nil
564  *
565  * You must not mix the two modes at a time; the block must always
566  * return either true/false, or always return a number. It is
567  * undefined which value is actually picked up at each iteration.
568  */
569 
570 static VALUE
572 {
573  VALUE beg, end;
574  int smaller, satisfied = 0;
575 
576  /* Implementation notes:
577  * Floats are handled by mapping them to 64 bits integers.
578  * Apart from sign issues, floats and their 64 bits integer have the
579  * same order, assuming they are represented as exponent followed
580  * by the mantissa. This is true with or without implicit bit.
581  *
582  * Finding the average of two ints needs to be careful about
583  * potential overflow (since float to long can use 64 bits)
584  * as well as the fact that -1/2 can be 0 or -1 in C89.
585  *
586  * Note that -0.0 is mapped to the same int as 0.0 as we don't want
587  * (-1...0.0).bsearch to yield -0.0.
588  */
589 
590 #define BSEARCH_CHECK(val) \
591  do { \
592  VALUE v = rb_yield(val); \
593  if (FIXNUM_P(v)) { \
594  if (FIX2INT(v) == 0) return val; \
595  smaller = FIX2INT(v) < 0; \
596  } \
597  else if (v == Qtrue) { \
598  satisfied = 1; \
599  smaller = 1; \
600  } \
601  else if (v == Qfalse || v == Qnil) { \
602  smaller = 0; \
603  } \
604  else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
605  int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
606  if (!cmp) return val; \
607  smaller = cmp < 0; \
608  } \
609  else { \
610  rb_raise(rb_eTypeError, "wrong argument type %s" \
611  " (must be numeric, true, false or nil)", \
612  rb_obj_classname(v)); \
613  } \
614  } while (0)
615 
616 #define BSEARCH(conv) \
617  do { \
618  RETURN_ENUMERATOR(range, 0, 0); \
619  if (EXCL(range)) high--; \
620  org_high = high; \
621  while (low < high) { \
622  mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
623  : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
624  BSEARCH_CHECK(conv(mid)); \
625  if (smaller) { \
626  high = mid; \
627  } \
628  else { \
629  low = mid + 1; \
630  } \
631  } \
632  if (low == org_high) { \
633  BSEARCH_CHECK(conv(low)); \
634  if (!smaller) return Qnil; \
635  } \
636  if (!satisfied) return Qnil; \
637  return conv(low); \
638  } while (0)
639 
640 
641  beg = RANGE_BEG(range);
642  end = RANGE_END(range);
643 
644  if (FIXNUM_P(beg) && FIXNUM_P(end)) {
645  long low = FIX2LONG(beg);
646  long high = FIX2LONG(end);
647  long mid, org_high;
648  BSEARCH(INT2FIX);
649  }
650 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
651  else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
652  int64_t low = double_as_int64(RFLOAT_VALUE(rb_Float(beg)));
653  int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end)));
654  int64_t mid, org_high;
655  BSEARCH(int64_as_double_to_num);
656  }
657 #endif
658  else if (is_integer_p(beg) && is_integer_p(end)) {
659  VALUE low = rb_to_int(beg);
660  VALUE high = rb_to_int(end);
661  VALUE mid, org_high;
662  RETURN_ENUMERATOR(range, 0, 0);
663  if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1));
664  org_high = high;
665 
666  while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
667  mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
668  BSEARCH_CHECK(mid);
669  if (smaller) {
670  high = mid;
671  }
672  else {
673  low = rb_funcall(mid, '+', 1, INT2FIX(1));
674  }
675  }
676  if (rb_equal(low, org_high)) {
677  BSEARCH_CHECK(low);
678  if (!smaller) return Qnil;
679  }
680  if (!satisfied) return Qnil;
681  return low;
682  }
683  else {
684  rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
685  }
686  return range;
687 }
688 
689 static VALUE
691 {
692  rb_yield(v);
693  return Qnil;
694 }
695 
696 static VALUE
698 {
700  return Qnil;
701 }
702 
703 /*
704  * call-seq:
705  * rng.size -> num
706  *
707  * Returns the number of elements in the range. Both the begin and the end of
708  * the Range must be Numeric, otherwise nil is returned.
709  *
710  * (10..20).size #=> 11
711  * ('a'..'z').size #=> nil
712  * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
713  */
714 
715 static VALUE
717 {
718  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
720  return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
721  }
722  return Qnil;
723 }
724 
725 static VALUE
727 {
728  return range_size(range);
729 }
730 
731 /*
732  * call-seq:
733  * rng.each {| i | block } -> rng
734  * rng.each -> an_enumerator
735  *
736  * Iterates over the elements of range, passing each in turn to the
737  * block.
738  *
739  * The +each+ method can only be used if the begin object of the range
740  * supports the +succ+ method. A TypeError is raised if the object
741  * does not have +succ+ method defined (like Float).
742  *
743  * If no block is given, an enumerator is returned instead.
744  *
745  * (10..15).each {|n| print n, ' ' }
746  * # prints: 10 11 12 13 14 15
747  *
748  * (2.5..5).each {|n| print n, ' ' }
749  * # raises: TypeError: can't iterate from Float
750  */
751 
752 static VALUE
754 {
755  VALUE beg, end;
756 
758 
759  beg = RANGE_BEG(range);
760  end = RANGE_END(range);
761 
762  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
763  long lim = FIX2LONG(end);
764  long i;
765 
766  if (!EXCL(range))
767  lim += 1;
768  for (i = FIX2LONG(beg); i < lim; i++) {
769  rb_yield(LONG2FIX(i));
770  }
771  }
772  else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
773  VALUE args[2];
774 
775  args[0] = rb_sym_to_s(end);
776  args[1] = EXCL(range) ? Qtrue : Qfalse;
777  rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
778  }
779  else {
780  VALUE tmp = rb_check_string_type(beg);
781 
782  if (!NIL_P(tmp)) {
783  VALUE args[2];
784 
785  args[0] = end;
786  args[1] = EXCL(range) ? Qtrue : Qfalse;
787  rb_block_call(tmp, rb_intern("upto"), 2, args, each_i, 0);
788  }
789  else {
790  if (!discrete_object_p(beg)) {
791  rb_raise(rb_eTypeError, "can't iterate from %s",
792  rb_obj_classname(beg));
793  }
794  range_each_func(range, each_i, 0);
795  }
796  }
797  return range;
798 }
799 
800 /*
801  * call-seq:
802  * rng.begin -> obj
803  *
804  * Returns the object that defines the beginning of the range.
805  *
806  * (1..10).begin #=> 1
807  */
808 
809 static VALUE
811 {
812  return RANGE_BEG(range);
813 }
814 
815 
816 /*
817  * call-seq:
818  * rng.end -> obj
819  *
820  * Returns the object that defines the end of the range.
821  *
822  * (1..10).end #=> 10
823  * (1...10).end #=> 10
824  */
825 
826 
827 static VALUE
829 {
830  return RANGE_END(range);
831 }
832 
833 
834 static VALUE
836 {
837  VALUE *ary = (VALUE *)cbarg;
838  long n = NUM2LONG(ary[0]);
839 
840  if (n <= 0) {
841  rb_iter_break();
842  }
843  rb_ary_push(ary[1], i);
844  n--;
845  ary[0] = INT2NUM(n);
846  return Qnil;
847 }
848 
849 /*
850  * call-seq:
851  * rng.first -> obj
852  * rng.first(n) -> an_array
853  *
854  * Returns the first object in the range, or an array of the first +n+
855  * elements.
856  *
857  * (10..20).first #=> 10
858  * (10..20).first(3) #=> [10, 11, 12]
859  */
860 
861 static VALUE
863 {
864  VALUE n, ary[2];
865 
866  if (argc == 0) return RANGE_BEG(range);
867 
868  rb_scan_args(argc, argv, "1", &n);
869  ary[0] = n;
870  ary[1] = rb_ary_new2(NUM2LONG(n));
871  rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
872 
873  return ary[1];
874 }
875 
876 
877 /*
878  * call-seq:
879  * rng.last -> obj
880  * rng.last(n) -> an_array
881  *
882  * Returns the last object in the range,
883  * or an array of the last +n+ elements.
884  *
885  * Note that with no arguments +last+ will return the object that defines
886  * the end of the range even if #exclude_end? is +true+.
887  *
888  * (10..20).last #=> 20
889  * (10...20).last #=> 20
890  * (10..20).last(3) #=> [18, 19, 20]
891  * (10...20).last(3) #=> [17, 18, 19]
892  */
893 
894 static VALUE
896 {
897  if (argc == 0) return RANGE_END(range);
898  return rb_ary_last(argc, argv, rb_Array(range));
899 }
900 
901 
902 /*
903  * call-seq:
904  * rng.min -> obj
905  * rng.min {| a,b | block } -> obj
906  *
907  * Returns the minimum value in the range. Returns +nil+ if the begin
908  * value of the range is larger than the end value.
909  *
910  * Can be given an optional block to override the default comparison
911  * method <code>a <=> b</code>.
912  *
913  * (10..20).min #=> 10
914  */
915 
916 
917 static VALUE
919 {
920  if (rb_block_given_p()) {
921  return rb_call_super(0, 0);
922  }
923  else {
924  VALUE b = RANGE_BEG(range);
925  VALUE e = RANGE_END(range);
926  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
927 
928  if (c > 0 || (c == 0 && EXCL(range)))
929  return Qnil;
930  return b;
931  }
932 }
933 
934 /*
935  * call-seq:
936  * rng.max -> obj
937  * rng.max {| a,b | block } -> obj
938  *
939  * Returns the maximum value in the range. Returns +nil+ if the begin
940  * value of the range larger than the end value.
941  *
942  * Can be given an optional block to override the default comparison
943  * method <code>a <=> b</code>.
944  *
945  * (10..20).max #=> 20
946  */
947 
948 static VALUE
950 {
951  VALUE e = RANGE_END(range);
952  int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
953 
954  if (rb_block_given_p() || (EXCL(range) && !nm)) {
955  return rb_call_super(0, 0);
956  }
957  else {
958  VALUE b = RANGE_BEG(range);
959  int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
960 
961  if (c > 0)
962  return Qnil;
963  if (EXCL(range)) {
964  if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
965  rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
966  }
967  if (c == 0) return Qnil;
968  if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
969  rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
970  }
971  if (FIXNUM_P(e)) {
972  return LONG2NUM(FIX2LONG(e) - 1);
973  }
974  return rb_funcall(e, '-', 1, INT2FIX(1));
975  }
976  return e;
977  }
978 }
979 
980 int
981 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
982 {
983  VALUE b, e;
984  int excl;
985 
986  if (rb_obj_is_kind_of(range, rb_cRange)) {
987  b = RANGE_BEG(range);
988  e = RANGE_END(range);
989  excl = EXCL(range);
990  }
991  else {
992  if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
993  if (!rb_respond_to(range, id_end)) return (int)Qfalse;
994  b = rb_funcall(range, id_beg, 0);
995  e = rb_funcall(range, id_end, 0);
996  excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
997  }
998  *begp = b;
999  *endp = e;
1000  *exclp = excl;
1001  return (int)Qtrue;
1002 }
1003 
1004 VALUE
1005 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
1006 {
1007  long beg, end, origbeg, origend;
1008  VALUE b, e;
1009  int excl;
1010 
1011  if (!rb_range_values(range, &b, &e, &excl))
1012  return Qfalse;
1013  beg = NUM2LONG(b);
1014  end = NUM2LONG(e);
1015  origbeg = beg;
1016  origend = end;
1017  if (beg < 0) {
1018  beg += len;
1019  if (beg < 0)
1020  goto out_of_range;
1021  }
1022  if (end < 0)
1023  end += len;
1024  if (!excl)
1025  end++; /* include end point */
1026  if (err == 0 || err == 2) {
1027  if (beg > len)
1028  goto out_of_range;
1029  if (end > len)
1030  end = len;
1031  }
1032  len = end - beg;
1033  if (len < 0)
1034  len = 0;
1035 
1036  *begp = beg;
1037  *lenp = len;
1038  return Qtrue;
1039 
1040  out_of_range:
1041  if (err) {
1042  rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
1043  origbeg, excl ? "." : "", origend);
1044  }
1045  return Qnil;
1046 }
1047 
1048 /*
1049  * call-seq:
1050  * rng.to_s -> string
1051  *
1052  * Convert this range object to a printable form (using #to_s to convert the
1053  * begin and end objects).
1054  */
1055 
1056 static VALUE
1058 {
1059  VALUE str, str2;
1060 
1061  str = rb_obj_as_string(RANGE_BEG(range));
1062  str2 = rb_obj_as_string(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 static VALUE
1073 {
1074  VALUE str, str2;
1075 
1076  if (recur) {
1077  return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
1078  }
1079  str = rb_inspect(RANGE_BEG(range));
1080  str2 = rb_inspect(RANGE_END(range));
1081  str = rb_str_dup(str);
1082  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1083  rb_str_append(str, str2);
1084  OBJ_INFECT(str, str2);
1085 
1086  return str;
1087 }
1088 
1089 /*
1090  * call-seq:
1091  * rng.inspect -> string
1092  *
1093  * Convert this range object to a printable form (using
1094  * <code>inspect</code> to convert the begin and end
1095  * objects).
1096  */
1097 
1098 
1099 static VALUE
1101 {
1102  return rb_exec_recursive(inspect_range, range, 0);
1103 }
1104 
1105 /*
1106  * call-seq:
1107  * rng === obj -> true or false
1108  *
1109  * Returns <code>true</code> if +obj+ is an element of the range,
1110  * <code>false</code> otherwise. Conveniently, <code>===</code> is the
1111  * comparison operator used by <code>case</code> statements.
1112  *
1113  * case 79
1114  * when 1..50 then print "low\n"
1115  * when 51..75 then print "medium\n"
1116  * when 76..100 then print "high\n"
1117  * end
1118  *
1119  * <em>produces:</em>
1120  *
1121  * high
1122  */
1123 
1124 static VALUE
1126 {
1127  return rb_funcall(range, rb_intern("include?"), 1, val);
1128 }
1129 
1130 
1131 /*
1132  * call-seq:
1133  * rng.member?(obj) -> true or false
1134  * rng.include?(obj) -> true or false
1135  *
1136  * Returns <code>true</code> if +obj+ is an element of
1137  * the range, <code>false</code> otherwise. If begin and end are
1138  * numeric, comparison is done according to the magnitude of the values.
1139  *
1140  * ("a".."z").include?("g") #=> true
1141  * ("a".."z").include?("A") #=> false
1142  * ("a".."z").include?("cc") #=> false
1143  */
1144 
1145 static VALUE
1147 {
1148  VALUE beg = RANGE_BEG(range);
1149  VALUE end = RANGE_END(range);
1150  int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1153 
1154  if (nv ||
1155  !NIL_P(rb_check_to_integer(beg, "to_int")) ||
1156  !NIL_P(rb_check_to_integer(end, "to_int"))) {
1157  if (r_le(beg, val)) {
1158  if (EXCL(range)) {
1159  if (r_lt(val, end))
1160  return Qtrue;
1161  }
1162  else {
1163  if (r_le(val, end))
1164  return Qtrue;
1165  }
1166  }
1167  return Qfalse;
1168  }
1169  else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
1170  RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
1171  if (NIL_P(val)) return Qfalse;
1172  if (RB_TYPE_P(val, T_STRING)) {
1173  if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
1174  return Qfalse;
1175  else {
1176  char b = RSTRING_PTR(beg)[0];
1177  char e = RSTRING_PTR(end)[0];
1178  char v = RSTRING_PTR(val)[0];
1179 
1180  if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
1181  if (b <= v && v < e) return Qtrue;
1182  if (!EXCL(range) && v == e) return Qtrue;
1183  return Qfalse;
1184  }
1185  }
1186  }
1187  }
1188  /* TODO: ruby_frame->this_func = rb_intern("include?"); */
1189  return rb_call_super(1, &val);
1190 }
1191 
1192 
1193 /*
1194  * call-seq:
1195  * rng.cover?(obj) -> true or false
1196  *
1197  * Returns <code>true</code> if +obj+ is between the begin and end of
1198  * the range.
1199  *
1200  * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1201  * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1202  *
1203  * ("a".."z").cover?("c") #=> true
1204  * ("a".."z").cover?("5") #=> false
1205  * ("a".."z").cover?("cc") #=> true
1206  */
1207 
1208 static VALUE
1210 {
1211  VALUE beg, end;
1212 
1213  beg = RANGE_BEG(range);
1214  end = RANGE_END(range);
1215  if (r_le(beg, val)) {
1216  if (EXCL(range)) {
1217  if (r_lt(val, end))
1218  return Qtrue;
1219  }
1220  else {
1221  if (r_le(val, end))
1222  return Qtrue;
1223  }
1224  }
1225  return Qfalse;
1226 }
1227 
1228 static VALUE
1230 {
1231  VALUE v;
1233 
1234  v = (VALUE)m;
1235 
1236  rb_ivar_set(v, id_excl, RANGE_EXCL(range));
1237  rb_ivar_set(v, id_beg, RANGE_BEG(range));
1238  rb_ivar_set(v, id_end, RANGE_END(range));
1239  return v;
1240 }
1241 
1242 static VALUE
1244 {
1245  if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
1246  rb_raise(rb_eTypeError, "not a dumped range object");
1247  }
1248 
1249  range_modify(range);
1250  RANGE_SET_BEG(range, rb_ivar_get(obj, id_beg));
1251  RANGE_SET_END(range, rb_ivar_get(obj, id_end));
1252  RANGE_SET_EXCL(range, rb_ivar_get(obj, id_excl));
1253  return range;
1254 }
1255 
1256 static VALUE
1258 {
1259  /* rb_struct_alloc_noinit itself should not be used because
1260  * rb_marshal_define_compat uses equality of allocation function */
1261  return rb_struct_alloc_noinit(klass);
1262 }
1263 
1264 /* A <code>Range</code> represents an interval---a set of values with a
1265  * beginning and an end. Ranges may be constructed using the
1266  * <em>s</em><code>..</code><em>e</em> and
1267  * <em>s</em><code>...</code><em>e</em> literals, or with
1268  * Range::new. Ranges constructed using <code>..</code>
1269  * run from the beginning to the end inclusively. Those created using
1270  * <code>...</code> exclude the end value. When used as an iterator,
1271  * ranges return each value in the sequence.
1272  *
1273  * (-1..-5).to_a #=> []
1274  * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
1275  * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
1276  * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
1277  *
1278  * == Custom Objects in Ranges
1279  *
1280  * Ranges can be constructed using any objects that can be compared
1281  * using the <code><=></code> operator.
1282  * Methods that treat the range as a sequence (#each and methods inherited
1283  * from Enumerable) expect the begin object to implement a
1284  * <code>succ</code> method to return the next object in sequence.
1285  * The #step and #include? methods require the begin
1286  * object to implement <code>succ</code> or to be numeric.
1287  *
1288  * In the <code>Xs</code> class below both <code><=></code> and
1289  * <code>succ</code> are implemented so <code>Xs</code> can be used
1290  * to construct ranges. Note that the Comparable module is included
1291  * so the <code>==</code> method is defined in terms of <code><=></code>.
1292  *
1293  * class Xs # represent a string of 'x's
1294  * include Comparable
1295  * attr :length
1296  * def initialize(n)
1297  * @length = n
1298  * end
1299  * def succ
1300  * Xs.new(@length + 1)
1301  * end
1302  * def <=>(other)
1303  * @length <=> other.length
1304  * end
1305  * def to_s
1306  * sprintf "%2d #{inspect}", @length
1307  * end
1308  * def inspect
1309  * 'x' * @length
1310  * end
1311  * end
1312  *
1313  * An example of using <code>Xs</code> to construct a range:
1314  *
1315  * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1316  * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1317  * r.member?(Xs.new(5)) #=> true
1318  *
1319  */
1320 
1321 void
1323 {
1324 #undef rb_intern
1325 #define rb_intern(str) rb_intern_const(str)
1326 
1327  id_cmp = rb_intern("<=>");
1328  id_succ = rb_intern("succ");
1329  id_beg = rb_intern("begin");
1330  id_end = rb_intern("end");
1331  id_excl = rb_intern("excl");
1332  id_integer_p = rb_intern("integer?");
1333  id_div = rb_intern("div");
1334 
1336  "Range", rb_cObject, range_alloc,
1337  "begin", "end", "excl", NULL);
1338 
1341  rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1342  rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1343  rb_define_method(rb_cRange, "==", range_eq, 1);
1344  rb_define_method(rb_cRange, "===", range_eqq, 1);
1345  rb_define_method(rb_cRange, "eql?", range_eql, 1);
1346  rb_define_method(rb_cRange, "hash", range_hash, 0);
1347  rb_define_method(rb_cRange, "each", range_each, 0);
1348  rb_define_method(rb_cRange, "step", range_step, -1);
1349  rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
1350  rb_define_method(rb_cRange, "begin", range_begin, 0);
1351  rb_define_method(rb_cRange, "end", range_end, 0);
1352  rb_define_method(rb_cRange, "first", range_first, -1);
1353  rb_define_method(rb_cRange, "last", range_last, -1);
1354  rb_define_method(rb_cRange, "min", range_min, 0);
1355  rb_define_method(rb_cRange, "max", range_max, 0);
1356  rb_define_method(rb_cRange, "size", range_size, 0);
1357  rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1358  rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1359 
1360  rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1361 
1362  rb_define_method(rb_cRange, "member?", range_include, 1);
1363  rb_define_method(rb_cRange, "include?", range_include, 1);
1364  rb_define_method(rb_cRange, "cover?", range_cover, 1);
1365 }
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:512
#define RANGE_BEG(r)
Definition: range.c:25
#define FALSE
Definition: nkf.h:174
#define INT2NUM(x)
Definition: ruby.h:1288
void Init_Range(void)
Definition: range.c:1322
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:981
static VALUE range_max(VALUE range)
Definition: range.c:949
#define FIXNUM_FLAG
Definition: ruby.h:430
static VALUE range_dumper(VALUE range)
Definition: range.c:1229
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2140
static VALUE range_include(VALUE range, VALUE val)
Definition: range.c:1146
#define Qtrue
Definition: ruby.h:426
static VALUE each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
Definition: range.c:690
#define RBOOL(v)
Definition: range.c:31
st_index_t rb_hash_end(st_index_t)
static ID id_succ
Definition: range.c:23
Definition: id.h:81
static VALUE range_bsearch(VALUE range)
Definition: range.c:571
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:707
static VALUE range_loader(VALUE range, VALUE obj)
Definition: range.c:1243
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:697
VALUE rb_ary_last(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1329
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:896
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:1072
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
VALUE rb_to_int(VALUE)
Definition: object.c:2679
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:4982
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
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:1057
#define FIXNUM_P(f)
Definition: ruby.h:347
VALUE rb_Float(VALUE)
Definition: object.c:2895
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:2665
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:1511
static VALUE recursive_eql(VALUE range, VALUE obj, int recur)
Definition: range.c:202
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
static VALUE range_eql(VALUE range, VALUE obj)
Definition: range.c:230
static VALUE range_size(VALUE range)
Definition: range.c:716
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1513
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:391
VALUE rb_Array(VALUE)
Definition: object.c:3014
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:1553
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4993
#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:726
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:1813
#define NIL_P(v)
Definition: ruby.h:438
#define ISASCII(c)
Definition: ruby.h:1766
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:835
#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:333
#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:1801
int err
Definition: win32.c:114
static VALUE range_first(int argc, VALUE *argv, VALUE range)
Definition: range.c:862
VALUE rb_sym_to_s(VALUE)
Definition: string.c:8478
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1782
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:942
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static VALUE range_check(VALUE *args)
Definition: range.c:43
static VALUE range_min(VALUE range)
Definition: range.c:918
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:1728
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
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:1568
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:274
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1575
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:1309
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:1005
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:828
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
static VALUE range_inspect(VALUE range)
Definition: range.c:1100
#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:810
VALUE rb_cRange
Definition: range.c:22
static VALUE range_last(int argc, VALUE *argv, VALUE range)
Definition: range.c:895
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:1679
#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:113
#define T_STRING
Definition: ruby.h:482
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
st_index_t rb_hash_uint(st_index_t, st_index_t)
static VALUE range_alloc(VALUE klass)
Definition: range.c:1257
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:753
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
static VALUE range_eqq(VALUE range, VALUE val)
Definition: range.c:1125
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:103
#define FIX2LONG(x)
Definition: ruby.h:345
#define Qundef
Definition: ruby.h:428
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1587
static int r_le(VALUE a, VALUE b)
Definition: range.c:185
static VALUE range_cover(VALUE range, VALUE val)
Definition: range.c:1209
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
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