3
3
enumerator.c - provides Enumerator class
7
7
Copyright (C) 2001-2003 Akinori MUSHA
9
9
$Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
10
10
$RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
11
$Id: enumerator.c 11708 2007-02-12 23:01:19Z shyouhei $
11
$Id: enumerator.c 13279 2007-08-26 16:33:45Z matz $
13
13
************************************************/
15
#include "ruby/ruby.h"
18
19
* Document-class: Enumerable::Enumerator
23
24
static VALUE rb_cEnumerator;
24
static VALUE sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
25
static VALUE sym_each, sym_each_with_index, sym_each_slice, sym_each_cons, sym_call;
27
VALUE rb_eStopIteration;
27
30
proc_call(VALUE proc, VALUE args)
32
35
return rb_proc_call(proc, args);
39
typedef VALUE enum_iter(VALUE, struct enumerator *);
35
41
struct enumerator {
39
VALUE (*iter)(VALUE, struct enumerator *);
144
155
args[0] = rb_ary_new2(size);
145
156
args[1] = (VALUE)size;
147
rb_block_call(obj, rb_intern("each"), 0, 0, each_slice_i, (VALUE)args);
158
rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_slice_i, (VALUE)args);
150
161
if (RARRAY_LEN(ary) > 0) rb_yield(ary);
200
211
args[0] = rb_ary_new2(size);
201
212
args[1] = (VALUE)size;
203
rb_block_call(obj, rb_intern("each"), 0, 0, each_cons_i, (VALUE)args);
214
rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_cons_i, (VALUE)args);
224
235
ptr->iter = enumerator_iter_i;
227
ptr->iter = (VALUE (*)(VALUE, struct enumerator *))rb_yield;
238
ptr->iter = (enum_iter *)rb_yield;
229
240
if (argc) ptr->args = rb_ary_new4(argc, argv);
243
ptr->no_next = Qfalse;
303
318
argc = RARRAY_LEN(e->args);
304
319
argv = RARRAY_PTR(e->args);
306
return rb_block_call(e->method, rb_intern("call"), argc, argv, e->iter, (VALUE)e);
321
return rb_block_call(e->method, SYM2ID(sym_call), argc, argv, e->iter, (VALUE)e);
333
/* RETURN_ENUMERATOR(obj, 0, 0); ?? */
348
RETURN_ENUMERATOR(obj, 0, 0);
335
350
argc = RARRAY_LEN(e->args);
336
351
argv = RARRAY_PTR(e->args);
338
return rb_block_call(e->method, rb_intern("call"), argc, argv,
353
return rb_block_call(e->method, SYM2ID(sym_call), argc, argv,
339
354
enumerator_with_index_i, (VALUE)&memo);
350
enumerator_to_splat(VALUE range)
352
return rb_convert_type(range, T_ARRAY, "Array", "to_a");
365
enumerator_to_splat(VALUE obj)
367
return rb_convert_type(obj, T_ARRAY, "Array", "to_a");
371
next_ii(VALUE i, VALUE obj)
373
struct enumerator *e = enumerator_ptr(obj);
374
rb_fiber_yield(1, &i);
379
next_i(VALUE curr, VALUE obj)
381
struct enumerator *e = enumerator_ptr(obj);
384
rb_block_call(obj, rb_intern("each"), 0, 0, next_ii, obj);
386
return rb_fiber_yield(1, &nil);
390
next_init(VALUE obj, struct enumerator *e)
392
VALUE curr = rb_fiber_current();
394
e->fib = rb_fiber_new(next_i, obj);
401
* Returns the next object in the enumerator, and move the internal
402
* position forward. When the position reached at the end, internal
403
* position is rewinded then StopIteration is raised.
405
* Note that enumeration sequence by next method does not affect other
406
* non-external enumeration methods, unless underlying iteration
407
* methods itself has side-effect, e.g. IO#each_line.
412
enumerator_next(VALUE obj)
414
struct enumerator *e = enumerator_ptr(obj);
416
curr = rb_fiber_current();
422
v = rb_fiber_resume(e->fib, 1, &curr);
427
rb_raise(rb_eStopIteration, "iteration reached at end");
436
* Rewinds the enumeration sequence by the next method.
440
enumerator_rewind(VALUE obj)
442
struct enumerator *e = enumerator_ptr(obj);
370
465
rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
371
466
rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0);
372
467
rb_define_method(rb_cEnumerator, "to_splat", enumerator_to_splat, 0);
468
rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
469
rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
471
rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
374
473
sym_each = ID2SYM(rb_intern("each"));
375
474
sym_each_with_index = ID2SYM(rb_intern("each_with_index"));
376
475
sym_each_slice = ID2SYM(rb_intern("each_slice"));
377
476
sym_each_cons = ID2SYM(rb_intern("each_cons"));
477
sym_call = ID2SYM(rb_intern("call"));
379
479
rb_provide("enumerator.so"); /* for backward compatibility */