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