00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/encoding.h"
00014
00015 VALUE rb_cRange;
00016 static ID id_cmp, id_succ, id_beg, id_end, id_excl;
00017
00018 extern VALUE rb_struct_init_copy(VALUE copy, VALUE s);
00019
00020 #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
00021 #define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
00022 #define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
00023
00024 #define EXCL(r) RTEST(RANGE_EXCL(r))
00025 #define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
00026
00027 static VALUE
00028 range_failed(void)
00029 {
00030 rb_raise(rb_eArgError, "bad value for range");
00031 return Qnil;
00032 }
00033
00034 static VALUE
00035 range_check(VALUE *args)
00036 {
00037 return rb_funcall(args[0], id_cmp, 1, args[1]);
00038 }
00039
00040 static void
00041 range_init(VALUE range, VALUE beg, VALUE end, int exclude_end)
00042 {
00043 VALUE args[2];
00044
00045 args[0] = beg;
00046 args[1] = end;
00047
00048 if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
00049 VALUE v;
00050
00051 v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
00052 if (NIL_P(v))
00053 range_failed();
00054 }
00055
00056 SET_EXCL(range, exclude_end);
00057 RSTRUCT(range)->as.ary[0] = beg;
00058 RSTRUCT(range)->as.ary[1] = end;
00059 }
00060
00061 VALUE
00062 rb_range_new(VALUE beg, VALUE end, int exclude_end)
00063 {
00064 VALUE range = rb_obj_alloc(rb_cRange);
00065
00066 range_init(range, beg, end, exclude_end);
00067 return range;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static VALUE
00080 range_initialize(int argc, VALUE *argv, VALUE range)
00081 {
00082 VALUE beg, end, flags;
00083
00084 rb_scan_args(argc, argv, "21", &beg, &end, &flags);
00085
00086 if (RANGE_EXCL(range) != Qnil) {
00087 rb_name_error(rb_intern("initialize"), "`initialize' called twice");
00088 }
00089 range_init(range, beg, end, RTEST(flags));
00090 return Qnil;
00091 }
00092
00093 #define range_initialize_copy rb_struct_init_copy
00094
00095
00096
00097
00098
00099
00100
00101
00102 static VALUE
00103 range_exclude_end_p(VALUE range)
00104 {
00105 return EXCL(range) ? Qtrue : Qfalse;
00106 }
00107
00108 static VALUE
00109 recursive_equal(VALUE range, VALUE obj, int recur)
00110 {
00111 if (recur) return Qtrue;
00112 if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
00113 return Qfalse;
00114 if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
00115 return Qfalse;
00116
00117 if (EXCL(range) != EXCL(obj))
00118 return Qfalse;
00119 return Qtrue;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static VALUE
00138 range_eq(VALUE range, VALUE obj)
00139 {
00140 if (range == obj)
00141 return Qtrue;
00142 if (!rb_obj_is_kind_of(obj, rb_cRange))
00143 return Qfalse;
00144
00145 return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
00146 }
00147
00148 static int
00149 r_lt(VALUE a, VALUE b)
00150 {
00151 VALUE r = rb_funcall(a, id_cmp, 1, b);
00152
00153 if (NIL_P(r))
00154 return (int)Qfalse;
00155 if (rb_cmpint(r, a, b) < 0)
00156 return (int)Qtrue;
00157 return (int)Qfalse;
00158 }
00159
00160 static int
00161 r_le(VALUE a, VALUE b)
00162 {
00163 int c;
00164 VALUE r = rb_funcall(a, id_cmp, 1, b);
00165
00166 if (NIL_P(r))
00167 return (int)Qfalse;
00168 c = rb_cmpint(r, a, b);
00169 if (c == 0)
00170 return (int)INT2FIX(0);
00171 if (c < 0)
00172 return (int)Qtrue;
00173 return (int)Qfalse;
00174 }
00175
00176
00177 static VALUE
00178 recursive_eql(VALUE range, VALUE obj, int recur)
00179 {
00180 if (recur) return Qtrue;
00181 if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
00182 return Qfalse;
00183 if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
00184 return Qfalse;
00185
00186 if (EXCL(range) != EXCL(obj))
00187 return Qfalse;
00188 return Qtrue;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 static VALUE
00206 range_eql(VALUE range, VALUE obj)
00207 {
00208 if (range == obj)
00209 return Qtrue;
00210 if (!rb_obj_is_kind_of(obj, rb_cRange))
00211 return Qfalse;
00212 return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
00213 }
00214
00215 static VALUE
00216 recursive_hash(VALUE range, VALUE dummy, int recur)
00217 {
00218 st_index_t hash = EXCL(range);
00219 VALUE v;
00220
00221 hash = rb_hash_start(hash);
00222 if (!recur) {
00223 v = rb_hash(RANGE_BEG(range));
00224 hash = rb_hash_uint(hash, NUM2LONG(v));
00225 v = rb_hash(RANGE_END(range));
00226 hash = rb_hash_uint(hash, NUM2LONG(v));
00227 }
00228 hash = rb_hash_uint(hash, EXCL(range) << 24);
00229 hash = rb_hash_end(hash);
00230
00231 return LONG2FIX(hash);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 static VALUE
00244 range_hash(VALUE range)
00245 {
00246 return rb_exec_recursive_outer(recursive_hash, range, 0);
00247 }
00248
00249 static void
00250 range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
00251 {
00252 int c;
00253 VALUE b = RANGE_BEG(range);
00254 VALUE e = RANGE_END(range);
00255 VALUE v = b;
00256
00257 if (EXCL(range)) {
00258 while (r_lt(v, e)) {
00259 (*func) (v, arg);
00260 v = rb_funcall(v, id_succ, 0, 0);
00261 }
00262 }
00263 else {
00264 while ((c = r_le(v, e)) != Qfalse) {
00265 (*func) (v, arg);
00266 if (c == (int)INT2FIX(0))
00267 break;
00268 v = rb_funcall(v, id_succ, 0, 0);
00269 }
00270 }
00271 }
00272
00273 static VALUE
00274 sym_step_i(VALUE i, void *arg)
00275 {
00276 VALUE *iter = arg;
00277
00278 if (FIXNUM_P(iter[0])) {
00279 iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
00280 }
00281 else {
00282 iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
00283 }
00284 if (iter[0] == INT2FIX(0)) {
00285 rb_yield(rb_str_intern(i));
00286 iter[0] = iter[1];
00287 }
00288 return Qnil;
00289 }
00290
00291 static VALUE
00292 step_i(VALUE i, void *arg)
00293 {
00294 VALUE *iter = arg;
00295
00296 if (FIXNUM_P(iter[0])) {
00297 iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
00298 }
00299 else {
00300 iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
00301 }
00302 if (iter[0] == INT2FIX(0)) {
00303 rb_yield(i);
00304 iter[0] = iter[1];
00305 }
00306 return Qnil;
00307 }
00308
00309 extern int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl);
00310
00311 static int
00312 discrete_object_p(VALUE obj)
00313 {
00314 if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE;
00315 return rb_respond_to(obj, id_succ);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 static VALUE
00351 range_step(int argc, VALUE *argv, VALUE range)
00352 {
00353 VALUE b, e, step, tmp;
00354
00355 RETURN_ENUMERATOR(range, argc, argv);
00356
00357 b = RANGE_BEG(range);
00358 e = RANGE_END(range);
00359 if (argc == 0) {
00360 step = INT2FIX(1);
00361 }
00362 else {
00363 rb_scan_args(argc, argv, "01", &step);
00364 if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
00365 step = rb_to_int(step);
00366 }
00367 if (rb_funcall(step, '<', 1, INT2FIX(0))) {
00368 rb_raise(rb_eArgError, "step can't be negative");
00369 }
00370 else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
00371 rb_raise(rb_eArgError, "step can't be 0");
00372 }
00373 }
00374
00375 if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) {
00376 long end = FIX2LONG(e);
00377 long i, unit = FIX2LONG(step);
00378
00379 if (!EXCL(range))
00380 end += 1;
00381 i = FIX2LONG(b);
00382 while (i < end) {
00383 rb_yield(LONG2NUM(i));
00384 if (i + unit < i) break;
00385 i += unit;
00386 }
00387
00388 }
00389 else if (SYMBOL_P(b) && SYMBOL_P(e)) {
00390 VALUE args[2], iter[2];
00391
00392 args[0] = rb_sym_to_s(e);
00393 args[1] = EXCL(range) ? Qtrue : Qfalse;
00394 iter[0] = INT2FIX(1);
00395 iter[1] = step;
00396 rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
00397 }
00398 else if (ruby_float_step(b, e, step, EXCL(range))) {
00399
00400 }
00401 else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
00402 !NIL_P(rb_check_to_integer(b, "to_int")) ||
00403 !NIL_P(rb_check_to_integer(e, "to_int"))) {
00404 ID op = EXCL(range) ? '<' : rb_intern("<=");
00405 VALUE v = b;
00406 int i = 0;
00407
00408 while (RTEST(rb_funcall(v, op, 1, e))) {
00409 rb_yield(v);
00410 i++;
00411 v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
00412 }
00413 }
00414 else {
00415 tmp = rb_check_string_type(b);
00416
00417 if (!NIL_P(tmp)) {
00418 VALUE args[2], iter[2];
00419
00420 b = tmp;
00421 args[0] = e;
00422 args[1] = EXCL(range) ? Qtrue : Qfalse;
00423 iter[0] = INT2FIX(1);
00424 iter[1] = step;
00425 rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
00426 }
00427 else {
00428 VALUE args[2];
00429
00430 if (!discrete_object_p(b)) {
00431 rb_raise(rb_eTypeError, "can't iterate from %s",
00432 rb_obj_classname(b));
00433 }
00434 args[0] = INT2FIX(1);
00435 args[1] = step;
00436 range_each_func(range, step_i, args);
00437 }
00438 }
00439 return range;
00440 }
00441
00442 static VALUE
00443 each_i(VALUE v, void *arg)
00444 {
00445 rb_yield(v);
00446 return Qnil;
00447 }
00448
00449 static VALUE
00450 sym_each_i(VALUE v, void *arg)
00451 {
00452 rb_yield(rb_str_intern(v));
00453 return Qnil;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 static VALUE
00478 range_each(VALUE range)
00479 {
00480 VALUE beg, end;
00481
00482 RETURN_ENUMERATOR(range, 0, 0);
00483
00484 beg = RANGE_BEG(range);
00485 end = RANGE_END(range);
00486
00487 if (FIXNUM_P(beg) && FIXNUM_P(end)) {
00488 long lim = FIX2LONG(end);
00489 long i;
00490
00491 if (!EXCL(range))
00492 lim += 1;
00493 for (i = FIX2LONG(beg); i < lim; i++) {
00494 rb_yield(LONG2FIX(i));
00495 }
00496 }
00497 else if (SYMBOL_P(beg) && SYMBOL_P(end)) {
00498 VALUE args[2];
00499
00500 args[0] = rb_sym_to_s(end);
00501 args[1] = EXCL(range) ? Qtrue : Qfalse;
00502 rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
00503 }
00504 else {
00505 VALUE tmp = rb_check_string_type(beg);
00506
00507 if (!NIL_P(tmp)) {
00508 VALUE args[2];
00509
00510 args[0] = end;
00511 args[1] = EXCL(range) ? Qtrue : Qfalse;
00512 rb_block_call(tmp, rb_intern("upto"), 2, args, rb_yield, 0);
00513 }
00514 else {
00515 if (!discrete_object_p(beg)) {
00516 rb_raise(rb_eTypeError, "can't iterate from %s",
00517 rb_obj_classname(beg));
00518 }
00519 range_each_func(range, each_i, NULL);
00520 }
00521 }
00522 return range;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 static VALUE
00533 range_begin(VALUE range)
00534 {
00535 return RANGE_BEG(range);
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 static VALUE
00551 range_end(VALUE range)
00552 {
00553 return RANGE_END(range);
00554 }
00555
00556
00557 static VALUE
00558 first_i(VALUE i, VALUE *ary)
00559 {
00560 long n = NUM2LONG(ary[0]);
00561
00562 if (n <= 0) {
00563 rb_iter_break();
00564 }
00565 rb_ary_push(ary[1], i);
00566 n--;
00567 ary[0] = INT2NUM(n);
00568 return Qnil;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 static VALUE
00580 range_first(int argc, VALUE *argv, VALUE range)
00581 {
00582 VALUE n, ary[2];
00583
00584 if (argc == 0) return RANGE_BEG(range);
00585
00586 rb_scan_args(argc, argv, "1", &n);
00587 ary[0] = n;
00588 ary[1] = rb_ary_new2(NUM2LONG(n));
00589 rb_block_call(range, rb_intern("each"), 0, 0, first_i, (VALUE)ary);
00590
00591 return ary[1];
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 static VALUE
00604 range_last(int argc, VALUE *argv, VALUE range)
00605 {
00606 VALUE rb_ary_last(int, VALUE *, VALUE);
00607
00608 if (argc == 0) return RANGE_END(range);
00609 return rb_ary_last(argc, argv, rb_Array(range));
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 static VALUE
00626 range_min(VALUE range)
00627 {
00628 if (rb_block_given_p()) {
00629 return rb_call_super(0, 0);
00630 }
00631 else {
00632 VALUE b = RANGE_BEG(range);
00633 VALUE e = RANGE_END(range);
00634 int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
00635
00636 if (c > 0 || (c == 0 && EXCL(range)))
00637 return Qnil;
00638 return b;
00639 }
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 static VALUE
00654 range_max(VALUE range)
00655 {
00656 VALUE e = RANGE_END(range);
00657 int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
00658
00659 if (rb_block_given_p() || (EXCL(range) && !nm)) {
00660 return rb_call_super(0, 0);
00661 }
00662 else {
00663 VALUE b = RANGE_BEG(range);
00664 int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
00665
00666 if (c > 0)
00667 return Qnil;
00668 if (EXCL(range)) {
00669 if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
00670 rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
00671 }
00672 if (c == 0) return Qnil;
00673 if (FIXNUM_P(e)) {
00674 return LONG2NUM(FIX2LONG(e) - 1);
00675 }
00676 return rb_funcall(e, '-', 1, INT2FIX(1));
00677 }
00678 return e;
00679 }
00680 }
00681
00682 int
00683 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
00684 {
00685 VALUE b, e;
00686 int excl;
00687
00688 if (rb_obj_is_kind_of(range, rb_cRange)) {
00689 b = RANGE_BEG(range);
00690 e = RANGE_END(range);
00691 excl = EXCL(range);
00692 }
00693 else {
00694 if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
00695 if (!rb_respond_to(range, id_end)) return (int)Qfalse;
00696 b = rb_funcall(range, id_beg, 0);
00697 e = rb_funcall(range, id_end, 0);
00698 excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
00699 }
00700 *begp = b;
00701 *endp = e;
00702 *exclp = excl;
00703 return (int)Qtrue;
00704 }
00705
00706 VALUE
00707 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
00708 {
00709 long beg, end, origbeg, origend;
00710 VALUE b, e;
00711 int excl;
00712
00713 if (!rb_range_values(range, &b, &e, &excl))
00714 return Qfalse;
00715 beg = NUM2LONG(b);
00716 end = NUM2LONG(e);
00717 origbeg = beg;
00718 origend = end;
00719 if (beg < 0) {
00720 beg += len;
00721 if (beg < 0)
00722 goto out_of_range;
00723 }
00724 if (err == 0 || err == 2) {
00725 if (beg > len)
00726 goto out_of_range;
00727 if (end > len)
00728 end = len;
00729 }
00730 if (end < 0)
00731 end += len;
00732 if (!excl)
00733 end++;
00734 len = end - beg;
00735 if (len < 0)
00736 len = 0;
00737
00738 *begp = beg;
00739 *lenp = len;
00740 return Qtrue;
00741
00742 out_of_range:
00743 if (err) {
00744 rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
00745 origbeg, excl ? "." : "", origend);
00746 }
00747 return Qnil;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757 static VALUE
00758 range_to_s(VALUE range)
00759 {
00760 VALUE str, str2;
00761
00762 str = rb_obj_as_string(RANGE_BEG(range));
00763 str2 = rb_obj_as_string(RANGE_END(range));
00764 str = rb_str_dup(str);
00765 rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
00766 rb_str_append(str, str2);
00767 OBJ_INFECT(str, str2);
00768
00769 return str;
00770 }
00771
00772 static VALUE
00773 inspect_range(VALUE range, VALUE dummy, int recur)
00774 {
00775 VALUE str, str2;
00776
00777 if (recur) {
00778 return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
00779 }
00780 str = rb_inspect(RANGE_BEG(range));
00781 str2 = rb_inspect(RANGE_END(range));
00782 str = rb_str_dup(str);
00783 rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
00784 rb_str_append(str, str2);
00785 OBJ_INFECT(str, str2);
00786
00787 return str;
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 static VALUE
00801 range_inspect(VALUE range)
00802 {
00803 return rb_exec_recursive(inspect_range, range, 0);
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 static VALUE
00827 range_eqq(VALUE range, VALUE val)
00828 {
00829 return rb_funcall(range, rb_intern("include?"), 1, val);
00830 }
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 static VALUE
00847 range_include(VALUE range, VALUE val)
00848 {
00849 VALUE beg = RANGE_BEG(range);
00850 VALUE end = RANGE_END(range);
00851 int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
00852 rb_obj_is_kind_of(beg, rb_cNumeric) ||
00853 rb_obj_is_kind_of(end, rb_cNumeric);
00854
00855 if (nv ||
00856 !NIL_P(rb_check_to_integer(beg, "to_int")) ||
00857 !NIL_P(rb_check_to_integer(end, "to_int"))) {
00858 if (r_le(beg, val)) {
00859 if (EXCL(range)) {
00860 if (r_lt(val, end))
00861 return Qtrue;
00862 }
00863 else {
00864 if (r_le(val, end))
00865 return Qtrue;
00866 }
00867 }
00868 return Qfalse;
00869 }
00870 else if (TYPE(beg) == T_STRING && TYPE(end) == T_STRING &&
00871 RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
00872 if (NIL_P(val)) return Qfalse;
00873 if (TYPE(val) == T_STRING) {
00874 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
00875 return Qfalse;
00876 else {
00877 char b = RSTRING_PTR(beg)[0];
00878 char e = RSTRING_PTR(end)[0];
00879 char v = RSTRING_PTR(val)[0];
00880
00881 if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
00882 if (b <= v && v < e) return Qtrue;
00883 if (!EXCL(range) && v == e) return Qtrue;
00884 return Qfalse;
00885 }
00886 }
00887 }
00888 }
00889
00890 return rb_call_super(1, &val);
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 static VALUE
00907 range_cover(VALUE range, VALUE val)
00908 {
00909 VALUE beg, end;
00910
00911 beg = RANGE_BEG(range);
00912 end = RANGE_END(range);
00913 if (r_le(beg, val)) {
00914 if (EXCL(range)) {
00915 if (r_lt(val, end))
00916 return Qtrue;
00917 }
00918 else {
00919 if (r_le(val, end))
00920 return Qtrue;
00921 }
00922 }
00923 return Qfalse;
00924 }
00925
00926 static VALUE
00927 range_dumper(VALUE range)
00928 {
00929 VALUE v;
00930 NEWOBJ(m, struct RObject);
00931 OBJSETUP(m, rb_cObject, T_OBJECT);
00932
00933 v = (VALUE)m;
00934
00935 rb_ivar_set(v, id_excl, RANGE_EXCL(range));
00936 rb_ivar_set(v, id_beg, RANGE_BEG(range));
00937 rb_ivar_set(v, id_end, RANGE_END(range));
00938 return v;
00939 }
00940
00941 static VALUE
00942 range_loader(VALUE range, VALUE obj)
00943 {
00944 if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
00945 rb_raise(rb_eTypeError, "not a dumped range object");
00946 }
00947
00948 RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
00949 RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
00950 RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
00951 return range;
00952 }
00953
00954 static VALUE
00955 range_alloc(VALUE klass)
00956 {
00957
00958
00959 return rb_struct_alloc_noinit(klass);
00960 }
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 void
01015 Init_Range(void)
01016 {
01017 #undef rb_intern
01018 #define rb_intern(str) rb_intern_const(str)
01019
01020 id_cmp = rb_intern("<=>");
01021 id_succ = rb_intern("succ");
01022 id_beg = rb_intern("begin");
01023 id_end = rb_intern("end");
01024 id_excl = rb_intern("excl");
01025
01026 rb_cRange = rb_struct_define_without_accessor(
01027 "Range", rb_cObject, range_alloc,
01028 "begin", "end", "excl", NULL);
01029
01030 rb_include_module(rb_cRange, rb_mEnumerable);
01031 rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
01032 rb_define_method(rb_cRange, "initialize", range_initialize, -1);
01033 rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
01034 rb_define_method(rb_cRange, "==", range_eq, 1);
01035 rb_define_method(rb_cRange, "===", range_eqq, 1);
01036 rb_define_method(rb_cRange, "eql?", range_eql, 1);
01037 rb_define_method(rb_cRange, "hash", range_hash, 0);
01038 rb_define_method(rb_cRange, "each", range_each, 0);
01039 rb_define_method(rb_cRange, "step", range_step, -1);
01040 rb_define_method(rb_cRange, "begin", range_begin, 0);
01041 rb_define_method(rb_cRange, "end", range_end, 0);
01042 rb_define_method(rb_cRange, "first", range_first, -1);
01043 rb_define_method(rb_cRange, "last", range_last, -1);
01044 rb_define_method(rb_cRange, "min", range_min, 0);
01045 rb_define_method(rb_cRange, "max", range_max, 0);
01046 rb_define_method(rb_cRange, "to_s", range_to_s, 0);
01047 rb_define_method(rb_cRange, "inspect", range_inspect, 0);
01048
01049 rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
01050
01051 rb_define_method(rb_cRange, "member?", range_include, 1);
01052 rb_define_method(rb_cRange, "include?", range_include, 1);
01053 rb_define_method(rb_cRange, "cover?", range_cover, 1);
01054 }
01055