Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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
22 VALUE rb_cRange;
23 static ID id_cmp, id_succ, id_beg, id_end, id_excl, id_integer_p, id_div;
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
36 range_failed(void)
37 {
38 rb_raise(rb_eArgError, "bad value for range");
39 return Qnil; /* dummy */
40 }
41
42 static VALUE
43 range_check(VALUE *args)
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 {
72 VALUE range = rb_obj_alloc(rb_cRange);
73
74 range_init(range, beg, end, RBOOL(exclude_end));
75 return range;
76 }
77
78 static void
79 range_modify(VALUE range)
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
97 range_initialize(int argc, VALUE *argv, VALUE range)
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
109 range_initialize_copy(VALUE range, VALUE orig)
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
127 range_exclude_end_p(VALUE range)
128 {
129 return EXCL(range) ? Qtrue : Qfalse;
130 }
131
132 static VALUE
133 recursive_equal(VALUE range, VALUE obj, int recur)
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
162 range_eq(VALUE range, VALUE obj)
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
173 r_lt(VALUE a, VALUE b)
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
185 r_le(VALUE a, VALUE b)
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
202 recursive_eql(VALUE range, VALUE obj, int recur)
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
230 range_eql(VALUE range, VALUE obj)
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
249 range_hash(VALUE range)
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
266 range_each_func(VALUE range, rb_block_call_func *func, VALUE arg)
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
290 sym_step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
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)) {
301 rb_yield(rb_str_intern(i));
302 iter[0] = iter[1];
303 }
304 return Qnil;
305 }
306
307 static VALUE
308 step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
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
326 discrete_object_p(VALUE obj)
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
333 range_step_size(VALUE range, VALUE args, VALUE eobj)
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
350 if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
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
391 range_step(int argc, VALUE *argv, VALUE range)
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
512 is_integer_p(VALUE v)
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
571 range_bsearch(VALUE range)
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
690 each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
691 {
692 rb_yield(v);
693 return Qnil;
694 }
695
696 static VALUE
697 sym_each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
698 {
699 rb_yield(rb_str_intern(v));
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
716 range_size(VALUE range)
717 {
718 VALUE b = RANGE_BEG(range), e = RANGE_END(range);
719 if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
720 return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
721 }
722 return Qnil;
723 }
724
725 static VALUE
726 range_enum_size(VALUE range, VALUE args, VALUE eobj)
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
753 range_each(VALUE range)
754 {
755 VALUE beg, end;
756
757 RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
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
810 range_begin(VALUE range)
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
828 range_end(VALUE range)
829 {
830 return RANGE_END(range);
831 }
832
833
834 static VALUE
835 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
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
862 range_first(int argc, VALUE *argv, VALUE range)
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
895 range_last(int argc, VALUE *argv, VALUE range)
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
918 range_min(VALUE range)
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
949 range_max(VALUE range)
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
1057 range_to_s(VALUE range)
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
1072 inspect_range(VALUE range, VALUE dummy, int recur)
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
1100 range_inspect(VALUE range)
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
1125 range_eqq(VALUE range, VALUE val)
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
1146 range_include(VALUE range, VALUE val)
1147 {
1148 VALUE beg = RANGE_BEG(range);
1149 VALUE end = RANGE_END(range);
1150 int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1151 rb_obj_is_kind_of(beg, rb_cNumeric) ||
1152 rb_obj_is_kind_of(end, rb_cNumeric);
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
1209 range_cover(VALUE range, VALUE val)
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
1229 range_dumper(VALUE range)
1230 {
1231 VALUE v;
1232 NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 1));
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
1243 range_loader(VALUE range, VALUE obj)
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
1257 range_alloc(VALUE klass)
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
1322 Init_Range(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
1335 rb_cRange = rb_struct_define_without_accessor(
1336 "Range", rb_cObject, range_alloc,
1337 "begin", "end", "excl", NULL);
1338
1339 rb_include_module(rb_cRange, rb_mEnumerable);
1340 rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
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 }
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:106
T_OBJECT
#define T_OBJECT
Definition: ruby.h:477
is_integer_p
static int is_integer_p(VALUE v)
Definition: range.c:512
RANGE_BEG
#define RANGE_BEG(r)
Definition: range.c:25
FALSE
#define FALSE
Definition: nkf.h:174
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1288
Init_Range
void Init_Range(void)
Definition: range.c:1322
rb_range_values
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:981
range_max
static VALUE range_max(VALUE range)
Definition: range.c:949
FIXNUM_FLAG
#define FIXNUM_FLAG
Definition: ruby.h:430
ruby.h
range_dumper
static VALUE range_dumper(VALUE range)
Definition: range.c:1229
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2140
range_include
static VALUE range_include(VALUE range, VALUE val)
Definition: range.c:1146
Qtrue
#define Qtrue
Definition: ruby.h:426
each_i
static VALUE each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
Definition: range.c:690
RBOOL
#define RBOOL(v)
Definition: range.c:31
rb_hash_end
st_index_t rb_hash_end(st_index_t)
id_succ
static ID id_succ
Definition: range.c:23
idLE
Definition: id.h:81
range_bsearch
static VALUE range_bsearch(VALUE range)
Definition: range.c:571
rb_struct_init_copy
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:707
range_loader
static VALUE range_loader(VALUE range, VALUE obj)
Definition: range.c:1243
range_modify
static void range_modify(VALUE range)
Definition: range.c:79
sym_each_i
static VALUE sym_each_i(RB_BLOCK_CALL_FUNC_ARGLIST(v, arg))
Definition: range.c:697
rb_ary_last
VALUE rb_ary_last(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1329
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_struct_alloc_noinit
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:235
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
id_excl
static ID id_excl
Definition: range.c:23
step_i
static VALUE step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
Definition: range.c:308
inspect_range
static VALUE inspect_range(VALUE range, VALUE dummy, int recur)
Definition: range.c:1072
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
rb_to_int
VALUE rb_to_int(VALUE)
Definition: object.c:2679
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
EXCL
#define EXCL(r)
Definition: range.c:33
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4982
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
rb_block_call
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
st_index_t
st_data_t st_index_t
Definition: st.h:48
RGENGC_WB_PROTECTED_OBJECT
#define RGENGC_WB_PROTECTED_OBJECT
Definition: ruby.h:723
range_to_s
static VALUE range_to_s(VALUE range)
Definition: range.c:1057
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
rb_Float
VALUE rb_Float(VALUE)
Definition: object.c:2895
rb_range_new
VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end)
Definition: range.c:70
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2665
rb_cmpint
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2909
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:552
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:90
range_each_func
static void range_each_func(VALUE range, rb_block_call_func *func, VALUE arg)
Definition: range.c:266
id.h
rb_name_error
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:967
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1511
recursive_eql
static VALUE recursive_eql(VALUE range, VALUE obj, int recur)
Definition: range.c:202
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
range_eql
static VALUE range_eql(VALUE range, VALUE obj)
Definition: range.c:230
range_size
static VALUE range_size(VALUE range)
Definition: range.c:716
rb_block_call_func
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1513
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1154
rb_rescue
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:799
range_step
static VALUE range_step(int argc, VALUE *argv, VALUE range)
Definition: range.c:391
rb_Array
VALUE rb_Array(VALUE)
Definition: object.c:3014
range_initialize_copy
static VALUE range_initialize_copy(VALUE range, VALUE orig)
Definition: range.c:109
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
val
#define val
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4993
BSEARCH
#define BSEARCH(conv)
id_div
static ID id_div
Definition: range.c:23
range_enum_size
static VALUE range_enum_size(VALUE range, VALUE args, VALUE eobj)
Definition: range.c:726
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1011
ruby_num_interval_step_size
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1813
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
ISASCII
#define ISASCII(c)
Definition: ruby.h:1766
range_initialize
static VALUE range_initialize(int argc, VALUE *argv, VALUE range)
Definition: range.c:97
first_i
static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
Definition: range.c:835
T_FLOAT
#define T_FLOAT
Definition: ruby.h:481
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
range_step_size
static VALUE range_step_size(VALUE range, VALUE args, VALUE eobj)
Definition: range.c:333
range
#define range(low, item, hi)
Definition: date_strftime.c:21
BSEARCH_CHECK
#define BSEARCH_CHECK(val)
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1801
err
int err
Definition: win32.c:114
range_first
static VALUE range_first(int argc, VALUE *argv, VALUE range)
Definition: range.c:862
rb_sym_to_s
VALUE rb_sym_to_s(VALUE)
Definition: string.c:8478
ruby_float_step
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:1782
encoding.h
id_cmp
static ID id_cmp
Definition: range.c:23
id_end
static ID id_end
Definition: range.c:23
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
rb_intern
#define rb_intern(str)
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
range_check
static VALUE range_check(VALUE *args)
Definition: range.c:43
range_min
static VALUE range_min(VALUE range)
Definition: range.c:918
range_hash
static VALUE range_hash(VALUE range)
Definition: range.c:249
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_eql
int rb_eql(VALUE, VALUE)
Definition: object.c:100
range_init
static void range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
Definition: range.c:49
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
range_exclude_end_p
static VALUE range_exclude_end_p(VALUE range)
Definition: range.c:127
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
internal.h
ID
unsigned long ID
Definition: ruby.h:89
Qnil
#define Qnil
Definition: ruby.h:427
discrete_object_p
static int discrete_object_p(VALUE obj)
Definition: range.c:326
RANGE_END
#define RANGE_END(r)
Definition: range.c:26
RANGE_SET_END
#define RANGE_SET_END(r, v)
Definition: range.c:29
VALUE
unsigned long VALUE
Definition: ruby.h:88
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:237
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
rb_cInteger
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1568
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:274
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1575
sym_step_i
static VALUE sym_step_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
Definition: range.c:290
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1062
RANGE_SET_EXCL
#define RANGE_SET_EXCL(r, v)
Definition: range.c:30
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1309
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
rb_range_beg_len
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:1005
recursive_equal
static VALUE recursive_equal(VALUE range, VALUE obj, int recur)
Definition: range.c:133
recur
#define recur(fmt)
Definition: date_strptime.c:147
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
rb_equal
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
range_end
static VALUE range_end(VALUE range)
Definition: range.c:828
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
range_inspect
static VALUE range_inspect(VALUE range)
Definition: range.c:1100
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
r_lt
static int r_lt(VALUE a, VALUE b)
Definition: range.c:173
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
range_begin
static VALUE range_begin(VALUE range)
Definition: range.c:810
rb_cRange
VALUE rb_cRange
Definition: range.c:22
range_last
static VALUE range_last(int argc, VALUE *argv, VALUE range)
Definition: range.c:895
id_beg
static ID id_beg
Definition: range.c:23
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1134
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1679
RANGE_EXCL
#define RANGE_EXCL(r)
Definition: range.c:27
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
RTEST
#define RTEST(v)
Definition: ruby.h:437
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:113
T_STRING
#define T_STRING
Definition: ruby.h:482
OBJ_INFECT
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
rb_hash_uint
st_index_t rb_hash_uint(st_index_t, st_index_t)
range_alloc
static VALUE range_alloc(VALUE klass)
Definition: range.c:1257
hash
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
range_each
static VALUE range_each(VALUE range)
Definition: range.c:753
RObject
Definition: ruby.h:762
rb_struct_define_without_accessor
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:288
rb_inspect
VALUE rb_inspect(VALUE)
Definition: object.c:470
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: string.c:7467
range_eqq
static VALUE range_eqq(VALUE range, VALUE val)
Definition: range.c:1125
range_eq
static VALUE range_eq(VALUE range, VALUE obj)
Definition: range.c:162
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:354
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
Qundef
#define Qundef
Definition: ruby.h:428
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1587
r_le
static int r_le(VALUE a, VALUE b)
Definition: range.c:185
range_cover
static VALUE range_cover(VALUE range, VALUE val)
Definition: range.c:1209
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
id_integer_p
static ID id_integer_p
Definition: range.c:23
RANGE_SET_BEG
#define RANGE_SET_BEG(r, v)
Definition: range.c:28
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
range_failed
static VALUE range_failed(void)
Definition: range.c:36
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1296
argv
char ** argv
Definition: ruby.c:132
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:815