Project

General

Profile

Feature #14084 ยป enumerator_next.diff

tessi (Philipp Tessenow), 11/06/2017 02:27 AM

View differences:

enumerator.c
824 824
    return ary2sv(vs, 0);
825 825
}
826 826

  
827
/*
828
 * call-seq:
829
 *   e.next?   -> object
830
 *
831
 * Returns whether there is a next object in the enumerator, but doesn't
832
 * move the internal position forward.
833
 *
834
 * === Example
835
 *
836
 *   a = [1,2,3]
837
 *   e = a.to_enum
838
 *   p e.next?   #=> true
839
 *   p e.next    #=> 1
840
 *   p e.next?   #=> true
841
 *   p e.next    #=> 2
842
 *   p e.next?   #=> true
843
 *   p e.next    #=> 3
844
 *   p e.next?   #=> false
845
 *   p e.next    #raises StopIteration
846
 *
847
 */
848

  
849
static VALUE
850
enumerator_has_next(VALUE obj)
851
{
852
    struct enumerator *e = enumerator_ptr(obj);
853
    if (e->stop_exc)
854
        return Qfalse;
855

  
856
    if (e->lookahead != Qundef)
857
        return Qtrue;
858

  
859
    VALUE curr, vs;
860

  
861
    curr = rb_fiber_current();
862

  
863
    if (!e->fib || !rb_fiber_alive_p(e->fib)) {
864
        next_init(obj, e);
865
    }
866

  
867
    vs = rb_fiber_resume(e->fib, 1, &curr);
868
    if (e->stop_exc) {
869
        e->fib = 0;
870
        e->dst = Qnil;
871
        e->lookahead = Qundef;
872
        e->feedvalue = Qundef;
873
        return Qfalse;
874
    }
875
    e->lookahead = vs;
876
    return Qtrue;
877
}
878

  
827 879
static VALUE
828 880
enumerator_peek_values(VALUE obj)
829 881
{
......
2352 2404
    rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0);
2353 2405
    rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0);
2354 2406
    rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
2407
    rb_define_method(rb_cEnumerator, "next?", enumerator_has_next, 0);
2355 2408
    rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0);
2356 2409
    rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);
2357 2410
    rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
test/ruby/test_enumerator.rb
38 38
    assert_raise(StopIteration){e.next}
39 39
  end
40 40

  
41
  def test_next?
42
    e = 3.times
43
    3.times{|i|
44
      assert_equal true, e.next?
45
      e.next
46
    }
47
    assert_equal false, e.next?
48
  end
49

  
41 50
  def test_loop
42 51
    e = 3.times
43 52
    i = 0