~ubuntu-branches/ubuntu/trusty/ruby1.9/trusty

« back to all changes in this revision

Viewing changes to range.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Hermann
  • Date: 2008-01-24 11:42:29 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20080124114229-jw2f87rdxlq6gp11
Tags: 1.9.0.0-2ubuntu1
* Merge from debian unstable, remaining changes:
  - Robustify check for target_os, fixing build failure on lpia.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  range.c -
4
4
 
5
 
  $Author: matz $
6
 
  $Date: 2007-08-25 12:29:39 +0900 (土, 25  8月 2007) $
 
5
  $Author: nobu $
 
6
  $Date: 2007-12-05 15:15:23 +0900 (Wed, 05 Dec 2007) $
7
7
  created at: Thu Aug 19 17:46:47 JST 1993
8
8
 
9
9
  Copyright (C) 1993-2007 Yukihiro Matsumoto
15
15
VALUE rb_cRange;
16
16
static ID id_cmp, id_succ, id_beg, id_end, id_excl;
17
17
 
18
 
#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
19
 
#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
 
18
#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
 
19
#define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
 
20
#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
 
21
 
 
22
#define EXCL(r) RTEST(RANGE_EXCL(r))
 
23
#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
20
24
 
21
25
static VALUE
22
26
range_failed(void)
48
52
    }
49
53
 
50
54
    SET_EXCL(range, exclude_end);
51
 
    rb_ivar_set(range, id_beg, beg);
52
 
    rb_ivar_set(range, id_end, end);
 
55
    RSTRUCT(range)->as.ary[0] = beg;
 
56
    RSTRUCT(range)->as.ary[1] = end;
53
57
}
54
58
 
55
59
VALUE
77
81
    
78
82
    rb_scan_args(argc, argv, "21", &beg, &end, &flags);
79
83
    /* Ranges are immutable, so that they should be initialized only once. */
80
 
    if (rb_ivar_defined(range, id_beg)) {
 
84
    if (RANGE_EXCL(range) != Qnil) {
81
85
        rb_name_error(rb_intern("initialize"), "`initialize' called twice");
82
86
    }
83
87
    range_init(range, beg, end, RTEST(flags));
121
125
    if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
122
126
        return Qfalse;
123
127
 
124
 
    if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
 
128
    if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
125
129
        return Qfalse;
126
 
    if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
 
130
    if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
127
131
        return Qfalse;
128
132
 
129
133
    if (EXCL(range) != EXCL(obj))
183
187
    if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
184
188
        return Qfalse;
185
189
 
186
 
    if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
 
190
    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
187
191
        return Qfalse;
188
 
    if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
 
192
    if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
189
193
        return Qfalse;
190
194
 
191
195
    if (EXCL(range) != EXCL(obj))
209
213
    long hash = EXCL(range);
210
214
    VALUE v;
211
215
 
212
 
    v = rb_hash(rb_ivar_get(range, id_beg));
 
216
    v = rb_hash(RANGE_BEG(range));
213
217
    hash ^= v << 1;
214
 
    v = rb_hash(rb_ivar_get(range, id_end));
 
218
    v = rb_hash(RANGE_END(range));
215
219
    hash ^= v << 9;
216
220
    hash ^= EXCL(range) << 24;
217
221
 
243
247
static VALUE
244
248
step_i(VALUE i, void *arg)
245
249
{
246
 
    long *iter = (long *)arg;
 
250
    VALUE *iter = arg;
247
251
 
248
 
    iter[0]--;
249
 
    if (iter[0] == 0) {
 
252
    if (FIXNUM_P(iter[0])) {
 
253
        iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
 
254
    }
 
255
    else {
 
256
        VALUE one = INT2FIX(1);
 
257
        iter[0] = rb_funcall(iter[0], '-', 1, &one);
 
258
    }
 
259
    if (iter[0] == INT2FIX(0)) {
250
260
        rb_yield(i);
251
261
        iter[0] = iter[1];
252
262
    }
289
299
 
290
300
    RETURN_ENUMERATOR(range, argc, argv);
291
301
 
292
 
    b = rb_ivar_get(range, id_beg);
293
 
    e = rb_ivar_get(range, id_end);
 
302
    b = RANGE_BEG(range);
 
303
    e = RANGE_END(range);
294
304
    if (rb_scan_args(argc, argv, "01", &step) == 0) {
295
305
        step = INT2FIX(1);
296
 
    }
297
 
 
298
 
    unit = NUM2LONG(step);
 
306
        unit = 1;
 
307
    }
 
308
    else if (FIXNUM_P(step)) {
 
309
        unit = NUM2LONG(step);
 
310
    }
 
311
    else {
 
312
        VALUE tmp = rb_to_int(step);
 
313
        unit = rb_cmpint(tmp, step, INT2FIX(0));
 
314
        step = tmp;
 
315
    }
299
316
    if (unit < 0) {
300
317
        rb_raise(rb_eArgError, "step can't be negative");
301
 
    } 
 
318
    }
302
319
    if (unit == 0)
303
320
        rb_raise(rb_eArgError, "step can't be 0");
304
 
    if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
 
321
    if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
305
322
        long end = FIX2LONG(e);
306
323
        long i;
307
324
 
308
325
        if (!EXCL(range))
309
326
            end += 1;
310
 
        for (i = FIX2LONG(b); i < end; i += unit) {
 
327
        i = FIX2LONG(b);        
 
328
        while (i < end) {
311
329
            rb_yield(LONG2NUM(i));
 
330
            if (i + unit < i) break;
 
331
            i += unit;
312
332
        }
313
333
    }
314
334
    else {
315
335
        VALUE tmp = rb_check_string_type(b);
316
336
 
317
337
        if (!NIL_P(tmp)) {
318
 
            VALUE args[2];
319
 
            long iter[2];
 
338
            VALUE args[2], iter[2];
320
339
 
321
340
            b = tmp;
322
341
            args[0] = e;
323
342
            args[1] = EXCL(range) ? Qtrue : Qfalse;
324
 
            iter[0] = 1;
325
 
            iter[1] = unit;
 
343
            iter[0] = INT2FIX(1);
 
344
            iter[1] = step;
326
345
            rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
327
346
        }
328
347
        else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
336
355
            }
337
356
        }
338
357
        else {
339
 
            long args[2];
 
358
            VALUE args[2];
340
359
 
341
360
            if (!rb_respond_to(b, id_succ)) {
342
361
                rb_raise(rb_eTypeError, "can't iterate from %s",
343
362
                         rb_obj_classname(b));
344
363
            }
345
 
            args[0] = 1;
346
 
            args[1] = unit;
 
364
            args[0] = INT2FIX(1);
 
365
            args[1] = step;
347
366
            range_each_func(range, step_i, b, e, args);
348
367
        }
349
368
    }
382
401
 
383
402
    RETURN_ENUMERATOR(range, 0, 0);
384
403
 
385
 
    beg = rb_ivar_get(range, id_beg);
386
 
    end = rb_ivar_get(range, id_end);
 
404
    beg = RANGE_BEG(range);
 
405
    end = RANGE_END(range);
387
406
 
388
407
    if (!rb_respond_to(beg, id_succ)) {
389
408
        rb_raise(rb_eTypeError, "can't iterate from %s",
414
433
 
415
434
/*
416
435
 *  call-seq:
417
 
 *     rng.first    => obj
418
436
 *     rng.begin    => obj
419
437
 *  
420
438
 *  Returns the first object in <i>rng</i>.
421
439
 */
422
440
 
423
441
static VALUE
424
 
range_first(VALUE range)
 
442
range_begin(VALUE range)
425
443
{
426
 
    return rb_ivar_get(range, id_beg);
 
444
    return RANGE_BEG(range);
427
445
}
428
446
 
429
447
 
430
448
/*
431
449
 *  call-seq:
432
450
 *     rng.end    => obj
433
 
 *     rng.last   => obj
434
451
 *  
435
452
 *  Returns the object that defines the end of <i>rng</i>.
436
453
 *     
440
457
 
441
458
 
442
459
static VALUE
443
 
range_last(VALUE range)
444
 
{
445
 
    return rb_ivar_get(range, id_end);
446
 
}
 
460
range_end(VALUE range)
 
461
{
 
462
    return RANGE_END(range);
 
463
}
 
464
 
 
465
 
 
466
static VALUE
 
467
first_i(VALUE i, VALUE *ary)
 
468
{
 
469
    long n = NUM2LONG(ary[0]);
 
470
 
 
471
    if (n <= 0) {
 
472
        rb_iter_break();
 
473
    }
 
474
    rb_ary_push(ary[1], i);
 
475
    n--;
 
476
    ary[0] = INT2NUM(n);
 
477
    return Qnil;
 
478
}
 
479
 
 
480
/*
 
481
 *  call-seq:
 
482
 *     rng.first    => obj
 
483
 *     rng.first(n) => an_array
 
484
 *  
 
485
 *  Returns the first object in <i>rng</i>, or the first +n+ elements.
 
486
 */
 
487
 
 
488
static VALUE
 
489
range_first(int argc, VALUE *argv, VALUE range)
 
490
{
 
491
    VALUE n, ary[2];
 
492
 
 
493
    if (argc == 0) return RANGE_BEG(range);
 
494
 
 
495
    rb_scan_args(argc, argv, "1", &n);
 
496
    ary[0] = n;
 
497
    ary[1] = rb_ary_new2(NUM2LONG(n));
 
498
    rb_block_call(range, rb_intern("each"), 0, 0, first_i, (VALUE)ary);
 
499
 
 
500
    return ary[1];
 
501
}
 
502
 
 
503
 
 
504
/*
 
505
 *  call-seq:
 
506
 *     rng.last    => obj
 
507
 *     rng.last(n) => an_array
 
508
 *  
 
509
 *  Returns the last object in <i>rng</i>, or the last +n+ elements.
 
510
 */
 
511
 
 
512
static VALUE
 
513
range_last(int argc, VALUE *argv, VALUE range)
 
514
{
 
515
    VALUE rb_ary_last(int, VALUE *, VALUE);
 
516
 
 
517
    if (argc == 0) return RANGE_END(range);
 
518
    return rb_ary_last(argc, argv, rb_Array(range)); 
 
519
}
 
520
 
447
521
 
448
522
/*
449
523
 *  call-seq:
464
538
        return rb_call_super(0, 0);
465
539
    }
466
540
    else {
467
 
        VALUE b = rb_ivar_get(range, id_beg);
468
 
        VALUE e = rb_ivar_get(range, id_end);
 
541
        VALUE b = RANGE_BEG(range);
 
542
        VALUE e = RANGE_END(range);
469
543
        int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
470
544
 
471
545
        if (c > 0 || (c == 0 && EXCL(range)))
489
563
static VALUE
490
564
range_max(VALUE range)
491
565
{
492
 
    VALUE e = rb_ivar_get(range, id_end);
 
566
    VALUE e = RANGE_END(range);
493
567
    int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);
494
568
 
495
569
    if (rb_block_given_p() || (EXCL(range) && !ip)) {
496
570
        return rb_call_super(0, 0);
497
571
    }
498
572
    else {
499
 
        VALUE b = rb_ivar_get(range, id_beg);
 
573
        VALUE b = RANGE_BEG(range);
500
574
        int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
501
575
 
502
576
        if (c > 0)
519
593
    long beg, end, excl;
520
594
 
521
595
    if (rb_obj_is_kind_of(range, rb_cRange)) {
522
 
        b = rb_ivar_get(range, id_beg);
523
 
        e = rb_ivar_get(range, id_end);
 
596
        b = RANGE_BEG(range);
 
597
        e = RANGE_END(range);
524
598
        excl = EXCL(range);
525
599
    }
526
600
    else {
578
652
{
579
653
    VALUE str, str2;
580
654
 
581
 
    str = rb_obj_as_string(rb_ivar_get(range, id_beg));
582
 
    str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
 
655
    str = rb_obj_as_string(RANGE_BEG(range));
 
656
    str2 = rb_obj_as_string(RANGE_END(range));
583
657
    str = rb_str_dup(str);
584
658
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
585
659
    rb_str_append(str, str2);
590
664
 
591
665
/*
592
666
 * call-seq:
593
 
 *   rng.to_splat   => array
594
 
 *
595
 
 * Convert this range object to an array to splat.
596
 
 */
597
 
 
598
 
static VALUE
599
 
range_to_splat(VALUE range)
600
 
{
601
 
    return rb_convert_type(range, T_ARRAY, "Array", "to_a");
602
 
}
603
 
 
604
 
/*
605
 
 * call-seq:
606
667
 *   rng.inspect  => string
607
668
 *
608
669
 * Convert this range object to a printable form (using 
616
677
{
617
678
    VALUE str, str2;
618
679
 
619
 
    str = rb_inspect(rb_ivar_get(range, id_beg));
620
 
    str2 = rb_inspect(rb_ivar_get(range, id_end));
 
680
    str = rb_inspect(RANGE_BEG(range));
 
681
    str2 = rb_inspect(RANGE_END(range));
621
682
    str = rb_str_dup(str);
622
683
    rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
623
684
    rb_str_append(str, str2);
668
729
static VALUE
669
730
range_include(VALUE range, VALUE val)
670
731
{
671
 
    VALUE beg = rb_ivar_get(range, id_beg);
672
 
    VALUE end = rb_ivar_get(range, id_end);
 
732
    VALUE beg = RANGE_BEG(range);
 
733
    VALUE end = RANGE_END(range);
673
734
    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
674
735
             rb_obj_is_kind_of(beg, rb_cNumeric) ||
675
736
             rb_obj_is_kind_of(end, rb_cNumeric);
711
772
{
712
773
    VALUE beg, end;
713
774
 
714
 
    beg = rb_ivar_get(range, id_beg);
715
 
    end = rb_ivar_get(range, id_end);
 
775
    beg = RANGE_BEG(range);
 
776
    end = RANGE_END(range);
716
777
    if (r_le(beg, val)) {
717
778
        if (EXCL(range)) {
718
779
            if (r_lt(val, end))
726
787
    return Qfalse;
727
788
}
728
789
 
 
790
static VALUE
 
791
range_dumper(VALUE range)
 
792
{
 
793
    VALUE v;
 
794
    NEWOBJ(m, struct RObject);
 
795
    OBJSETUP(m, rb_cObject, T_OBJECT);
 
796
 
 
797
    v = (VALUE)m;
 
798
 
 
799
    rb_ivar_set(v, id_excl, RANGE_EXCL(range));
 
800
    rb_ivar_set(v, id_beg, RANGE_BEG(range));
 
801
    rb_ivar_set(v, id_end, RANGE_END(range));
 
802
    return v;
 
803
}
 
804
 
 
805
static VALUE
 
806
range_loader(VALUE range, VALUE obj)
 
807
{
 
808
    if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
 
809
        rb_raise(rb_eTypeError, "not a dumped range object");
 
810
    }
 
811
 
 
812
    RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
 
813
    RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
 
814
    RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
 
815
    return range;
 
816
}
 
817
 
 
818
static VALUE
 
819
range_alloc(VALUE klass)
 
820
{
 
821
  /* rb_struct_alloc_noinit itself should not be used because
 
822
   * rb_marshal_define_compat uses equality of allocaiton function */
 
823
    return rb_struct_alloc_noinit(klass);
 
824
}
729
825
 
730
826
/*  A <code>Range</code> represents an interval---a set of values with a
731
827
 *  start and an end. Ranges may be constructed using the
782
878
void
783
879
Init_Range(void)
784
880
{
785
 
    rb_cRange = rb_define_class("Range", rb_cObject);
 
881
    id_cmp = rb_intern("<=>");
 
882
    id_succ = rb_intern("succ");
 
883
    id_beg = rb_intern("begin");
 
884
    id_end = rb_intern("end");
 
885
    id_excl = rb_intern("excl");
 
886
 
 
887
    rb_cRange = rb_struct_define_without_accessor(
 
888
        "Range", rb_cObject, range_alloc,
 
889
        "begin", "end", "excl", NULL);
 
890
 
786
891
    rb_include_module(rb_cRange, rb_mEnumerable);
 
892
    rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
787
893
    rb_define_method(rb_cRange, "initialize", range_initialize, -1);
788
894
    rb_define_method(rb_cRange, "==", range_eq, 1);
789
895
    rb_define_method(rb_cRange, "===", range_eqq, 1);
791
897
    rb_define_method(rb_cRange, "hash", range_hash, 0);
792
898
    rb_define_method(rb_cRange, "each", range_each, 0);
793
899
    rb_define_method(rb_cRange, "step", range_step, -1);
794
 
    rb_define_method(rb_cRange, "first", range_first, 0);
795
 
    rb_define_method(rb_cRange, "last", range_last, 0);
796
 
    rb_define_method(rb_cRange, "begin", range_first, 0);
797
 
    rb_define_method(rb_cRange, "end", range_last, 0);
 
900
    rb_define_method(rb_cRange, "begin", range_begin, 0);
 
901
    rb_define_method(rb_cRange, "end", range_end, 0);
 
902
    rb_define_method(rb_cRange, "first", range_first, -1);
 
903
    rb_define_method(rb_cRange, "last", range_last, -1);
798
904
    rb_define_method(rb_cRange, "min", range_min, 0);
799
905
    rb_define_method(rb_cRange, "max", range_max, 0);
800
906
    rb_define_method(rb_cRange, "to_s", range_to_s, 0);
801
907
    rb_define_method(rb_cRange, "inspect", range_inspect, 0);
802
 
    rb_define_method(rb_cRange, "to_splat", range_to_splat, 0);
803
908
 
804
909
    rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
805
910
 
806
911
    rb_define_method(rb_cRange, "member?", range_include, 1);
807
912
    rb_define_method(rb_cRange, "include?", range_include, 1);
808
913
    rb_define_method(rb_cRange, "cover?", range_cover, 1);
809
 
 
810
 
    id_cmp = rb_intern("<=>");
811
 
    id_succ = rb_intern("succ");
812
 
    id_beg = rb_intern("begin");
813
 
    id_end = rb_intern("end");
814
 
    id_excl = rb_intern("excl");
815
914
}