~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to enumerator.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  enumerator.c - provides Enumerator class
4
4
 
5
 
  $Author: shyouhei $
 
5
  $Author: matz $
6
6
 
7
7
  Copyright (C) 2001-2003 Akinori MUSHA
8
8
 
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 $
12
12
 
13
13
************************************************/
14
14
 
15
 
#include "ruby.h"
 
15
#include "ruby/ruby.h"
 
16
#include "debug.h"
16
17
 
17
18
/*
18
19
 * Document-class: Enumerable::Enumerator
21
22
 * object.
22
23
 */
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;
 
26
 
 
27
VALUE rb_eStopIteration;
25
28
 
26
29
static VALUE
27
30
proc_call(VALUE proc, VALUE args)
32
35
    return rb_proc_call(proc, args);
33
36
}
34
37
 
 
38
struct enumerator;
 
39
typedef VALUE enum_iter(VALUE, struct enumerator *);
 
40
 
35
41
struct enumerator {
36
42
    VALUE method;
37
43
    VALUE proc;
38
44
    VALUE args;
39
 
    VALUE (*iter)(VALUE, struct enumerator *);
 
45
    enum_iter *iter;
 
46
    VALUE fib;
 
47
    VALUE dst;
 
48
    VALUE no_next;
40
49
};
41
50
 
42
51
static void
46
55
    rb_gc_mark(ptr->method);
47
56
    rb_gc_mark(ptr->proc);
48
57
    rb_gc_mark(ptr->args);
 
58
    rb_gc_mark(ptr->fib);
 
59
    rb_gc_mark(ptr->dst);
49
60
}
50
61
 
51
62
static struct enumerator *
144
155
    args[0] = rb_ary_new2(size);
145
156
    args[1] = (VALUE)size;
146
157
 
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);
148
159
 
149
160
    ary = args[0];
150
161
    if (RARRAY_LEN(ary) > 0) rb_yield(ary);
200
211
    args[0] = rb_ary_new2(size);
201
212
    args[1] = (VALUE)size;
202
213
 
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);
204
215
 
205
216
    return Qnil;
206
217
}
224
235
        ptr->iter = enumerator_iter_i;
225
236
    }
226
237
    else {
227
 
        ptr->iter = (VALUE (*)(VALUE, struct enumerator *))rb_yield;
 
238
        ptr->iter = (enum_iter *)rb_yield;
228
239
    }
229
240
    if (argc) ptr->args = rb_ary_new4(argc, argv);
 
241
    ptr->fib = 0;
 
242
    ptr->dst = Qnil;
 
243
    ptr->no_next = Qfalse;
230
244
 
231
245
    return enum_obj;
232
246
}
272
286
    ptr1->proc = ptr0->proc;
273
287
    ptr1->iter = ptr0->iter;
274
288
    ptr1->args = ptr0->args;
 
289
    ptr1->fib  = ptr0->fib;
275
290
 
276
291
    return obj;
277
292
}
303
318
        argc = RARRAY_LEN(e->args);
304
319
        argv = RARRAY_PTR(e->args);
305
320
    }
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);
307
322
}
308
323
 
309
324
static VALUE
330
345
    int argc = 0;
331
346
    VALUE *argv = 0;
332
347
 
333
 
/*    RETURN_ENUMERATOR(obj, 0, 0); ?? */
 
348
    RETURN_ENUMERATOR(obj, 0, 0);
334
349
    if (e->args) {
335
350
        argc = RARRAY_LEN(e->args);
336
351
        argv = RARRAY_PTR(e->args);
337
352
    }
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);
340
355
}
341
356
 
347
362
 */
348
363
 
349
364
static VALUE
350
 
enumerator_to_splat(VALUE range)
351
 
{
352
 
    return rb_convert_type(range, T_ARRAY, "Array", "to_a");
 
365
enumerator_to_splat(VALUE obj)
 
366
{
 
367
    return rb_convert_type(obj, T_ARRAY, "Array", "to_a");
 
368
}
 
369
 
 
370
static VALUE
 
371
next_ii(VALUE i, VALUE obj)
 
372
{
 
373
    struct enumerator *e = enumerator_ptr(obj);
 
374
    rb_fiber_yield(1, &i);
 
375
    return Qnil;
 
376
}
 
377
 
 
378
static VALUE
 
379
next_i(VALUE curr, VALUE obj)
 
380
{
 
381
    struct enumerator *e = enumerator_ptr(obj);
 
382
    VALUE nil = Qnil;
 
383
 
 
384
    rb_block_call(obj, rb_intern("each"), 0, 0, next_ii, obj);
 
385
    e->no_next = Qtrue;
 
386
    return rb_fiber_yield(1, &nil);
 
387
}
 
388
 
 
389
static void
 
390
next_init(VALUE obj, struct enumerator *e)
 
391
{
 
392
    VALUE curr = rb_fiber_current();
 
393
    e->dst = curr;
 
394
    e->fib = rb_fiber_new(next_i, obj);
 
395
}
 
396
 
 
397
/*
 
398
 * call-seq:
 
399
 *   e.next   => object
 
400
 *
 
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.
 
404
 *
 
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.
 
408
 *
 
409
 */
 
410
 
 
411
static VALUE
 
412
enumerator_next(VALUE obj)
 
413
{
 
414
    struct enumerator *e = enumerator_ptr(obj);
 
415
    VALUE curr, v;
 
416
    curr = rb_fiber_current();
 
417
 
 
418
    if (!e->fib) {
 
419
        next_init(obj, e);
 
420
    }
 
421
 
 
422
    v = rb_fiber_resume(e->fib, 1, &curr);
 
423
    if (e->no_next) {
 
424
        e->fib = 0;
 
425
        e->dst = Qnil;
 
426
        e->no_next = Qfalse;
 
427
        rb_raise(rb_eStopIteration, "iteration reached at end");
 
428
    }
 
429
    return v;
 
430
}
 
431
 
 
432
/*
 
433
 * call-seq:
 
434
 *   e.next?   => e
 
435
 *
 
436
 * Rewinds the enumeration sequence by the next method.
 
437
 */
 
438
 
 
439
static VALUE
 
440
enumerator_rewind(VALUE obj)
 
441
{
 
442
    struct enumerator *e = enumerator_ptr(obj);
 
443
 
 
444
    e->fib = 0;
 
445
    e->dst = Qnil;
 
446
    e->no_next = Qfalse;
 
447
    return obj;
353
448
}
354
449
 
355
450
void
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);
 
470
 
 
471
    rb_eStopIteration   = rb_define_class("StopIteration", rb_eIndexError);
373
472
 
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"));
378
478
 
379
479
    rb_provide("enumerator.so");        /* for backward compatibility */
380
480
}