Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

range.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 range.c -
4
5 $Author$
6 created at: Thu Aug 19 17:46:47 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10 **********************************************************************/
11
12 #include "internal.h"
13 #include "id.h"
14 #include <assert.h>
15
16 #ifdef HAVE_FLOAT_H
17 #include <float.h>
18 #endif
19 #include <math.h>
20
21 VALUE rb_cRange;
22 static ID id_beg, id_end, id_excl;
23 #define id_cmp idCmp
24 #define id_succ idSucc
25
26 static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
27
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 void
36 range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
37 {
38 if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) {
39 VALUE v;
40
41 v = rb_funcall(beg, id_cmp, 1, end);
42 if (NIL_P(v))
43 rb_raise(rb_eArgError, "bad value for range");
44 }
45
46 RANGE_SET_EXCL(range, exclude_end);
47 RANGE_SET_BEG(range, beg);
48 RANGE_SET_END(range, end);
49 }
50
51 VALUE
52 rb_range_new(VALUE beg, VALUE end, int exclude_end)
53 {
54 VALUE range = rb_obj_alloc(rb_cRange);
55
56 range_init(range, beg, end, RBOOL(exclude_end));
57 return range;
58 }
59
60 static void
61 range_modify(VALUE range)
62 {
63 rb_check_frozen(range);
64 /* Ranges are immutable, so that they should be initialized only once. */
65 if (RANGE_EXCL(range) != Qnil) {
66 rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
67 }
68 }
69
70 /*
71 * call-seq:
72 * Range.new(begin, end, exclude_end=false) -> rng
73 *
74 * Constructs a range using the given +begin+ and +end+. If the +exclude_end+
75 * parameter is omitted or is <code>false</code>, the range will include
76 * the end object; otherwise, it will be excluded.
77 */
78
79 static VALUE
80 range_initialize(int argc, VALUE *argv, VALUE range)
81 {
82 VALUE beg, end, flags;
83
84 rb_scan_args(argc, argv, "21", &beg, &end, &flags);
85 range_modify(range);
86 range_init(range, beg, end, RBOOL(RTEST(flags)));
87 return Qnil;
88 }
89
90 /* :nodoc: */
91 static VALUE
92 range_initialize_copy(VALUE range, VALUE orig)
93 {
94 range_modify(range);
95 rb_struct_init_copy(range, orig);
96 return range;
97 }
98
99 /*
100 * call-seq:
101 * rng.exclude_end? -> true or false
102 *
103 * Returns <code>true</code> if the range excludes its end value.
104 *
105 * (1..5).exclude_end? #=> false
106 * (1...5).exclude_end? #=> true
107 */
108
109 static VALUE
110 range_exclude_end_p(VALUE range)
111 {
112 return EXCL(range) ? Qtrue : Qfalse;
113 }
114
115 static VALUE
116 recursive_equal(VALUE range, VALUE obj, int recur)
117 {
118 if (recur) return Qtrue; /* Subtle! */
119 if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
120 return Qfalse;
121 if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
122 return Qfalse;
123
124 if (EXCL(range) != EXCL(obj))
125 return Qfalse;
126 return Qtrue;
127 }
128
129
130 /*
131 * call-seq:
132 * rng == obj -> true or false
133 *
134 * Returns <code>true</code> only if +obj+ is a Range, has equivalent
135 * begin and end items (by comparing them with <code>==</code>), and has
136 * the same #exclude_end? setting as the range.
137 *
138 * (0..2) == (0..2) #=> true
139 * (0..2) == Range.new(0,2) #=> true
140 * (0..2) == (0...2) #=> false
141 *
142 */
143
144 static VALUE
145 range_eq(VALUE range, VALUE obj)
146 {
147 if (range == obj)
148 return Qtrue;
149 if (!rb_obj_is_kind_of(obj, rb_cRange))
150 return Qfalse;
151
152 return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
153 }
154
155 /* compares _a_ and _b_ and returns:
156 * < 0: a < b
157 * = 0: a = b
158 * > 0: a > b or non-comparable
159 */
160 static int
161 r_less(VALUE a, VALUE b)
162 {
163 VALUE r = rb_funcall(a, id_cmp, 1, b);
164
165 if (NIL_P(r))
166 return INT_MAX;
167 return rb_cmpint(r, a, b);
168 }
169
170 static VALUE
171 recursive_eql(VALUE range, VALUE obj, int recur)
172 {
173 if (recur) return Qtrue; /* Subtle! */
174 if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
175 return Qfalse;
176 if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
177 return Qfalse;
178
179 if (EXCL(range) != EXCL(obj))
180 return Qfalse;
181 return Qtrue;
182 }
183
184 /*
185 * call-seq:
186 * rng.eql?(obj) -> true or false
187 *
188 * Returns <code>true</code> only if +obj+ is a Range, has equivalent
189 * begin and end items (by comparing them with <code>eql?</code>),
190 * and has the same #exclude_end? setting as the range.
191 *
192 * (0..2).eql?(0..2) #=> true
193 * (0..2).eql?(Range.new(0,2)) #=> true
194 * (0..2).eql?(0...2) #=> false
195 *
196 */
197
198 static VALUE
199 range_eql(VALUE range, VALUE obj)
200 {
201 if (range == obj)
202 return Qtrue;
203 if (!rb_obj_is_kind_of(obj, rb_cRange))
204 return Qfalse;
205 return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
206 }
207
208 /*
209 * call-seq:
210 * rng.hash -> integer
211 *
212 * Compute a hash-code for this range. Two ranges with equal
213 * begin and end points (using <code>eql?</code>), and the same
214 * #exclude_end? value will generate the same hash-code.
215 *
216 * See also Object#hash.
217 */
218
219 static VALUE
220 range_hash(VALUE range)
221 {
222 st_index_t hash = EXCL(range);
223 VALUE v;
224
225 hash = rb_hash_start(hash);
226 v = rb_hash(RANGE_BEG(range));
227 hash = rb_hash_uint(hash, NUM2LONG(v));
228 v = rb_hash(RANGE_END(range));
229 hash = rb_hash_uint(hash, NUM2LONG(v));
230 hash = rb_hash_uint(hash, EXCL(range) << 24);
231 hash = rb_hash_end(hash);
232
233 return ST2FIX(hash);
234 }
235
236 static void
237 range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg)
238 {
239 int c;
240 VALUE b = RANGE_BEG(range);
241 VALUE e = RANGE_END(range);
242 VALUE v = b;
243
244 if (EXCL(range)) {
245 while (r_less(v, e) < 0) {
246 if ((*func)(v, arg)) break;
247 v = rb_funcallv(v, id_succ, 0, 0);
248 }
249 }
250 else {
251 while ((c = r_less(v, e)) <= 0) {
252 if ((*func)(v, arg)) break;
253 if (!c) break;
254 v = rb_funcallv(v, id_succ, 0, 0);
255 }
256 }
257 }
258
259 static int
260 sym_step_i(VALUE i, VALUE arg)
261 {
262 VALUE *iter = (VALUE *)arg;
263
264 if (FIXNUM_P(iter[0])) {
265 iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
266 }
267 else {
268 iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
269 }
270 if (iter[0] == INT2FIX(0)) {
271 rb_yield(rb_str_intern(i));
272 iter[0] = iter[1];
273 }
274 return 0;
275 }
276
277 static int
278 step_i(VALUE i, VALUE arg)
279 {
280 VALUE *iter = (VALUE *)arg;
281
282 if (FIXNUM_P(iter[0])) {
283 iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
284 }
285 else {
286 iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
287 }
288 if (iter[0] == INT2FIX(0)) {
289 rb_yield(i);
290 iter[0] = iter[1];
291 }
292 return 0;
293 }
294
295 static int
296 discrete_object_p(VALUE obj)
297 {
298 if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
299 return rb_respond_to(obj, id_succ);
300 }
301
302 static int
303 linear_object_p(VALUE obj)
304 {
305 if (FIXNUM_P(obj) || FLONUM_P(obj)) return TRUE;
306 if (SPECIAL_CONST_P(obj)) return FALSE;
307 switch (BUILTIN_TYPE(obj)) {
308 case T_FLOAT:
309 case T_BIGNUM:
310 return TRUE;
311 }
312 if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE;
313 if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE;
314 return FALSE;
315 }
316
317 static VALUE
318 check_step_domain(VALUE step)
319 {
320 VALUE zero = INT2FIX(0);
321 int cmp;
322 if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
323 step = rb_to_int(step);
324 }
325 cmp = rb_cmpint(rb_funcallv(step, idCmp, 1, &zero), step, zero);
326 if (cmp < 0) {
327 rb_raise(rb_eArgError, "step can't be negative");
328 }
329 else if (cmp == 0) {
330 rb_raise(rb_eArgError, "step can't be 0");
331 }
332 return step;
333 }
334
335 static VALUE
336 range_step_size(VALUE range, VALUE args, VALUE eobj)
337 {
338 VALUE b = RANGE_BEG(range), e = RANGE_END(range);
339 VALUE step = INT2FIX(1);
340 if (args) {
341 step = check_step_domain(RARRAY_AREF(args, 0));
342 }
343
344 if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
345 return ruby_num_interval_step_size(b, e, step, EXCL(range));
346 }
347 return Qnil;
348 }
349
350 /*
351 * Document-method: Range#step
352 * Document-method: Range#%
353 * call-seq:
354 * rng.step(n=1) {| obj | block } -> rng
355 * rng.step(n=1) -> an_enumerator
356 * rng.step(n=1) -> an_arithmetic_sequence
357 * rng % n -> an_enumerator
358 * rng % n -> an_arithmetic_sequence
359 *
360 * Iterates over the range, passing each <code>n</code>th element to the block.
361 * If begin and end are numeric, +n+ is added for each iteration.
362 * Otherwise #step invokes #succ to iterate through range elements.
363 *
364 * If no block is given, an enumerator is returned instead.
365 * Especially, the enumerator is an Enumerator::ArithmeticSequence
366 * if begin and end of the range are numeric.
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 b = RANGE_BEG(range);
396 e = RANGE_END(range);
397 step = (!rb_check_arity(argc, 0, 1) ? INT2FIX(1) : argv[0]);
398
399 if (!rb_block_given_p()) {
400 const VALUE b_num_p = rb_obj_is_kind_of(b, rb_cNumeric);
401 const VALUE e_num_p = rb_obj_is_kind_of(e, rb_cNumeric);
402 if ((b_num_p && (NIL_P(e) || e_num_p)) || (NIL_P(b) && e_num_p)) {
403 return rb_arith_seq_new(range, ID2SYM(rb_frame_this_func()), argc, argv,
404 range_step_size, b, e, step, EXCL(range));
405 }
406
407 RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);
408 }
409
410 step = check_step_domain(step);
411
412 if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) {
413 long i = FIX2LONG(b), unit = FIX2LONG(step);
414 do {
415 rb_yield(LONG2FIX(i));
416 i += unit; /* FIXABLE+FIXABLE never overflow */
417 } while (FIXABLE(i));
418 b = LONG2NUM(i);
419
420 for (;; b = rb_big_plus(b, step))
421 rb_yield(b);
422 }
423 else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
424 long end = FIX2LONG(e);
425 long i, unit = FIX2LONG(step);
426
427 if (!EXCL(range))
428 end += 1;
429 i = FIX2LONG(b);
430 while (i < end) {
431 rb_yield(LONG2NUM(i));
432 if (i + unit < i) break;
433 i += unit;
434 }
435
436 }
437 else if (SYMBOL_P(b) && (NIL_P(e) || SYMBOL_P(e))) { /* symbols are special */
438 VALUE iter[2];
439 iter[0] = INT2FIX(1);
440 iter[1] = step;
441
442 b = rb_sym2str(b);
443 if (NIL_P(e)) {
444 rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter);
445 }
446 else {
447 rb_str_upto_each(b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
448 }
449 }
450 else if (ruby_float_step(b, e, step, EXCL(range), TRUE)) {
451 /* done */
452 }
453 else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
454 !NIL_P(rb_check_to_integer(b, "to_int")) ||
455 !NIL_P(rb_check_to_integer(e, "to_int"))) {
456 ID op = EXCL(range) ? '<' : idLE;
457 VALUE v = b;
458 int i = 0;
459
460 while (NIL_P(e) || RTEST(rb_funcall(v, op, 1, e))) {
461 rb_yield(v);
462 i++;
463 v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
464 }
465 }
466 else {
467 tmp = rb_check_string_type(b);
468
469 if (!NIL_P(tmp)) {
470 VALUE iter[2];
471
472 b = tmp;
473 iter[0] = INT2FIX(1);
474 iter[1] = step;
475
476 if (NIL_P(e)) {
477 rb_str_upto_endless_each(b, step_i, (VALUE)iter);
478 }
479 else {
480 rb_str_upto_each(b, e, EXCL(range), step_i, (VALUE)iter);
481 }
482 }
483 else {
484 VALUE args[2];
485
486 if (!discrete_object_p(b)) {
487 rb_raise(rb_eTypeError, "can't iterate from %s",
488 rb_obj_classname(b));
489 }
490 args[0] = INT2FIX(1);
491 args[1] = step;
492 range_each_func(range, step_i, (VALUE)args);
493 }
494 }
495 return range;
496 }
497
498 static VALUE
499 range_percent_step(VALUE range, VALUE step)
500 {
501 return range_step(1, &step, range);
502 }
503
504 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
505 union int64_double {
506 int64_t i;
507 double d;
508 };
509
510 static VALUE
511 int64_as_double_to_num(int64_t i)
512 {
513 union int64_double convert;
514 if (i < 0) {
515 convert.i = -i;
516 return DBL2NUM(-convert.d);
517 }
518 else {
519 convert.i = i;
520 return DBL2NUM(convert.d);
521 }
522 }
523
524 static int64_t
525 double_as_int64(double d)
526 {
527 union int64_double convert;
528 convert.d = fabs(d);
529 return d < 0 ? -convert.i : convert.i;
530 }
531 #endif
532
533 static int
534 is_integer_p(VALUE v)
535 {
536 ID id_integer_p;
537 VALUE is_int;
538 CONST_ID(id_integer_p, "integer?");
539 is_int = rb_check_funcall(v, id_integer_p, 0, 0);
540 return RTEST(is_int) && is_int != Qundef;
541 }
542
543 static VALUE
544 bsearch_integer_range(VALUE beg, VALUE end, int excl)
545 {
546 VALUE satisfied = Qnil;
547 int smaller;
548
549 #define BSEARCH_CHECK(expr) \
550 do { \
551 VALUE val = (expr); \
552 VALUE v = rb_yield(val); \
553 if (FIXNUM_P(v)) { \
554 if (v == INT2FIX(0)) return val; \
555 smaller = (SIGNED_VALUE)v < 0; \
556 } \
557 else if (v == Qtrue) { \
558 satisfied = val; \
559 smaller = 1; \
560 } \
561 else if (v == Qfalse || v == Qnil) { \
562 smaller = 0; \
563 } \
564 else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
565 int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
566 if (!cmp) return val; \
567 smaller = cmp < 0; \
568 } \
569 else { \
570 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE \
571 " (must be numeric, true, false or nil)", \
572 rb_obj_class(v)); \
573 } \
574 } while (0)
575
576 VALUE low = rb_to_int(beg);
577 VALUE high = rb_to_int(end);
578 VALUE mid, org_high;
579 ID id_div;
580 CONST_ID(id_div, "div");
581
582 if (excl) high = rb_funcall(high, '-', 1, INT2FIX(1));
583 org_high = high;
584
585 while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
586 mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
587 BSEARCH_CHECK(mid);
588 if (smaller) {
589 high = mid;
590 }
591 else {
592 low = rb_funcall(mid, '+', 1, INT2FIX(1));
593 }
594 }
595 if (rb_equal(low, org_high)) {
596 BSEARCH_CHECK(low);
597 if (!smaller) return Qnil;
598 }
599 return satisfied;
600 }
601
602 /*
603 * call-seq:
604 * rng.bsearch {|obj| block } -> value
605 *
606 * By using binary search, finds a value in range which meets the given
607 * condition in O(log n) where n is the size of the range.
608 *
609 * You can use this method in two use cases: a find-minimum mode and
610 * a find-any mode. In either case, the elements of the range must be
611 * monotone (or sorted) with respect to the block.
612 *
613 * In find-minimum mode (this is a good choice for typical use case),
614 * the block must return true or false, and there must be a value x
615 * so that:
616 *
617 * - the block returns false for any value which is less than x, and
618 * - the block returns true for any value which is greater than or
619 * equal to x.
620 *
621 * If x is within the range, this method returns the value x.
622 * Otherwise, it returns nil.
623 *
624 * ary = [0, 4, 7, 10, 12]
625 * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
626 * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
627 * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
628 * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
629 *
630 * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
631 *
632 * In find-any mode (this behaves like libc's bsearch(3)), the block
633 * must return a number, and there must be two values x and y (x <= y)
634 * so that:
635 *
636 * - the block returns a positive number for v if v < x,
637 * - the block returns zero for v if x <= v < y, and
638 * - the block returns a negative number for v if y <= v.
639 *
640 * This method returns any value which is within the intersection of
641 * the given range and x...y (if any). If there is no value that
642 * satisfies the condition, it returns nil.
643 *
644 * ary = [0, 100, 100, 100, 200]
645 * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
646 * (0..4).bsearch {|i| 300 - ary[i] } #=> nil
647 * (0..4).bsearch {|i| 50 - ary[i] } #=> nil
648 *
649 * You must not mix the two modes at a time; the block must always
650 * return either true/false, or always return a number. It is
651 * undefined which value is actually picked up at each iteration.
652 */
653
654 static VALUE
655 range_bsearch(VALUE range)
656 {
657 VALUE beg, end, satisfied = Qnil;
658 int smaller;
659
660 /* Implementation notes:
661 * Floats are handled by mapping them to 64 bits integers.
662 * Apart from sign issues, floats and their 64 bits integer have the
663 * same order, assuming they are represented as exponent followed
664 * by the mantissa. This is true with or without implicit bit.
665 *
666 * Finding the average of two ints needs to be careful about
667 * potential overflow (since float to long can use 64 bits)
668 * as well as the fact that -1/2 can be 0 or -1 in C89.
669 *
670 * Note that -0.0 is mapped to the same int as 0.0 as we don't want
671 * (-1...0.0).bsearch to yield -0.0.
672 */
673
674 #define BSEARCH(conv) \
675 do { \
676 RETURN_ENUMERATOR(range, 0, 0); \
677 if (EXCL(range)) high--; \
678 org_high = high; \
679 while (low < high) { \
680 mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
681 : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
682 BSEARCH_CHECK(conv(mid)); \
683 if (smaller) { \
684 high = mid; \
685 } \
686 else { \
687 low = mid + 1; \
688 } \
689 } \
690 if (low == org_high) { \
691 BSEARCH_CHECK(conv(low)); \
692 if (!smaller) return Qnil; \
693 } \
694 return satisfied; \
695 } while (0)
696
697
698 beg = RANGE_BEG(range);
699 end = RANGE_END(range);
700
701 if (FIXNUM_P(beg) && FIXNUM_P(end)) {
702 long low = FIX2LONG(beg);
703 long high = FIX2LONG(end);
704 long mid, org_high;
705 BSEARCH(INT2FIX);
706 }
707 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
708 else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
709 int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg)));
710 int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end)));
711 int64_t mid, org_high;
712 BSEARCH(int64_as_double_to_num);
713 }
714 #endif
715 else if (is_integer_p(beg) && is_integer_p(end)) {
716 RETURN_ENUMERATOR(range, 0, 0);
717 return bsearch_integer_range(beg, end, EXCL(range));
718 }
719 else if (is_integer_p(beg) && NIL_P(end)) {
720 VALUE diff = LONG2FIX(1);
721 RETURN_ENUMERATOR(range, 0, 0);
722 while (1) {
723 VALUE mid = rb_funcall(beg, '+', 1, diff);
724 BSEARCH_CHECK(mid);
725 if (smaller) {
726 return bsearch_integer_range(beg, mid, 0);
727 }
728 diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
729 }
730 }
731 else if (NIL_P(beg) && is_integer_p(end)) {
732 VALUE diff = LONG2FIX(-1);
733 RETURN_ENUMERATOR(range, 0, 0);
734 while (1) {
735 VALUE mid = rb_funcall(end, '+', 1, diff);
736 BSEARCH_CHECK(mid);
737 if (!smaller) {
738 return bsearch_integer_range(mid, end, 0);
739 }
740 diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
741 }
742 }
743 else {
744 rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
745 }
746 return range;
747 }
748
749 static int
750 each_i(VALUE v, VALUE arg)
751 {
752 rb_yield(v);
753 return 0;
754 }
755
756 static int
757 sym_each_i(VALUE v, VALUE arg)
758 {
759 rb_yield(rb_str_intern(v));
760 return 0;
761 }
762
763 /*
764 * call-seq:
765 * rng.size -> num
766 *
767 * Returns the number of elements in the range. Both the begin and the end of
768 * the Range must be Numeric, otherwise nil is returned.
769 *
770 * (10..20).size #=> 11
771 * ('a'..'z').size #=> nil
772 * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
773 */
774
775 static VALUE
776 range_size(VALUE range)
777 {
778 VALUE b = RANGE_BEG(range), e = RANGE_END(range);
779 if (rb_obj_is_kind_of(b, rb_cNumeric)) {
780 if (rb_obj_is_kind_of(e, rb_cNumeric)) {
781 return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
782 }
783 if (NIL_P(e)) {
784 return DBL2NUM(HUGE_VAL);
785 }
786 }
787 else if (NIL_P(b)) {
788 return DBL2NUM(HUGE_VAL);
789 }
790
791 return Qnil;
792 }
793
794 /*
795 * call-seq:
796 * rng.to_a -> array
797 * rng.entries -> array
798 *
799 * Returns an array containing the items in the range.
800 *
801 * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
802 * (1..).to_a #=> RangeError: cannot convert endless range to an array
803 */
804
805 static VALUE
806 range_to_a(VALUE range)
807 {
808 if (NIL_P(RANGE_END(range))) {
809 rb_raise(rb_eRangeError, "cannot convert endless range to an array");
810 }
811 return rb_call_super(0, 0);
812 }
813
814 static VALUE
815 range_enum_size(VALUE range, VALUE args, VALUE eobj)
816 {
817 return range_size(range);
818 }
819
820 /*
821 * call-seq:
822 * rng.each {| i | block } -> rng
823 * rng.each -> an_enumerator
824 *
825 * Iterates over the elements of range, passing each in turn to the
826 * block.
827 *
828 * The +each+ method can only be used if the begin object of the range
829 * supports the +succ+ method. A TypeError is raised if the object
830 * does not have +succ+ method defined (like Float).
831 *
832 * If no block is given, an enumerator is returned instead.
833 *
834 * (10..15).each {|n| print n, ' ' }
835 * # prints: 10 11 12 13 14 15
836 *
837 * (2.5..5).each {|n| print n, ' ' }
838 * # raises: TypeError: can't iterate from Float
839 */
840
841 static VALUE
842 range_each(VALUE range)
843 {
844 VALUE beg, end;
845 long i, lim;
846
847 RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
848
849 beg = RANGE_BEG(range);
850 end = RANGE_END(range);
851
852 if (FIXNUM_P(beg) && NIL_P(end)) {
853 fixnum_endless:
854 i = FIX2LONG(beg);
855 while (FIXABLE(i)) {
856 rb_yield(LONG2FIX(i++));
857 }
858 beg = LONG2NUM(i);
859 bignum_endless:
860 for (;; beg = rb_big_plus(beg, INT2FIX(1)))
861 rb_yield(beg);
862 }
863 else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
864 fixnum_loop:
865 lim = FIX2LONG(end);
866 if (!EXCL(range))
867 lim += 1;
868 for (i = FIX2LONG(beg); i < lim; i++) {
869 rb_yield(LONG2FIX(i));
870 }
871 }
872 else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
873 if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
874 if (!FIXNUM_P(beg)) {
875 if (RBIGNUM_NEGATIVE_P(beg)) {
876 do {
877 rb_yield(beg);
878 } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
879 if (NIL_P(end)) goto fixnum_endless;
880 if (FIXNUM_P(end)) goto fixnum_loop;
881 }
882 else {
883 if (NIL_P(end)) goto bignum_endless;
884 if (FIXNUM_P(end)) return range;
885 }
886 }
887 if (FIXNUM_P(beg)) {
888 i = FIX2LONG(beg);
889 do {
890 rb_yield(LONG2FIX(i));
891 } while (POSFIXABLE(++i));
892 beg = LONG2NUM(i);
893 }
894 ASSUME(!FIXNUM_P(beg));
895 ASSUME(!SPECIAL_CONST_P(end));
896 }
897 if (!FIXNUM_P(beg) && RBIGNUM_SIGN(beg) == RBIGNUM_SIGN(end)) {
898 if (EXCL(range)) {
899 while (rb_big_cmp(beg, end) == INT2FIX(-1)) {
900 rb_yield(beg);
901 beg = rb_big_plus(beg, INT2FIX(1));
902 }
903 }
904 else {
905 VALUE c;
906 while ((c = rb_big_cmp(beg, end)) != INT2FIX(1)) {
907 rb_yield(beg);
908 if (c == INT2FIX(0)) break;
909 beg = rb_big_plus(beg, INT2FIX(1));
910 }
911 }
912 }
913 }
914 else if (SYMBOL_P(beg) && (NIL_P(end) || SYMBOL_P(end))) { /* symbols are special */
915 beg = rb_sym2str(beg);
916 if (NIL_P(end)) {
917 rb_str_upto_endless_each(beg, sym_each_i, 0);
918 }
919 else {
920 rb_str_upto_each(beg, rb_sym2str(end), EXCL(range), sym_each_i, 0);
921 }
922 }
923 else {
924 VALUE tmp = rb_check_string_type(beg);
925
926 if (!NIL_P(tmp)) {
927 if (!NIL_P(end)) {
928 rb_str_upto_each(tmp, end, EXCL(range), each_i, 0);
929 }
930 else {
931 rb_str_upto_endless_each(tmp, each_i, 0);
932 }
933 }
934 else {
935 if (!discrete_object_p(beg)) {
936 rb_raise(rb_eTypeError, "can't iterate from %s",
937 rb_obj_classname(beg));
938 }
939 if (!NIL_P(end))
940 range_each_func(range, each_i, 0);
941 else
942 for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
943 rb_yield(beg);
944 }
945 }
946 return range;
947 }
948
949 /*
950 * call-seq:
951 * rng.begin -> obj
952 *
953 * Returns the object that defines the beginning of the range.
954 *
955 * (1..10).begin #=> 1
956 */
957
958 static VALUE
959 range_begin(VALUE range)
960 {
961 return RANGE_BEG(range);
962 }
963
964
965 /*
966 * call-seq:
967 * rng.end -> obj
968 *
969 * Returns the object that defines the end of the range.
970 *
971 * (1..10).end #=> 10
972 * (1...10).end #=> 10
973 */
974
975
976 static VALUE
977 range_end(VALUE range)
978 {
979 return RANGE_END(range);
980 }
981
982
983 static VALUE
984 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
985 {
986 VALUE *ary = (VALUE *)cbarg;
987 long n = NUM2LONG(ary[0]);
988
989 if (n <= 0) {
990 rb_iter_break();
991 }
992 rb_ary_push(ary[1], i);
993 n--;
994 ary[0] = INT2NUM(n);
995 return Qnil;
996 }
997
998 /*
999 * call-seq:
1000 * rng.first -> obj
1001 * rng.first(n) -> an_array
1002 *
1003 * Returns the first object in the range, or an array of the first +n+
1004 * elements.
1005 *
1006 * (10..20).first #=> 10
1007 * (10..20).first(3) #=> [10, 11, 12]
1008 */
1009
1010 static VALUE
1011 range_first(int argc, VALUE *argv, VALUE range)
1012 {
1013 VALUE n, ary[2];
1014
1015 if (NIL_P(RANGE_BEG(range))) {
1016 rb_raise(rb_eRangeError, "cannot get the first element of beginless range");
1017 }
1018 if (argc == 0) return RANGE_BEG(range);
1019
1020 rb_scan_args(argc, argv, "1", &n);
1021 ary[0] = n;
1022 ary[1] = rb_ary_new2(NUM2LONG(n));
1023 rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
1024
1025 return ary[1];
1026 }
1027
1028 static VALUE
1029 rb_int_range_last(int argc, VALUE *argv, VALUE range)
1030 {
1031 static const VALUE ONE = INT2FIX(1);
1032
1033 VALUE b, e, len_1, len, nv, ary;
1034 int x;
1035 long n;
1036
1037 assert(argc > 0);
1038
1039 b = RANGE_BEG(range);
1040 e = RANGE_END(range);
1041 assert(RB_INTEGER_TYPE_P(b) && RB_INTEGER_TYPE_P(e));
1042
1043 x = EXCL(range);
1044
1045 len_1 = rb_int_minus(e, b);
1046 if (FIXNUM_ZERO_P(len_1) || rb_num_negative_p(len_1)) {
1047 return rb_ary_new_capa(0);
1048 }
1049
1050 if (x) {
1051 e = rb_int_minus(e, ONE);
1052 len = len_1;
1053 }
1054 else {
1055 len = rb_int_plus(len_1, ONE);
1056 }
1057
1058 rb_scan_args(argc, argv, "1", &nv);
1059 n = NUM2LONG(nv);
1060 if (n < 0) {
1061 rb_raise(rb_eArgError, "negative array size");
1062 }
1063
1064 nv = LONG2NUM(n);
1065 if (RTEST(rb_int_gt(nv, len))) {
1066 nv = len;
1067 n = NUM2LONG(nv);
1068 }
1069
1070 ary = rb_ary_new_capa(n);
1071 b = rb_int_minus(e, nv);
1072 while (n) {
1073 b = rb_int_plus(b, ONE);
1074 rb_ary_push(ary, b);
1075 --n;
1076 }
1077
1078 return ary;
1079 }
1080
1081 /*
1082 * call-seq:
1083 * rng.last -> obj
1084 * rng.last(n) -> an_array
1085 *
1086 * Returns the last object in the range,
1087 * or an array of the last +n+ elements.
1088 *
1089 * Note that with no arguments +last+ will return the object that defines
1090 * the end of the range even if #exclude_end? is +true+.
1091 *
1092 * (10..20).last #=> 20
1093 * (10...20).last #=> 20
1094 * (10..20).last(3) #=> [18, 19, 20]
1095 * (10...20).last(3) #=> [17, 18, 19]
1096 */
1097
1098 static VALUE
1099 range_last(int argc, VALUE *argv, VALUE range)
1100 {
1101 VALUE b, e;
1102
1103 if (NIL_P(RANGE_END(range))) {
1104 rb_raise(rb_eRangeError, "cannot get the last element of endless range");
1105 }
1106 if (argc == 0) return RANGE_END(range);
1107
1108 b = RANGE_BEG(range);
1109 e = RANGE_END(range);
1110 if (RB_INTEGER_TYPE_P(b) && RB_INTEGER_TYPE_P(e) &&
1111 RB_LIKELY(rb_method_basic_definition_p(rb_cRange, idEach))) {
1112 return rb_int_range_last(argc, argv, range);
1113 }
1114 return rb_ary_last(argc, argv, rb_Array(range));
1115 }
1116
1117
1118 /*
1119 * call-seq:
1120 * rng.min -> obj
1121 * rng.min {| a,b | block } -> obj
1122 * rng.min(n) -> array
1123 * rng.min(n) {| a,b | block } -> array
1124 *
1125 * Returns the minimum value in the range. Returns +nil+ if the begin
1126 * value of the range is larger than the end value. Returns +nil+ if
1127 * the begin value of an exclusive range is equal to the end value.
1128 *
1129 * Can be given an optional block to override the default comparison
1130 * method <code>a <=> b</code>.
1131 *
1132 * (10..20).min #=> 10
1133 */
1134
1135
1136 static VALUE
1137 range_min(int argc, VALUE *argv, VALUE range)
1138 {
1139 if (NIL_P(RANGE_BEG(range))) {
1140 rb_raise(rb_eRangeError, "cannot get the minimum of beginless range");
1141 }
1142
1143 if (rb_block_given_p()) {
1144 if (NIL_P(RANGE_END(range))) {
1145 rb_raise(rb_eRangeError, "cannot get the minimum of endless range with custom comparison method");
1146 }
1147 return rb_call_super(argc, argv);
1148 }
1149 else if (argc != 0) {
1150 return range_first(argc, argv, range);
1151 }
1152 else {
1153 struct cmp_opt_data cmp_opt = { 0, 0 };
1154 VALUE b = RANGE_BEG(range);
1155 VALUE e = RANGE_END(range);
1156 int c = NIL_P(e) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt);
1157
1158 if (c > 0 || (c == 0 && EXCL(range)))
1159 return Qnil;
1160 return b;
1161 }
1162 }
1163
1164 /*
1165 * call-seq:
1166 * rng.max -> obj
1167 * rng.max {| a,b | block } -> obj
1168 * rng.max(n) -> obj
1169 * rng.max(n) {| a,b | block } -> obj
1170 *
1171 * Returns the maximum value in the range. Returns +nil+ if the begin
1172 * value of the range larger than the end value. Returns +nil+ if
1173 * the begin value of an exclusive range is equal to the end value.
1174 *
1175 * Can be given an optional block to override the default comparison
1176 * method <code>a <=> b</code>.
1177 *
1178 * (10..20).max #=> 20
1179 */
1180
1181 static VALUE
1182 range_max(int argc, VALUE *argv, VALUE range)
1183 {
1184 VALUE e = RANGE_END(range);
1185 int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
1186
1187 if (NIL_P(RANGE_END(range))) {
1188 rb_raise(rb_eRangeError, "cannot get the maximum of endless range");
1189 }
1190
1191 if (rb_block_given_p() || (EXCL(range) && !nm) || argc) {
1192 if (NIL_P(RANGE_BEG(range))) {
1193 rb_raise(rb_eRangeError, "cannot get the maximum of beginless range with custom comparison method");
1194 }
1195 return rb_call_super(argc, argv);
1196 }
1197 else {
1198 struct cmp_opt_data cmp_opt = { 0, 0 };
1199 VALUE b = RANGE_BEG(range);
1200 int c = OPTIMIZED_CMP(b, e, cmp_opt);
1201
1202 if (c > 0)
1203 return Qnil;
1204 if (EXCL(range)) {
1205 if (!RB_INTEGER_TYPE_P(e)) {
1206 rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
1207 }
1208 if (c == 0) return Qnil;
1209 if (!RB_INTEGER_TYPE_P(b)) {
1210 rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
1211 }
1212 if (FIXNUM_P(e)) {
1213 return LONG2NUM(FIX2LONG(e) - 1);
1214 }
1215 return rb_funcall(e, '-', 1, INT2FIX(1));
1216 }
1217 return e;
1218 }
1219 }
1220
1221 /*
1222 * call-seq:
1223 * rng.minmax -> [obj, obj]
1224 * rng.minmax {| a,b | block } -> [obj, obj]
1225 *
1226 * Returns a two element array which contains the minimum and the
1227 * maximum value in the range.
1228 *
1229 * Can be given an optional block to override the default comparison
1230 * method <code>a <=> b</code>.
1231 */
1232
1233 static VALUE
1234 range_minmax(VALUE range)
1235 {
1236 if (rb_block_given_p()) {
1237 return rb_call_super(0, NULL);
1238 }
1239 return rb_assoc_new(range_min(0, NULL, range), range_max(0, NULL, range));
1240 }
1241
1242 int
1243 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
1244 {
1245 VALUE b, e;
1246 int excl;
1247
1248 if (rb_obj_is_kind_of(range, rb_cRange)) {
1249 b = RANGE_BEG(range);
1250 e = RANGE_END(range);
1251 excl = EXCL(range);
1252 }
1253 else if (RTEST(rb_obj_is_kind_of(range, rb_cArithSeq))) {
1254 return (int)Qfalse;
1255 }
1256 else {
1257 VALUE x;
1258 b = rb_check_funcall(range, id_beg, 0, 0);
1259 if (b == Qundef) return (int)Qfalse;
1260 e = rb_check_funcall(range, id_end, 0, 0);
1261 if (e == Qundef) return (int)Qfalse;
1262 x = rb_check_funcall(range, rb_intern("exclude_end?"), 0, 0);
1263 if (x == Qundef) return (int)Qfalse;
1264 excl = RTEST(x);
1265 }
1266 *begp = b;
1267 *endp = e;
1268 *exclp = excl;
1269 return (int)Qtrue;
1270 }
1271
1272 VALUE
1273 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
1274 {
1275 long beg, end, origbeg, origend;
1276 VALUE b, e;
1277 int excl;
1278
1279 if (!rb_range_values(range, &b, &e, &excl))
1280 return Qfalse;
1281 beg = NIL_P(b) ? 0 : NUM2LONG(b);
1282 end = NIL_P(e) ? -1 : NUM2LONG(e);
1283 if (NIL_P(e)) excl = 0;
1284 origbeg = beg;
1285 origend = end;
1286 if (beg < 0) {
1287 beg += len;
1288 if (beg < 0)
1289 goto out_of_range;
1290 }
1291 if (end < 0)
1292 end += len;
1293 if (!excl)
1294 end++; /* include end point */
1295 if (err == 0 || err == 2) {
1296 if (beg > len)
1297 goto out_of_range;
1298 if (end > len)
1299 end = len;
1300 }
1301 len = end - beg;
1302 if (len < 0)
1303 len = 0;
1304
1305 *begp = beg;
1306 *lenp = len;
1307 return Qtrue;
1308
1309 out_of_range:
1310 if (err) {
1311 rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
1312 origbeg, excl ? "." : "", origend);
1313 }
1314 return Qnil;
1315 }
1316
1317 /*
1318 * call-seq:
1319 * rng.to_s -> string
1320 *
1321 * Convert this range object to a printable form (using #to_s to convert the
1322 * begin and end objects).
1323 */
1324
1325 static VALUE
1326 range_to_s(VALUE range)
1327 {
1328 VALUE str, str2;
1329
1330 str = rb_obj_as_string(RANGE_BEG(range));
1331 str2 = rb_obj_as_string(RANGE_END(range));
1332 str = rb_str_dup(str);
1333 rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1334 rb_str_append(str, str2);
1335
1336 return str;
1337 }
1338
1339 static VALUE
1340 inspect_range(VALUE range, VALUE dummy, int recur)
1341 {
1342 VALUE str, str2 = Qundef;
1343
1344 if (recur) {
1345 return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
1346 }
1347 if (!NIL_P(RANGE_BEG(range)) || NIL_P(RANGE_END(range))) {
1348 str = rb_str_dup(rb_inspect(RANGE_BEG(range)));
1349 }
1350 else {
1351 str = rb_str_new(0, 0);
1352 }
1353 rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1354 if (NIL_P(RANGE_BEG(range)) || !NIL_P(RANGE_END(range))) {
1355 str2 = rb_inspect(RANGE_END(range));
1356 }
1357 if (str2 != Qundef) rb_str_append(str, str2);
1358
1359 return str;
1360 }
1361
1362 /*
1363 * call-seq:
1364 * rng.inspect -> string
1365 *
1366 * Convert this range object to a printable form (using #inspect to
1367 * convert the begin and end objects).
1368 */
1369
1370
1371 static VALUE
1372 range_inspect(VALUE range)
1373 {
1374 return rb_exec_recursive(inspect_range, range, 0);
1375 }
1376
1377 static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover);
1378
1379 /*
1380 * call-seq:
1381 * rng === obj -> true or false
1382 *
1383 * Returns <code>true</code> if +obj+ is between begin and end of range,
1384 * <code>false</code> otherwise (same as #cover?). Conveniently,
1385 * <code>===</code> is the comparison operator used by <code>case</code>
1386 * statements.
1387 *
1388 * case 79
1389 * when 1..50 then puts "low"
1390 * when 51..75 then puts "medium"
1391 * when 76..100 then puts "high"
1392 * end
1393 * # Prints "high"
1394 *
1395 * case "2.6.5"
1396 * when ..."2.4" then puts "EOL"
1397 * when "2.4"..."2.5" then puts "maintenance"
1398 * when "2.5"..."2.7" then puts "stable"
1399 * when "2.7".. then puts "upcoming"
1400 * end
1401 * # Prints "stable"
1402 *
1403 */
1404
1405 static VALUE
1406 range_eqq(VALUE range, VALUE val)
1407 {
1408 VALUE ret = range_include_internal(range, val, 1);
1409 if (ret != Qundef) return ret;
1410 return r_cover_p(range, RANGE_BEG(range), RANGE_END(range), val);
1411 }
1412
1413
1414 /*
1415 * call-seq:
1416 * rng.member?(obj) -> true or false
1417 * rng.include?(obj) -> true or false
1418 *
1419 * Returns <code>true</code> if +obj+ is an element of
1420 * the range, <code>false</code> otherwise.
1421 *
1422 * ("a".."z").include?("g") #=> true
1423 * ("a".."z").include?("A") #=> false
1424 * ("a".."z").include?("cc") #=> false
1425 *
1426 * If you need to ensure +obj+ is between +begin+ and +end+, use #cover?
1427 *
1428 * ("a".."z").cover?("cc") #=> true
1429 *
1430 * If begin and end are numeric, #include? behaves like #cover?
1431 *
1432 * (1..3).include?(1.5) # => true
1433 */
1434
1435 static VALUE
1436 range_include(VALUE range, VALUE val)
1437 {
1438 VALUE ret = range_include_internal(range, val, 0);
1439 if (ret != Qundef) return ret;
1440 return rb_call_super(1, &val);
1441 }
1442
1443 static VALUE
1444 range_include_internal(VALUE range, VALUE val, int string_use_cover)
1445 {
1446 VALUE beg = RANGE_BEG(range);
1447 VALUE end = RANGE_END(range);
1448 int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1449 linear_object_p(beg) || linear_object_p(end);
1450
1451 if (nv ||
1452 !NIL_P(rb_check_to_integer(beg, "to_int")) ||
1453 !NIL_P(rb_check_to_integer(end, "to_int"))) {
1454 return r_cover_p(range, beg, end, val);
1455 }
1456 else if (RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING)) {
1457 if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) {
1458 if (string_use_cover) {
1459 return r_cover_p(range, beg, end, val);
1460 }
1461 else {
1462 VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
1463 return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range));
1464 }
1465 }
1466 else if (NIL_P(beg)) {
1467 VALUE r = rb_funcall(val, id_cmp, 1, end);
1468 if (NIL_P(r)) return Qfalse;
1469 if (rb_cmpint(r, val, end) <= 0) return Qtrue;
1470 return Qfalse;
1471 }
1472 else if (NIL_P(end)) {
1473 VALUE r = rb_funcall(beg, id_cmp, 1, val);
1474 if (NIL_P(r)) return Qfalse;
1475 if (rb_cmpint(r, beg, val) <= 0) return Qtrue;
1476 return Qfalse;
1477 }
1478 }
1479 return Qundef;
1480 }
1481
1482 static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val);
1483
1484 /*
1485 * call-seq:
1486 * rng.cover?(obj) -> true or false
1487 * rng.cover?(range) -> true or false
1488 *
1489 * Returns <code>true</code> if +obj+ is between the begin and end of
1490 * the range.
1491 *
1492 * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1493 * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1494 *
1495 * If called with a Range argument, returns <code>true</code> when the
1496 * given range is covered by the receiver,
1497 * by comparing the begin and end values. If the argument can be treated as
1498 * a sequence, this method treats it that way. In the specific case of
1499 * <code>(a..b).cover?(c...d)</code> with <code>a <= c && b < d</code>,
1500 * the end of the sequence must be calculated, which may exhibit poor
1501 * performance if <code>c</code> is non-numeric.
1502 * Returns <code>false</code> if the begin value of the
1503 * range is larger than the end value. Also returns +false+ if one of the
1504 * internal calls to <code><=></code> returns +nil+ (indicating the objects
1505 * are not comparable).
1506 *
1507 * ("a".."z").cover?("c") #=> true
1508 * ("a".."z").cover?("5") #=> false
1509 * ("a".."z").cover?("cc") #=> true
1510 * ("a".."z").cover?(1) #=> false
1511 * (1..5).cover?(2..3) #=> true
1512 * (1..5).cover?(0..6) #=> false
1513 * (1..5).cover?(1...6) #=> true
1514 */
1515
1516 static VALUE
1517 range_cover(VALUE range, VALUE val)
1518 {
1519 VALUE beg, end;
1520
1521 beg = RANGE_BEG(range);
1522 end = RANGE_END(range);
1523
1524 if (rb_obj_is_kind_of(val, rb_cRange)) {
1525 return RBOOL(r_cover_range_p(range, beg, end, val));
1526 }
1527 return r_cover_p(range, beg, end, val);
1528 }
1529
1530 static VALUE
1531 r_call_max(VALUE r)
1532 {
1533 return rb_funcallv(r, rb_intern("max"), 0, 0);
1534 }
1535
1536 static int
1537 r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1538 {
1539 VALUE val_beg, val_end, val_max;
1540 int cmp_end;
1541
1542 val_beg = RANGE_BEG(val);
1543 val_end = RANGE_END(val);
1544
1545 if (!NIL_P(end) && NIL_P(val_end)) return FALSE;
1546 if (!NIL_P(beg) && NIL_P(val_beg)) return FALSE;
1547 if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > -EXCL(val)) return FALSE;
1548 if (!NIL_P(val_beg) && !r_cover_p(range, beg, end, val_beg)) return FALSE;
1549
1550 cmp_end = r_less(end, val_end);
1551
1552 if (EXCL(range) == EXCL(val)) {
1553 return cmp_end >= 0;
1554 }
1555 else if (EXCL(range)) {
1556 return cmp_end > 0;
1557 }
1558 else if (cmp_end >= 0) {
1559 return TRUE;
1560 }
1561
1562 val_max = rb_rescue2(r_call_max, val, NULL, Qnil, rb_eTypeError, (VALUE)0);
1563 if (val_max == Qnil) return FALSE;
1564
1565 return r_less(end, val_max) >= 0;
1566 }
1567
1568 static VALUE
1569 r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1570 {
1571 if (NIL_P(beg) || r_less(beg, val) <= 0) {
1572 int excl = EXCL(range);
1573 if (NIL_P(end) || r_less(val, end) <= -excl)
1574 return Qtrue;
1575 }
1576 return Qfalse;
1577 }
1578
1579 static VALUE
1580 range_dumper(VALUE range)
1581 {
1582 VALUE v;
1583 NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 1));
1584
1585 v = (VALUE)m;
1586
1587 rb_ivar_set(v, id_excl, RANGE_EXCL(range));
1588 rb_ivar_set(v, id_beg, RANGE_BEG(range));
1589 rb_ivar_set(v, id_end, RANGE_END(range));
1590 return v;
1591 }
1592
1593 static VALUE
1594 range_loader(VALUE range, VALUE obj)
1595 {
1596 VALUE beg, end, excl;
1597
1598 if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
1599 rb_raise(rb_eTypeError, "not a dumped range object");
1600 }
1601
1602 range_modify(range);
1603 beg = rb_ivar_get(obj, id_beg);
1604 end = rb_ivar_get(obj, id_end);
1605 excl = rb_ivar_get(obj, id_excl);
1606 if (!NIL_P(excl)) {
1607 range_init(range, beg, end, RBOOL(RTEST(excl)));
1608 }
1609 return range;
1610 }
1611
1612 static VALUE
1613 range_alloc(VALUE klass)
1614 {
1615 /* rb_struct_alloc_noinit itself should not be used because
1616 * rb_marshal_define_compat uses equality of allocation function */
1617 return rb_struct_alloc_noinit(klass);
1618 }
1619
1620 /*
1621 * call-seq:
1622 * range.count -> int
1623 * range.count(item) -> int
1624 * range.count { |obj| block } -> int
1625 *
1626 * Identical to Enumerable#count, except it returns Infinity for endless
1627 * ranges.
1628 *
1629 */
1630 static VALUE
1631 range_count(int argc, VALUE *argv, VALUE range)
1632 {
1633 if (argc != 0) {
1634 /* It is odd for instance (1...).count(0) to return Infinity. Just let
1635 * it loop. */
1636 return rb_call_super(argc, argv);
1637 }
1638 else if (rb_block_given_p()) {
1639 /* Likewise it is odd for instance (1...).count {|x| x == 0 } to return
1640 * Infinity. Just let it loop. */
1641 return rb_call_super(argc, argv);
1642 }
1643 else if (NIL_P(RANGE_END(range))) {
1644 /* We are confident that the answer is Infinity. */
1645 return DBL2NUM(HUGE_VAL);
1646 }
1647 else if (NIL_P(RANGE_BEG(range))) {
1648 /* We are confident that the answer is Infinity. */
1649 return DBL2NUM(HUGE_VAL);
1650 }
1651 else {
1652 return rb_call_super(argc, argv);
1653 }
1654 }
1655
1656 /* A Range represents an interval---a set of values with a
1657 * beginning and an end. Ranges may be constructed using the
1658 * <em>s</em><code>..</code><em>e</em> and
1659 * <em>s</em><code>...</code><em>e</em> literals, or with
1660 * Range::new. Ranges constructed using <code>..</code>
1661 * run from the beginning to the end inclusively. Those created using
1662 * <code>...</code> exclude the end value. When used as an iterator,
1663 * ranges return each value in the sequence.
1664 *
1665 * (-1..-5).to_a #=> []
1666 * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
1667 * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
1668 * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
1669 *
1670 * == Beginless/Endless Ranges
1671 *
1672 * A "beginless range" and "endless range" represents a semi-infinite
1673 * range. Literal notation for a beginless range is:
1674 *
1675 * (..1)
1676 * # or
1677 * (...1)
1678 *
1679 * Literal notation for an endless range is:
1680 *
1681 * (1..)
1682 * # or similarly
1683 * (1...)
1684 *
1685 * Which is equivalent to
1686 *
1687 * (1..nil) # or similarly (1...nil)
1688 * Range.new(1, nil) # or Range.new(1, nil, true)
1689 *
1690 * Beginless/endless ranges are useful, for example, for idiomatic
1691 * slicing of arrays:
1692 *
1693 * [1, 2, 3, 4, 5][...2] # => [1, 2]
1694 * [1, 2, 3, 4, 5][2...] # => [3, 4, 5]
1695 *
1696 * Some implementation details:
1697 *
1698 * * +begin+ of beginless range and +end+ of endless range are +nil+;
1699 * * +each+ of beginless range raises an exception;
1700 * * +each+ of endless range enumerates infinite sequence (may be
1701 * useful in combination with Enumerable#take_while or similar
1702 * methods);
1703 * * <code>(1..)</code> and <code>(1...)</code> are not equal,
1704 * although technically representing the same sequence.
1705 *
1706 * == Custom Objects in Ranges
1707 *
1708 * Ranges can be constructed using any objects that can be compared
1709 * using the <code><=></code> operator.
1710 * Methods that treat the range as a sequence (#each and methods inherited
1711 * from Enumerable) expect the begin object to implement a
1712 * <code>succ</code> method to return the next object in sequence.
1713 * The #step and #include? methods require the begin
1714 * object to implement <code>succ</code> or to be numeric.
1715 *
1716 * In the <code>Xs</code> class below both <code><=></code> and
1717 * <code>succ</code> are implemented so <code>Xs</code> can be used
1718 * to construct ranges. Note that the Comparable module is included
1719 * so the <code>==</code> method is defined in terms of <code><=></code>.
1720 *
1721 * class Xs # represent a string of 'x's
1722 * include Comparable
1723 * attr :length
1724 * def initialize(n)
1725 * @length = n
1726 * end
1727 * def succ
1728 * Xs.new(@length + 1)
1729 * end
1730 * def <=>(other)
1731 * @length <=> other.length
1732 * end
1733 * def to_s
1734 * sprintf "%2d #{inspect}", @length
1735 * end
1736 * def inspect
1737 * 'x' * @length
1738 * end
1739 * end
1740 *
1741 * An example of using <code>Xs</code> to construct a range:
1742 *
1743 * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1744 * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1745 * r.member?(Xs.new(5)) #=> true
1746 *
1747 */
1748
1749 void
1750 Init_Range(void)
1751 {
1752 #undef rb_intern
1753 #define rb_intern(str) rb_intern_const(str)
1754
1755 id_beg = rb_intern("begin");
1756 id_end = rb_intern("end");
1757 id_excl = rb_intern("excl");
1758
1759 rb_cRange = rb_struct_define_without_accessor(
1760 "Range", rb_cObject, range_alloc,
1761 "begin", "end", "excl", NULL);
1762
1763 rb_include_module(rb_cRange, rb_mEnumerable);
1764 rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
1765 rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1766 rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1767 rb_define_method(rb_cRange, "==", range_eq, 1);
1768 rb_define_method(rb_cRange, "===", range_eqq, 1);
1769 rb_define_method(rb_cRange, "eql?", range_eql, 1);
1770 rb_define_method(rb_cRange, "hash", range_hash, 0);
1771 rb_define_method(rb_cRange, "each", range_each, 0);
1772 rb_define_method(rb_cRange, "step", range_step, -1);
1773 rb_define_method(rb_cRange, "%", range_percent_step, 1);
1774 rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
1775 rb_define_method(rb_cRange, "begin", range_begin, 0);
1776 rb_define_method(rb_cRange, "end", range_end, 0);
1777 rb_define_method(rb_cRange, "first", range_first, -1);
1778 rb_define_method(rb_cRange, "last", range_last, -1);
1779 rb_define_method(rb_cRange, "min", range_min, -1);
1780 rb_define_method(rb_cRange, "max", range_max, -1);
1781 rb_define_method(rb_cRange, "minmax", range_minmax, 0);
1782 rb_define_method(rb_cRange, "size", range_size, 0);
1783 rb_define_method(rb_cRange, "to_a", range_to_a, 0);
1784 rb_define_method(rb_cRange, "entries", range_to_a, 0);
1785 rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1786 rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1787
1788 rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1789
1790 rb_define_method(rb_cRange, "member?", range_include, 1);
1791 rb_define_method(rb_cRange, "include?", range_include, 1);
1792 rb_define_method(rb_cRange, "cover?", range_cover, 1);
1793 rb_define_method(rb_cRange, "count", range_count, -1);
1794 }
FLONUM_P
#define FLONUM_P(x)
Definition: ruby.h:430
rb_ary_new_capa
VALUE rb_ary_new_capa(long capa)
Definition: array.c:717
ID
unsigned long ID
Definition: ruby.h:103
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
RANGE_SET_EXCL
#define RANGE_SET_EXCL(r, v)
Definition: range.c:30
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.0.h:7900
TRUE
#define TRUE
Definition: nkf.h:175
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_range_beg_len
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:1273
assert
#define assert(x)
Definition: dlmalloc.c:1176
range
#define range(low, item, hi)
Definition: date_strftime.c:21
idEach
@ idEach
Definition: rb_mjit_min_header-2.7.0.h:8703
rb_arith_seq_new
VALUE rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, rb_enumerator_size_func *size_fn, VALUE beg, VALUE end, VALUE step, int excl)
Definition: enumerator.c:3308
id_div
#define id_div
Definition: enum.c:24
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
id_cmp
#define id_cmp
Definition: range.c:23
RBIGNUM_POSITIVE_P
#define RBIGNUM_POSITIVE_P(b)
Definition: ruby.h:1262
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:2037
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
RObject
Definition: ruby.h:922
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:133
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:2048
FIXNUM_ZERO_P
#define FIXNUM_ZERO_P(num)
Definition: internal.h:1773
RB_LIKELY
#define RB_LIKELY(x)
Definition: defines.h:91
rb_num_negative_p
int rb_num_negative_p(VALUE)
Definition: numeric.c:313
id.h
RBOOL
#define RBOOL(v)
Definition: range.c:31
Init_Range
void Init_Range(void)
Definition: range.c:1750
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:306
assert.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
RANGE_END
#define RANGE_END(r)
Definition: internal.h:2086
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_Float
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3493
rb_str_include_range_p
VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive)
Definition: string.c:4398
Qundef
#define Qundef
Definition: ruby.h:470
idInitialize
@ idInitialize
Definition: rb_mjit_min_header-2.7.0.h:8709
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
idLE
@ idLE
Definition: id.h:93
Qfalse
#define Qfalse
Definition: ruby.h:467
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:271
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:967
fabs
double fabs(double)
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
NULL
#define NULL
Definition: _sdbm.c:101
rb_cmpint
#define rb_cmpint(cmp, a, b)
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
int64_t
__int64_t int64_t
Definition: rb_mjit_min_header-2.7.0.h:1180
RBIGNUM_SIGN
#define RBIGNUM_SIGN(b)
Definition: ruby.h:1261
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_struct_alloc_noinit
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:352
T_OBJECT
#define T_OBJECT
Definition: ruby.h:523
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
ASSUME
#define ASSUME(x)
Definition: ruby.h:52
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_eql
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
EXCL
#define EXCL(r)
Definition: range.c:33
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_cRange
VALUE rb_cRange
Definition: range.c:21
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
id_succ
#define id_succ
Definition: range.c:24
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:926
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
BSEARCH_CHECK
#define BSEARCH_CHECK(expr)
FIXNUM_FLAG
#define FIXNUM_FLAG
Definition: ruby.h:472
HUGE_VAL
#define HUGE_VAL
Definition: missing.h:161
rb_str_upto_endless_each
VALUE rb_str_upto_endless_each(VALUE, int(*each)(VALUE, VALUE), VALUE)
Definition: string.c:4345
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
POSFIXABLE
#define POSFIXABLE(f)
Definition: ruby.h:397
rb_Array
VALUE rb_Array(VALUE)
Equivalent to Kernel#Array in Ruby.
Definition: object.c:3684
rb_big_cmp
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5419
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1182
RANGE_BEG
#define RANGE_BEG(r)
Definition: internal.h:2085
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.0.h:4052
rb_ary_last
VALUE rb_ary_last(int argc, const VALUE *argv, VALUE ary)
Definition: array.c:1677
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
rb_struct_define_without_accessor
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:421
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
FALSE
#define FALSE
Definition: nkf.h:174
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
rb_struct_init_copy
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:977
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
cmp_opt_data
Definition: internal.h:1322
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1546
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
rb_cArithSeq
VALUE rb_cArithSeq
Definition: enumerator.c:180
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
ruby_num_interval_step_size
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:2555
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
internal.h
OPTIMIZED_CMP
#define OPTIMIZED_CMP(a, b, data)
Definition: internal.h:1337
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
ruby_float_step
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless)
Definition: numeric.c:2524
rb_hash_end
#define rb_hash_end(h)
Definition: intern.h:816
BSEARCH
#define BSEARCH(conv)
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition: cxxanyargs.hpp:178
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argc
int argc
Definition: ruby.c:222
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
rb_big_plus
VALUE rb_big_plus(VALUE x, VALUE y)
Definition: bignum.c:5824
recur
#define recur(fmt)
Definition: date_strptime.c:152
err
int err
Definition: win32.c:135
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:966
rb_int_gt
VALUE rb_int_gt(VALUE x, VALUE y)
Definition: numeric.c:4252
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
RANGE_SET_BEG
#define RANGE_SET_BEG(r, v)
Definition: range.c:28
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:961
len
uint8_t len
Definition: escape.c:17
idCmp
@ idCmp
Definition: id.h:84
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
ONE
#define ONE
Definition: complex.c:21
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5086
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
RGENGC_WB_PROTECTED_OBJECT
#define RGENGC_WB_PROTECTED_OBJECT
Definition: ruby.h:814
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
rb_range_new
VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end)
Definition: range.c:52
FIXABLE
#define FIXABLE(f)
Definition: ruby.h:399
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
rb_range_values
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:1243
Qnil
#define Qnil
Definition: ruby.h:469
RANGE_EXCL
#define RANGE_EXCL(r)
Definition: internal.h:2087
rb_intern
#define rb_intern(str)
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1574
rb_int_plus
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3610
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
RTEST
#define RTEST(v)
Definition: ruby.h:481
RBIGNUM_NEGATIVE_P
#define RBIGNUM_NEGATIVE_P(b)
Definition: ruby.h:1263
RANGE_SET_END
#define RANGE_SET_END(r, v)
Definition: range.c:29
rb_int_minus
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3649
rb_str_upto_each
VALUE rb_str_upto_each(VALUE, VALUE, int, int(*each)(VALUE, VALUE), VALUE)
Definition: string.c:4263