Ruby
1.9.3p551(2014-11-13revision48407)
Main Page
Modules
Data Structures
Files
File List
Globals
enumerator.c
Go to the documentation of this file.
1
/************************************************
2
3
enumerator.c - provides Enumerator class
4
5
$Author: usa $
6
7
Copyright (C) 2001-2003 Akinori MUSHA
8
9
$Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
10
$RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
11
$Id: enumerator.c 44749 2014-01-29 10:23:19Z usa $
12
13
************************************************/
14
15
#include "
ruby/ruby.h
"
16
#include "
node.h
"
17
#include "
internal.h
"
18
19
/*
20
* Document-class: Enumerator
21
*
22
* A class which allows both internal and external iteration.
23
*
24
* An Enumerator can be created by the following methods.
25
* - Kernel#to_enum
26
* - Kernel#enum_for
27
* - Enumerator.new
28
*
29
* Most methods have two forms: a block form where the contents
30
* are evaluated for each item in the enumeration, and a non-block form
31
* which returns a new Enumerator wrapping the iteration.
32
*
33
* enumerator = %w(one two three).each
34
* puts enumerator.class # => Enumerator
35
* enumerator.each_with_object("foo") do |item,obj|
36
* puts "#{obj}: #{item}"
37
* end
38
* # foo: one
39
* # foo: two
40
* # foo: three
41
* enum_with_obj = enumerator.each_with_object("foo")
42
* puts enum_with_obj.class # => Enumerator
43
* enum_with_obj.each do |item,obj|
44
* puts "#{obj: #{item}"
45
* end
46
* # foo: one
47
* # foo: two
48
* # foo: three
49
*
50
* This allows you to chain Enumerators together. For example, you
51
* can map a list's elements to strings containing the index
52
* and the element as a string via:
53
*
54
* puts %w[foo bar baz].map.with_index {|w,i| "#{i}:#{w}" }
55
* # => ["0:foo", "1:bar", "2:baz"]
56
*
57
* An Enumerator can also be used as an external iterator.
58
* For example, Enumerator#next returns the next value of the iterator
59
* or raises StopIteration if the Enumerator is at the end.
60
*
61
* e = [1,2,3].each # returns an enumerator object.
62
* puts e.next # => 1
63
* puts e.next # => 2
64
* puts e.next # => 3
65
* puts e.next # raises StopIteration
66
*
67
* You can use this to implement an internal iterator as follows:
68
*
69
* def ext_each(e)
70
* while true
71
* begin
72
* vs = e.next_values
73
* rescue StopIteration
74
* return $!.result
75
* end
76
* y = yield(*vs)
77
* e.feed y
78
* end
79
* end
80
*
81
* o = Object.new
82
*
83
* def o.each
84
* puts yield
85
* puts yield(1)
86
* puts yield(1, 2)
87
* 3
88
* end
89
*
90
* # use o.each as an internal iterator directly.
91
* puts o.each {|*x| puts x; [:b, *x] }
92
* # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
93
*
94
* # convert o.each to an external iterator for
95
* # implementing an internal iterator.
96
* puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
97
* # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
98
*
99
*/
100
VALUE
rb_cEnumerator
;
101
static
ID
id_rewind
,
id_each
;
102
static
VALUE
sym_each
;
103
104
VALUE
rb_eStopIteration
;
105
106
struct
enumerator
{
107
VALUE
obj
;
108
ID
meth
;
109
VALUE
args
;
110
VALUE
fib
;
111
VALUE
dst
;
112
VALUE
lookahead
;
113
VALUE
feedvalue
;
114
VALUE
stop_exc
;
115
};
116
117
static
VALUE
rb_cGenerator
,
rb_cYielder
;
118
119
struct
generator
{
120
VALUE
proc
;
121
};
122
123
struct
yielder
{
124
VALUE
proc
;
125
};
126
127
static
VALUE
generator_allocate
(
VALUE
klass);
128
static
VALUE
generator_init
(
VALUE
obj,
VALUE
proc);
129
130
/*
131
* Enumerator
132
*/
133
static
void
134
enumerator_mark
(
void
*
p
)
135
{
136
struct
enumerator
*ptr =
p
;
137
rb_gc_mark
(ptr->
obj
);
138
rb_gc_mark
(ptr->
args
);
139
rb_gc_mark
(ptr->
fib
);
140
rb_gc_mark
(ptr->
dst
);
141
rb_gc_mark
(ptr->
lookahead
);
142
rb_gc_mark
(ptr->
feedvalue
);
143
rb_gc_mark
(ptr->
stop_exc
);
144
}
145
146
#define enumerator_free RUBY_TYPED_DEFAULT_FREE
147
148
static
size_t
149
enumerator_memsize
(
const
void
*
p
)
150
{
151
return
p ?
sizeof
(
struct
enumerator
) : 0;
152
}
153
154
static
const
rb_data_type_t
enumerator_data_type
= {
155
"enumerator"
,
156
{
157
enumerator_mark
,
158
enumerator_free
,
159
enumerator_memsize
,
160
},
161
};
162
163
static
struct
enumerator
*
164
enumerator_ptr
(
VALUE
obj
)
165
{
166
struct
enumerator
*ptr;
167
168
TypedData_Get_Struct
(obj,
struct
enumerator
, &
enumerator_data_type
, ptr);
169
if
(!ptr || ptr->
obj
==
Qundef
) {
170
rb_raise
(
rb_eArgError
,
"uninitialized enumerator"
);
171
}
172
return
ptr;
173
}
174
175
/*
176
* call-seq:
177
* obj.to_enum(method = :each, *args)
178
* obj.enum_for(method = :each, *args)
179
*
180
* Creates a new Enumerator which will enumerate by on calling +method+ on
181
* +obj+.
182
*
183
* +method+:: the method to call on +obj+ to generate the enumeration
184
* +args+:: arguments that will be passed in +method+ <i>in addition</i>
185
* to the item itself. Note that the number of args
186
* must not exceed the number expected by +method+
187
*
188
* === Example
189
*
190
* str = "xyz"
191
*
192
* enum = str.enum_for(:each_byte)
193
* enum.each { |b| puts b }
194
* # => 120
195
* # => 121
196
* # => 122
197
*
198
* # protect an array from being modified by some_method
199
* a = [1, 2, 3]
200
* some_method(a.to_enum)
201
*
202
*/
203
static
VALUE
204
obj_to_enum
(
int
argc
,
VALUE
*
argv
,
VALUE
obj
)
205
{
206
VALUE
meth
=
sym_each
;
207
208
if
(argc > 0) {
209
--
argc
;
210
meth = *argv++;
211
}
212
return
rb_enumeratorize
(obj, meth, argc, argv);
213
}
214
215
static
VALUE
216
enumerator_allocate
(
VALUE
klass)
217
{
218
struct
enumerator
*ptr;
219
VALUE
enum_obj;
220
221
enum_obj =
TypedData_Make_Struct
(klass,
struct
enumerator
, &
enumerator_data_type
, ptr);
222
ptr->
obj
=
Qundef
;
223
224
return
enum_obj;
225
}
226
227
static
VALUE
228
enumerator_init
(
VALUE
enum_obj,
VALUE
obj
,
VALUE
meth
,
int
argc
,
VALUE
*
argv
)
229
{
230
struct
enumerator
*ptr;
231
232
TypedData_Get_Struct
(enum_obj,
struct
enumerator
, &
enumerator_data_type
, ptr);
233
234
if
(!ptr) {
235
rb_raise
(
rb_eArgError
,
"unallocated enumerator"
);
236
}
237
238
ptr->
obj
=
obj
;
239
ptr->
meth
=
rb_to_id
(meth);
240
if
(argc) ptr->
args
=
rb_ary_new4
(argc, argv);
241
ptr->
fib
= 0;
242
ptr->
dst
=
Qnil
;
243
ptr->
lookahead
=
Qundef
;
244
ptr->
feedvalue
=
Qundef
;
245
ptr->
stop_exc
=
Qfalse
;
246
247
return
enum_obj;
248
}
249
250
/*
251
* call-seq:
252
* Enumerator.new { |yielder| ... }
253
* Enumerator.new(obj, method = :each, *args)
254
*
255
* Creates a new Enumerator object, which can be used as an
256
* Enumerable.
257
*
258
* In the first form, iteration is defined by the given block, in
259
* which a "yielder" object, given as block parameter, can be used to
260
* yield a value by calling the +yield+ method (aliased as +<<+):
261
*
262
* fib = Enumerator.new do |y|
263
* a = b = 1
264
* loop do
265
* y << a
266
* a, b = b, a + b
267
* end
268
* end
269
*
270
* p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
271
*
272
* In the second, deprecated, form, a generated Enumerator iterates over the
273
* given object using the given method with the given arguments passed.
274
*
275
* Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum
276
* instead.
277
*
278
* e = Enumerator.new(ObjectSpace, :each_object)
279
* #-> ObjectSpace.enum_for(:each_object)
280
*
281
* e.select { |obj| obj.is_a?(Class) } #=> array of all classes
282
*
283
*/
284
static
VALUE
285
enumerator_initialize
(
int
argc
,
VALUE
*
argv
,
VALUE
obj
)
286
{
287
VALUE
recv,
meth
=
sym_each
;
288
289
if
(argc == 0) {
290
if
(!
rb_block_given_p
())
291
rb_raise
(
rb_eArgError
,
"wrong number of argument (0 for 1+)"
);
292
293
recv =
generator_init
(
generator_allocate
(
rb_cGenerator
),
rb_block_proc
());
294
}
295
else
{
296
recv = *argv++;
297
if
(--argc) {
298
meth = *argv++;
299
--
argc
;
300
}
301
}
302
303
return
enumerator_init
(obj, recv, meth, argc, argv);
304
}
305
306
/* :nodoc: */
307
static
VALUE
308
enumerator_init_copy
(
VALUE
obj
,
VALUE
orig)
309
{
310
struct
enumerator
*ptr0, *ptr1;
311
312
ptr0 =
enumerator_ptr
(orig);
313
if
(ptr0->
fib
) {
314
/* Fibers cannot be copied */
315
rb_raise
(
rb_eTypeError
,
"can't copy execution context"
);
316
}
317
318
TypedData_Get_Struct
(obj,
struct
enumerator
, &
enumerator_data_type
, ptr1);
319
320
if
(!ptr1) {
321
rb_raise
(
rb_eArgError
,
"unallocated enumerator"
);
322
}
323
324
ptr1->
obj
= ptr0->
obj
;
325
ptr1->
meth
= ptr0->
meth
;
326
ptr1->
args
= ptr0->
args
;
327
ptr1->
fib
= 0;
328
ptr1->
lookahead
=
Qundef
;
329
ptr1->
feedvalue
=
Qundef
;
330
331
return
obj
;
332
}
333
334
VALUE
335
rb_enumeratorize
(
VALUE
obj
,
VALUE
meth
,
int
argc
,
VALUE
*
argv
)
336
{
337
return
enumerator_init
(
enumerator_allocate
(
rb_cEnumerator
), obj, meth, argc, argv);
338
}
339
340
static
VALUE
341
enumerator_block_call
(
VALUE
obj
,
rb_block_call_func
*
func
,
VALUE
arg
)
342
{
343
int
argc
= 0;
344
VALUE
*
argv
= 0;
345
const
struct
enumerator
*e =
enumerator_ptr
(obj);
346
ID
meth
= e->
meth
;
347
348
if
(e->
args
) {
349
argc =
RARRAY_LENINT
(e->
args
);
350
argv =
RARRAY_PTR
(e->
args
);
351
}
352
return
rb_block_call
(e->
obj
, meth, argc, argv, func, arg);
353
}
354
355
/*
356
* call-seq:
357
* enum.each {...}
358
*
359
* Iterates over the block according to how this Enumerable was constructed.
360
* If no block is given, returns self.
361
*
362
*/
363
static
VALUE
364
enumerator_each
(
VALUE
obj
)
365
{
366
if
(!
rb_block_given_p
())
return
obj
;
367
return
enumerator_block_call
(obj, 0, obj);
368
}
369
370
static
VALUE
371
enumerator_with_index_i
(
VALUE
val,
VALUE
m,
int
argc
,
VALUE
*
argv
)
372
{
373
NODE
*memo = (
NODE
*)m;
374
VALUE
idx = memo->
u1
.
value
;
375
memo->
u1
.
value
=
rb_int_succ
(idx);
376
377
if
(argc <= 1)
378
return
rb_yield_values
(2, val, idx);
379
380
return
rb_yield_values
(2,
rb_ary_new4
(argc, argv), idx);
381
}
382
383
/*
384
* call-seq:
385
* e.with_index(offset = 0) {|(*args), idx| ... }
386
* e.with_index(offset = 0)
387
*
388
* Iterates the given block for each element with an index, which
389
* starts from +offset+. If no block is given, returns a new Enumerator
390
* that includes the index, starting from +offset+
391
*
392
* +offset+:: the starting index to use
393
*
394
*/
395
static
VALUE
396
enumerator_with_index
(
int
argc
,
VALUE
*
argv
,
VALUE
obj
)
397
{
398
VALUE
memo;
399
400
rb_scan_args
(argc, argv,
"01"
, &memo);
401
RETURN_ENUMERATOR
(obj, argc, argv);
402
if
(
NIL_P
(memo))
403
memo =
INT2FIX
(0);
404
else
405
memo =
rb_to_int
(memo);
406
return
enumerator_block_call
(obj,
enumerator_with_index_i
, (
VALUE
)
NEW_MEMO
(memo, 0, 0));
407
}
408
409
/*
410
* call-seq:
411
* e.each_with_index {|(*args), idx| ... }
412
* e.each_with_index
413
*
414
* Same as Enumerator#with_index(0), i.e. there is no starting offset.
415
*
416
* If no block is given, a new Enumerator is returned that includes the index.
417
*
418
*/
419
static
VALUE
420
enumerator_each_with_index
(
VALUE
obj
)
421
{
422
return
enumerator_with_index
(0,
NULL
, obj);
423
}
424
425
static
VALUE
426
enumerator_with_object_i
(
VALUE
val,
VALUE
memo,
int
argc
,
VALUE
*
argv
)
427
{
428
if
(argc <= 1)
429
return
rb_yield_values
(2, val, memo);
430
431
return
rb_yield_values
(2,
rb_ary_new4
(argc, argv), memo);
432
}
433
434
/*
435
* call-seq:
436
* e.with_object(obj) {|(*args), obj| ... }
437
* e.with_object(obj)
438
*
439
* Iterates the given block for each element with an arbitrary object, +obj+,
440
* and returns +obj+
441
*
442
* If no block is given, returns a new Enumerator.
443
*
444
* === Example
445
*
446
* to_three = Enumerator.new do |y|
447
* 3.times do |x|
448
* y << x
449
* end
450
* end
451
*
452
* to_three_with_string = to_three.with_object("foo")
453
* to_three_with_string.each do |x,string|
454
* puts "#{string}: #{x}"
455
* end
456
*
457
* # => foo:0
458
* # => foo:1
459
* # => foo:2
460
*/
461
static
VALUE
462
enumerator_with_object
(
VALUE
obj
,
VALUE
memo)
463
{
464
RETURN_ENUMERATOR
(obj, 1, &memo);
465
enumerator_block_call
(obj,
enumerator_with_object_i
, memo);
466
467
return
memo;
468
}
469
470
static
VALUE
471
next_ii
(
VALUE
i
,
VALUE
obj
,
int
argc
,
VALUE
*
argv
)
472
{
473
struct
enumerator
*e =
enumerator_ptr
(obj);
474
VALUE
feedvalue
=
Qnil
;
475
VALUE
args
=
rb_ary_new4
(argc, argv);
476
rb_fiber_yield
(1, &args);
477
if
(e->
feedvalue
!=
Qundef
) {
478
feedvalue = e->
feedvalue
;
479
e->
feedvalue
=
Qundef
;
480
}
481
return
feedvalue
;
482
}
483
484
static
VALUE
485
next_i
(
VALUE
curr,
VALUE
obj
)
486
{
487
struct
enumerator
*e =
enumerator_ptr
(obj);
488
VALUE
nil =
Qnil
;
489
VALUE
result
;
490
491
result =
rb_block_call
(obj,
id_each
, 0, 0,
next_ii
, obj);
492
e->
stop_exc
=
rb_exc_new2
(
rb_eStopIteration
,
"iteration reached an end"
);
493
rb_ivar_set
(e->
stop_exc
,
rb_intern
(
"result"
), result);
494
return
rb_fiber_yield
(1, &nil);
495
}
496
497
static
void
498
next_init
(
VALUE
obj
,
struct
enumerator
*e)
499
{
500
VALUE
curr =
rb_fiber_current
();
501
e->
dst
= curr;
502
e->
fib
=
rb_fiber_new
(
next_i
, obj);
503
e->
lookahead
=
Qundef
;
504
}
505
506
static
VALUE
507
get_next_values
(
VALUE
obj
,
struct
enumerator
*e)
508
{
509
VALUE
curr, vs;
510
511
if
(e->
stop_exc
)
512
rb_exc_raise
(e->
stop_exc
);
513
514
curr =
rb_fiber_current
();
515
516
if
(!e->
fib
|| !
rb_fiber_alive_p
(e->
fib
)) {
517
next_init
(obj, e);
518
}
519
520
vs =
rb_fiber_resume
(e->
fib
, 1, &curr);
521
if
(e->
stop_exc
) {
522
e->
fib
= 0;
523
e->
dst
=
Qnil
;
524
e->
lookahead
=
Qundef
;
525
e->
feedvalue
=
Qundef
;
526
rb_exc_raise
(e->
stop_exc
);
527
}
528
return
vs;
529
}
530
531
/*
532
* call-seq:
533
* e.next_values -> array
534
*
535
* Returns the next object as an array in the enumerator, and move the
536
* internal position forward. When the position reached at the end,
537
* StopIteration is raised.
538
*
539
* This method can be used to distinguish <code>yield</code> and <code>yield
540
* nil</code>.
541
*
542
* === Example
543
*
544
* o = Object.new
545
* def o.each
546
* yield
547
* yield 1
548
* yield 1, 2
549
* yield nil
550
* yield [1, 2]
551
* end
552
* e = o.to_enum
553
* p e.next_values
554
* p e.next_values
555
* p e.next_values
556
* p e.next_values
557
* p e.next_values
558
* e = o.to_enum
559
* p e.next
560
* p e.next
561
* p e.next
562
* p e.next
563
* p e.next
564
*
565
* ## yield args next_values next
566
* # yield [] nil
567
* # yield 1 [1] 1
568
* # yield 1, 2 [1, 2] [1, 2]
569
* # yield nil [nil] nil
570
* # yield [1, 2] [[1, 2]] [1, 2]
571
*
572
* Note that +next_values+ does not affect other non-external enumeration
573
* methods unless underlying iteration method itself has side-effect, e.g.
574
* IO#each_line.
575
*
576
*/
577
578
static
VALUE
579
enumerator_next_values
(
VALUE
obj
)
580
{
581
struct
enumerator
*e =
enumerator_ptr
(obj);
582
VALUE
vs;
583
584
if
(e->
lookahead
!=
Qundef
) {
585
vs = e->
lookahead
;
586
e->
lookahead
=
Qundef
;
587
return
vs;
588
}
589
590
return
get_next_values
(obj, e);
591
}
592
593
static
VALUE
594
ary2sv
(
VALUE
args
,
int
dup)
595
{
596
if
(
TYPE
(args) !=
T_ARRAY
)
597
return
args
;
598
599
switch
(
RARRAY_LEN
(args)) {
600
case
0:
601
return
Qnil
;
602
603
case
1:
604
return
RARRAY_PTR
(args)[0];
605
606
default
:
607
if
(dup)
608
return
rb_ary_dup
(args);
609
return
args
;
610
}
611
}
612
613
/*
614
* call-seq:
615
* e.next -> object
616
*
617
* Returns the next object in the enumerator, and move the internal position
618
* forward. When the position reached at the end, StopIteration is raised.
619
*
620
* === Example
621
*
622
* a = [1,2,3]
623
* e = a.to_enum
624
* p e.next #=> 1
625
* p e.next #=> 2
626
* p e.next #=> 3
627
* p e.next #raises StopIteration
628
*
629
* Note that enumeration sequence by +next+ does not affect other non-external
630
* enumeration methods, unless the underlying iteration methods itself has
631
* side-effect, e.g. IO#each_line.
632
*
633
*/
634
635
static
VALUE
636
enumerator_next
(
VALUE
obj
)
637
{
638
VALUE
vs =
enumerator_next_values
(obj);
639
return
ary2sv
(vs, 0);
640
}
641
642
static
VALUE
643
enumerator_peek_values
(
VALUE
obj
)
644
{
645
struct
enumerator
*e =
enumerator_ptr
(obj);
646
647
if
(e->
lookahead
==
Qundef
) {
648
e->
lookahead
=
get_next_values
(obj, e);
649
}
650
return
e->
lookahead
;
651
}
652
653
/*
654
* call-seq:
655
* e.peek_values -> array
656
*
657
* Returns the next object as an array, similar to Enumerator#next_values, but
658
* doesn't move the internal position forward. If the position is already at
659
* the end, StopIteration is raised.
660
*
661
* === Example
662
*
663
* o = Object.new
664
* def o.each
665
* yield
666
* yield 1
667
* yield 1, 2
668
* end
669
* e = o.to_enum
670
* p e.peek_values #=> []
671
* e.next
672
* p e.peek_values #=> [1]
673
* p e.peek_values #=> [1]
674
* e.next
675
* p e.peek_values #=> [1, 2]
676
* e.next
677
* p e.peek_values # raises StopIteration
678
*
679
*/
680
681
static
VALUE
682
enumerator_peek_values_m
(
VALUE
obj
)
683
{
684
return
rb_ary_dup
(
enumerator_peek_values
(obj));
685
}
686
687
/*
688
* call-seq:
689
* e.peek -> object
690
*
691
* Returns the next object in the enumerator, but doesn't move the internal
692
* position forward. If the position is already at the end, StopIteration
693
* is raised.
694
*
695
* === Example
696
*
697
* a = [1,2,3]
698
* e = a.to_enum
699
* p e.next #=> 1
700
* p e.peek #=> 2
701
* p e.peek #=> 2
702
* p e.peek #=> 2
703
* p e.next #=> 2
704
* p e.next #=> 3
705
* p e.next #raises StopIteration
706
*
707
*/
708
709
static
VALUE
710
enumerator_peek
(
VALUE
obj
)
711
{
712
VALUE
vs =
enumerator_peek_values
(obj);
713
return
ary2sv
(vs, 1);
714
}
715
716
/*
717
* call-seq:
718
* e.feed obj -> nil
719
*
720
* Sets the value to be returned by the next yield inside +e+.
721
*
722
* If the value is not set, the yield returns nil.
723
*
724
* This value is cleared after being yielded.
725
*
726
* o = Object.new
727
* def o.each
728
* x = yield # (2) blocks
729
* p x # (5) => "foo"
730
* x = yield # (6) blocks
731
* p x # (8) => nil
732
* x = yield # (9) blocks
733
* p x # not reached w/o another e.next
734
* end
735
*
736
* e = o.to_enum
737
* e.next # (1)
738
* e.feed "foo" # (3)
739
* e.next # (4)
740
* e.next # (7)
741
* # (10)
742
*/
743
744
static
VALUE
745
enumerator_feed
(
VALUE
obj
,
VALUE
v
)
746
{
747
struct
enumerator
*e =
enumerator_ptr
(obj);
748
749
if
(e->
feedvalue
!=
Qundef
) {
750
rb_raise
(
rb_eTypeError
,
"feed value already set"
);
751
}
752
e->
feedvalue
=
v
;
753
754
return
Qnil
;
755
}
756
757
/*
758
* call-seq:
759
* e.rewind -> e
760
*
761
* Rewinds the enumeration sequence to the beginning.
762
*
763
* If the enclosed object responds to a "rewind" method, it is called.
764
*/
765
766
static
VALUE
767
enumerator_rewind
(
VALUE
obj
)
768
{
769
struct
enumerator
*e =
enumerator_ptr
(obj);
770
771
rb_check_funcall
(e->
obj
,
id_rewind
, 0, 0);
772
773
e->
fib
= 0;
774
e->
dst
=
Qnil
;
775
e->
lookahead
=
Qundef
;
776
e->
feedvalue
=
Qundef
;
777
e->
stop_exc
=
Qfalse
;
778
return
obj
;
779
}
780
781
static
VALUE
782
inspect_enumerator
(
VALUE
obj
,
VALUE
dummy,
int
recur
)
783
{
784
struct
enumerator
*e;
785
const
char
*cname;
786
VALUE
eobj, str;
787
int
tainted, untrusted;
788
789
TypedData_Get_Struct
(obj,
struct
enumerator
, &
enumerator_data_type
, e);
790
791
cname =
rb_obj_classname
(obj);
792
793
if
(!e || e->
obj
==
Qundef
) {
794
return
rb_sprintf
(
"#<%s: uninitialized>"
, cname);
795
}
796
797
if
(recur) {
798
str =
rb_sprintf
(
"#<%s: ...>"
, cname);
799
OBJ_TAINT
(str);
800
return
str;
801
}
802
803
eobj = e->
obj
;
804
805
tainted =
OBJ_TAINTED
(eobj);
806
untrusted =
OBJ_UNTRUSTED
(eobj);
807
808
/* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
809
str =
rb_sprintf
(
"#<%s: "
, cname);
810
rb_str_concat
(str,
rb_inspect
(eobj));
811
rb_str_buf_cat2
(str,
":"
);
812
rb_str_buf_cat2
(str,
rb_id2name
(e->
meth
));
813
814
if
(e->
args
) {
815
long
argc
=
RARRAY_LEN
(e->
args
);
816
VALUE
*
argv
=
RARRAY_PTR
(e->
args
);
817
818
rb_str_buf_cat2
(str,
"("
);
819
820
while
(argc--) {
821
VALUE
arg
= *argv++;
822
823
rb_str_concat
(str,
rb_inspect
(arg));
824
rb_str_buf_cat2
(str, argc > 0 ?
", "
:
")"
);
825
826
if
(
OBJ_TAINTED
(arg)) tainted =
TRUE
;
827
if
(
OBJ_UNTRUSTED
(arg)) untrusted =
TRUE
;
828
}
829
}
830
831
rb_str_buf_cat2
(str,
">"
);
832
833
if
(tainted)
OBJ_TAINT
(str);
834
if
(untrusted)
OBJ_UNTRUST
(str);
835
return
str;
836
}
837
838
/*
839
* call-seq:
840
* e.inspect -> string
841
*
842
* Creates a printable version of <i>e</i>.
843
*/
844
845
static
VALUE
846
enumerator_inspect
(
VALUE
obj
)
847
{
848
return
rb_exec_recursive
(
inspect_enumerator
, obj, 0);
849
}
850
851
/*
852
* Yielder
853
*/
854
static
void
855
yielder_mark
(
void
*p)
856
{
857
struct
yielder
*ptr =
p
;
858
rb_gc_mark
(ptr->
proc
);
859
}
860
861
#define yielder_free RUBY_TYPED_DEFAULT_FREE
862
863
static
size_t
864
yielder_memsize
(
const
void
*p)
865
{
866
return
p ?
sizeof
(
struct
yielder
) : 0;
867
}
868
869
static
const
rb_data_type_t
yielder_data_type
= {
870
"yielder"
,
871
{
872
yielder_mark
,
873
yielder_free
,
874
yielder_memsize
,
875
},
876
};
877
878
static
struct
yielder
*
879
yielder_ptr
(
VALUE
obj)
880
{
881
struct
yielder
*ptr;
882
883
TypedData_Get_Struct
(obj,
struct
yielder
, &
yielder_data_type
, ptr);
884
if
(!ptr || ptr->
proc
==
Qundef
) {
885
rb_raise
(
rb_eArgError
,
"uninitialized yielder"
);
886
}
887
return
ptr;
888
}
889
890
/* :nodoc: */
891
static
VALUE
892
yielder_allocate
(
VALUE
klass)
893
{
894
struct
yielder
*ptr;
895
VALUE
obj;
896
897
obj =
TypedData_Make_Struct
(klass,
struct
yielder
, &
yielder_data_type
, ptr);
898
ptr->
proc
=
Qundef
;
899
900
return
obj;
901
}
902
903
static
VALUE
904
yielder_init
(
VALUE
obj,
VALUE
proc
)
905
{
906
struct
yielder
*ptr;
907
908
TypedData_Get_Struct
(obj,
struct
yielder
, &
yielder_data_type
, ptr);
909
910
if
(!ptr) {
911
rb_raise
(
rb_eArgError
,
"unallocated yielder"
);
912
}
913
914
ptr->
proc
=
proc
;
915
916
return
obj;
917
}
918
919
/* :nodoc: */
920
static
VALUE
921
yielder_initialize
(
VALUE
obj)
922
{
923
rb_need_block
();
924
925
return
yielder_init
(obj,
rb_block_proc
());
926
}
927
928
/* :nodoc: */
929
static
VALUE
930
yielder_yield
(
VALUE
obj,
VALUE
args
)
931
{
932
struct
yielder
*ptr =
yielder_ptr
(obj);
933
934
return
rb_proc_call
(ptr->
proc
, args);
935
}
936
937
/* :nodoc: */
938
static
VALUE
yielder_yield_push
(
VALUE
obj,
VALUE
args
)
939
{
940
yielder_yield
(obj, args);
941
return
obj;
942
}
943
944
static
VALUE
945
yielder_yield_i
(
VALUE
obj,
VALUE
memo,
int
argc
,
VALUE
*
argv
)
946
{
947
return
rb_yield_values2
(argc, argv);
948
}
949
950
static
VALUE
951
yielder_new
(
void
)
952
{
953
return
yielder_init
(
yielder_allocate
(
rb_cYielder
),
rb_proc_new
(
yielder_yield_i
, 0));
954
}
955
956
/*
957
* Generator
958
*/
959
static
void
960
generator_mark
(
void
*p)
961
{
962
struct
generator
*ptr =
p
;
963
rb_gc_mark
(ptr->
proc
);
964
}
965
966
#define generator_free RUBY_TYPED_DEFAULT_FREE
967
968
static
size_t
969
generator_memsize
(
const
void
*p)
970
{
971
return
p ?
sizeof
(
struct
generator
) : 0;
972
}
973
974
static
const
rb_data_type_t
generator_data_type
= {
975
"generator"
,
976
{
977
generator_mark
,
978
generator_free
,
979
generator_memsize
,
980
},
981
};
982
983
static
struct
generator
*
984
generator_ptr
(
VALUE
obj)
985
{
986
struct
generator
*ptr;
987
988
TypedData_Get_Struct
(obj,
struct
generator
, &
generator_data_type
, ptr);
989
if
(!ptr || ptr->
proc
==
Qundef
) {
990
rb_raise
(
rb_eArgError
,
"uninitialized generator"
);
991
}
992
return
ptr;
993
}
994
995
/* :nodoc: */
996
static
VALUE
997
generator_allocate
(
VALUE
klass)
998
{
999
struct
generator
*ptr;
1000
VALUE
obj;
1001
1002
obj =
TypedData_Make_Struct
(klass,
struct
generator
, &
generator_data_type
, ptr);
1003
ptr->
proc
=
Qundef
;
1004
1005
return
obj;
1006
}
1007
1008
static
VALUE
1009
generator_init
(
VALUE
obj,
VALUE
proc
)
1010
{
1011
struct
generator
*ptr;
1012
1013
TypedData_Get_Struct
(obj,
struct
generator
, &
generator_data_type
, ptr);
1014
1015
if
(!ptr) {
1016
rb_raise
(
rb_eArgError
,
"unallocated generator"
);
1017
}
1018
1019
ptr->
proc
=
proc
;
1020
1021
return
obj;
1022
}
1023
1024
/* :nodoc: */
1025
static
VALUE
1026
generator_initialize
(
int
argc
,
VALUE
*
argv
,
VALUE
obj)
1027
{
1028
VALUE
proc
;
1029
1030
if
(argc == 0) {
1031
rb_need_block
();
1032
1033
proc =
rb_block_proc
();
1034
}
else
{
1035
rb_scan_args
(argc, argv,
"1"
, &proc);
1036
1037
if
(!
rb_obj_is_proc
(proc))
1038
rb_raise
(
rb_eTypeError
,
1039
"wrong argument type %s (expected Proc)"
,
1040
rb_obj_classname
(proc));
1041
1042
if
(
rb_block_given_p
()) {
1043
rb_warn
(
"given block not used"
);
1044
}
1045
}
1046
1047
return
generator_init
(obj, proc);
1048
}
1049
1050
/* :nodoc: */
1051
static
VALUE
1052
generator_init_copy
(
VALUE
obj,
VALUE
orig)
1053
{
1054
struct
generator
*ptr0, *ptr1;
1055
1056
ptr0 =
generator_ptr
(orig);
1057
1058
TypedData_Get_Struct
(obj,
struct
generator
, &
generator_data_type
, ptr1);
1059
1060
if
(!ptr1) {
1061
rb_raise
(
rb_eArgError
,
"unallocated generator"
);
1062
}
1063
1064
ptr1->
proc
= ptr0->
proc
;
1065
1066
return
obj;
1067
}
1068
1069
/* :nodoc: */
1070
static
VALUE
1071
generator_each
(
VALUE
obj)
1072
{
1073
struct
generator
*ptr =
generator_ptr
(obj);
1074
VALUE
yielder
;
1075
1076
yielder =
yielder_new
();
1077
1078
return
rb_proc_call
(ptr->
proc
,
rb_ary_new3
(1, yielder));
1079
}
1080
1081
/*
1082
* Document-class: StopIteration
1083
*
1084
* Raised to stop the iteration, in particular by Enumerator#next. It is
1085
* rescued by Kernel#loop.
1086
*
1087
* loop do
1088
* puts "Hello"
1089
* raise StopIteration
1090
* puts "World"
1091
* end
1092
* puts "Done!"
1093
*
1094
* <em>produces:</em>
1095
*
1096
* Hello
1097
* Done!
1098
*/
1099
1100
/*
1101
* call-seq:
1102
* result -> value
1103
*
1104
* Returns the return value of the iterator.
1105
*
1106
* o = Object.new
1107
* def o.each
1108
* yield 1
1109
* yield 2
1110
* yield 3
1111
* 100
1112
* end
1113
*
1114
* e = o.to_enum
1115
*
1116
* puts e.next #=> 1
1117
* puts e.next #=> 2
1118
* puts e.next #=> 3
1119
*
1120
* begin
1121
* e.next
1122
* rescue StopIteration => ex
1123
* puts ex.result #=> 100
1124
* end
1125
*
1126
*/
1127
static
VALUE
1128
stop_result
(
VALUE
self
)
1129
{
1130
return
rb_attr_get
(
self
,
rb_intern
(
"result"
));
1131
}
1132
1133
void
1134
Init_Enumerator
(
void
)
1135
{
1136
rb_define_method
(
rb_mKernel
,
"to_enum"
,
obj_to_enum
, -1);
1137
rb_define_method
(
rb_mKernel
,
"enum_for"
,
obj_to_enum
, -1);
1138
1139
rb_cEnumerator
=
rb_define_class
(
"Enumerator"
,
rb_cObject
);
1140
rb_include_module
(
rb_cEnumerator
,
rb_mEnumerable
);
1141
1142
rb_define_alloc_func
(
rb_cEnumerator
,
enumerator_allocate
);
1143
rb_define_method
(
rb_cEnumerator
,
"initialize"
,
enumerator_initialize
, -1);
1144
rb_define_method
(
rb_cEnumerator
,
"initialize_copy"
,
enumerator_init_copy
, 1);
1145
rb_define_method
(
rb_cEnumerator
,
"each"
,
enumerator_each
, 0);
1146
rb_define_method
(
rb_cEnumerator
,
"each_with_index"
,
enumerator_each_with_index
, 0);
1147
rb_define_method
(
rb_cEnumerator
,
"each_with_object"
,
enumerator_with_object
, 1);
1148
rb_define_method
(
rb_cEnumerator
,
"with_index"
,
enumerator_with_index
, -1);
1149
rb_define_method
(
rb_cEnumerator
,
"with_object"
,
enumerator_with_object
, 1);
1150
rb_define_method
(
rb_cEnumerator
,
"next_values"
,
enumerator_next_values
, 0);
1151
rb_define_method
(
rb_cEnumerator
,
"peek_values"
,
enumerator_peek_values_m
, 0);
1152
rb_define_method
(
rb_cEnumerator
,
"next"
,
enumerator_next
, 0);
1153
rb_define_method
(
rb_cEnumerator
,
"peek"
,
enumerator_peek
, 0);
1154
rb_define_method
(
rb_cEnumerator
,
"feed"
,
enumerator_feed
, 1);
1155
rb_define_method
(
rb_cEnumerator
,
"rewind"
,
enumerator_rewind
, 0);
1156
rb_define_method
(
rb_cEnumerator
,
"inspect"
,
enumerator_inspect
, 0);
1157
1158
rb_eStopIteration
=
rb_define_class
(
"StopIteration"
,
rb_eIndexError
);
1159
rb_define_method
(
rb_eStopIteration
,
"result"
,
stop_result
, 0);
1160
1161
/* Generator */
1162
rb_cGenerator
=
rb_define_class_under
(
rb_cEnumerator
,
"Generator"
,
rb_cObject
);
1163
rb_include_module
(
rb_cGenerator
,
rb_mEnumerable
);
1164
rb_define_alloc_func
(
rb_cGenerator
,
generator_allocate
);
1165
rb_define_method
(
rb_cGenerator
,
"initialize"
,
generator_initialize
, -1);
1166
rb_define_method
(
rb_cGenerator
,
"initialize_copy"
,
generator_init_copy
, 1);
1167
rb_define_method
(
rb_cGenerator
,
"each"
,
generator_each
, 0);
1168
1169
/* Yielder */
1170
rb_cYielder
=
rb_define_class_under
(
rb_cEnumerator
,
"Yielder"
,
rb_cObject
);
1171
rb_define_alloc_func
(
rb_cYielder
,
yielder_allocate
);
1172
rb_define_method
(
rb_cYielder
,
"initialize"
,
yielder_initialize
, 0);
1173
rb_define_method
(
rb_cYielder
,
"yield"
,
yielder_yield
, -2);
1174
rb_define_method
(
rb_cYielder
,
"<<"
,
yielder_yield_push
, -2);
1175
1176
id_rewind
=
rb_intern
(
"rewind"
);
1177
id_each
=
rb_intern
(
"each"
);
1178
sym_each
=
ID2SYM
(
id_each
);
1179
1180
rb_provide
(
"enumerator.so"
);
/* for backward compatibility */
1181
}
1182
Generated on Fri Nov 14 2014 16:03:52 for Ruby by
1.8.3