Ruby 2.0.0p353(2013-11-22revision43784)

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