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