Ruby 3.2.4p170 (2024-04-23 revision af471c0e0127eea0cafa6f308c0425bbfab0acf5)
enum.c
1/**********************************************************************
2
3 enum.c -
4
5 $Author$
6 created at: Fri Oct 1 15:15:19 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "id.h"
13#include "internal.h"
14#include "internal/compar.h"
15#include "internal/enum.h"
16#include "internal/hash.h"
17#include "internal/imemo.h"
18#include "internal/numeric.h"
19#include "internal/object.h"
20#include "internal/proc.h"
21#include "internal/rational.h"
22#include "internal/re.h"
23#include "ruby/util.h"
24#include "ruby_assert.h"
25#include "symbol.h"
26
28
29static ID id_next;
30static ID id__alone;
31static ID id__separator;
32static ID id_chunk_categorize;
33static ID id_chunk_enumerable;
34static ID id_sliceafter_enum;
35static ID id_sliceafter_pat;
36static ID id_sliceafter_pred;
37static ID id_slicebefore_enumerable;
38static ID id_slicebefore_sep_pat;
39static ID id_slicebefore_sep_pred;
40static ID id_slicewhen_enum;
41static ID id_slicewhen_inverted;
42static ID id_slicewhen_pred;
43
44#define id_div idDiv
45#define id_each idEach
46#define id_eqq idEqq
47#define id_cmp idCmp
48#define id_lshift idLTLT
49#define id_call idCall
50#define id_size idSize
51
53rb_enum_values_pack(int argc, const VALUE *argv)
54{
55 if (argc == 0) return Qnil;
56 if (argc == 1) return argv[0];
57 return rb_ary_new4(argc, argv);
58}
59
60#define ENUM_WANT_SVALUE() do { \
61 i = rb_enum_values_pack(argc, argv); \
62} while (0)
63
64static VALUE
65enum_yield(int argc, VALUE ary)
66{
67 if (argc > 1)
68 return rb_yield_force_blockarg(ary);
69 if (argc == 1)
70 return rb_yield(ary);
71 return rb_yield_values2(0, 0);
72}
73
74static VALUE
75enum_yield_array(VALUE ary)
76{
77 long len = RARRAY_LEN(ary);
78
79 if (len > 1)
80 return rb_yield_force_blockarg(ary);
81 if (len == 1)
82 return rb_yield(RARRAY_AREF(ary, 0));
83 return rb_yield_values2(0, 0);
84}
85
86static VALUE
87grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
88{
89 struct MEMO *memo = MEMO_CAST(args);
90 ENUM_WANT_SVALUE();
91
92 if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
93 rb_ary_push(memo->v2, i);
94 }
95 return Qnil;
96}
97
98static VALUE
99grep_regexp_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
100{
101 struct MEMO *memo = MEMO_CAST(args);
102 VALUE converted_element, match;
103 ENUM_WANT_SVALUE();
104
105 /* In case element can't be converted to a Symbol or String: not a match (don't raise) */
106 converted_element = SYMBOL_P(i) ? i : rb_check_string_type(i);
107 match = NIL_P(converted_element) ? Qfalse : rb_reg_match_p(memo->v1, i, 0);
108 if (match == memo->u3.value) {
109 rb_ary_push(memo->v2, i);
110 }
111 return Qnil;
112}
113
114static VALUE
115grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
116{
117 struct MEMO *memo = MEMO_CAST(args);
118 ENUM_WANT_SVALUE();
119
120 if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
121 rb_ary_push(memo->v2, enum_yield(argc, i));
122 }
123 return Qnil;
124}
125
126static VALUE
127enum_grep0(VALUE obj, VALUE pat, VALUE test)
128{
129 VALUE ary = rb_ary_new();
130 struct MEMO *memo = MEMO_NEW(pat, ary, test);
132 if (rb_block_given_p()) {
133 fn = grep_iter_i;
134 }
135 else if (RB_TYPE_P(pat, T_REGEXP) &&
136 LIKELY(rb_method_basic_definition_p(CLASS_OF(pat), idEqq))) {
137 fn = grep_regexp_i;
138 }
139 else {
140 fn = grep_i;
141 }
142 rb_block_call(obj, id_each, 0, 0, fn, (VALUE)memo);
143
144 return ary;
145}
146
147/*
148 * call-seq:
149 * grep(pattern) -> array
150 * grep(pattern) {|element| ... } -> array
151 *
152 * Returns an array of objects based elements of +self+ that match the given pattern.
153 *
154 * With no block given, returns an array containing each element
155 * for which <tt>pattern === element</tt> is +true+:
156 *
157 * a = ['foo', 'bar', 'car', 'moo']
158 * a.grep(/ar/) # => ["bar", "car"]
159 * (1..10).grep(3..8) # => [3, 4, 5, 6, 7, 8]
160 * ['a', 'b', 0, 1].grep(Integer) # => [0, 1]
161 *
162 * With a block given,
163 * calls the block with each matching element and returns an array containing each
164 * object returned by the block:
165 *
166 * a = ['foo', 'bar', 'car', 'moo']
167 * a.grep(/ar/) {|element| element.upcase } # => ["BAR", "CAR"]
168 *
169 * Related: #grep_v.
170 */
171
172static VALUE
173enum_grep(VALUE obj, VALUE pat)
174{
175 return enum_grep0(obj, pat, Qtrue);
176}
177
178/*
179 * call-seq:
180 * grep_v(pattern) -> array
181 * grep_v(pattern) {|element| ... } -> array
182 *
183 * Returns an array of objects based on elements of +self+
184 * that <em>don't</em> match the given pattern.
185 *
186 * With no block given, returns an array containing each element
187 * for which <tt>pattern === element</tt> is +false+:
188 *
189 * a = ['foo', 'bar', 'car', 'moo']
190 * a.grep_v(/ar/) # => ["foo", "moo"]
191 * (1..10).grep_v(3..8) # => [1, 2, 9, 10]
192 * ['a', 'b', 0, 1].grep_v(Integer) # => ["a", "b"]
193 *
194 * With a block given,
195 * calls the block with each non-matching element and returns an array containing each
196 * object returned by the block:
197 *
198 * a = ['foo', 'bar', 'car', 'moo']
199 * a.grep_v(/ar/) {|element| element.upcase } # => ["FOO", "MOO"]
200 *
201 * Related: #grep.
202 */
203
204static VALUE
205enum_grep_v(VALUE obj, VALUE pat)
206{
207 return enum_grep0(obj, pat, Qfalse);
208}
209
210#define COUNT_BIGNUM IMEMO_FL_USER0
211#define MEMO_V3_SET(m, v) RB_OBJ_WRITE((m), &(m)->u3.value, (v))
212
213static void
214imemo_count_up(struct MEMO *memo)
215{
216 if (memo->flags & COUNT_BIGNUM) {
217 MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
218 }
219 else if (++memo->u3.cnt == 0) {
220 /* overflow */
221 unsigned long buf[2] = {0, 1};
222 MEMO_V3_SET(memo, rb_big_unpack(buf, 2));
223 memo->flags |= COUNT_BIGNUM;
224 }
225}
226
227static VALUE
228imemo_count_value(struct MEMO *memo)
229{
230 if (memo->flags & COUNT_BIGNUM) {
231 return memo->u3.value;
232 }
233 else {
234 return ULONG2NUM(memo->u3.cnt);
235 }
236}
237
238static VALUE
239count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
240{
241 struct MEMO *memo = MEMO_CAST(memop);
242
243 ENUM_WANT_SVALUE();
244
245 if (rb_equal(i, memo->v1)) {
246 imemo_count_up(memo);
247 }
248 return Qnil;
249}
250
251static VALUE
252count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
253{
254 struct MEMO *memo = MEMO_CAST(memop);
255
256 if (RTEST(rb_yield_values2(argc, argv))) {
257 imemo_count_up(memo);
258 }
259 return Qnil;
260}
261
262static VALUE
263count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
264{
265 struct MEMO *memo = MEMO_CAST(memop);
266
267 imemo_count_up(memo);
268 return Qnil;
269}
270
271/*
272 * call-seq:
273 * count -> integer
274 * count(object) -> integer
275 * count {|element| ... } -> integer
276 *
277 * Returns the count of elements, based on an argument or block criterion, if given.
278 *
279 * With no argument and no block given, returns the number of elements:
280 *
281 * [0, 1, 2].count # => 3
282 * {foo: 0, bar: 1, baz: 2}.count # => 3
283 *
284 * With argument +object+ given,
285 * returns the number of elements that are <tt>==</tt> to +object+:
286 *
287 * [0, 1, 2, 1].count(1) # => 2
288 *
289 * With a block given, calls the block with each element
290 * and returns the number of elements for which the block returns a truthy value:
291 *
292 * [0, 1, 2, 3].count {|element| element < 2} # => 2
293 * {foo: 0, bar: 1, baz: 2}.count {|key, value| value < 2} # => 2
294 *
295 */
296
297static VALUE
298enum_count(int argc, VALUE *argv, VALUE obj)
299{
300 VALUE item = Qnil;
301 struct MEMO *memo;
302 rb_block_call_func *func;
303
304 if (argc == 0) {
305 if (rb_block_given_p()) {
306 func = count_iter_i;
307 }
308 else {
309 func = count_all_i;
310 }
311 }
312 else {
313 rb_scan_args(argc, argv, "1", &item);
314 if (rb_block_given_p()) {
315 rb_warn("given block not used");
316 }
317 func = count_i;
318 }
319
320 memo = MEMO_NEW(item, 0, 0);
321 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
322 return imemo_count_value(memo);
323}
324
325static VALUE
326find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
327{
328 ENUM_WANT_SVALUE();
329
330 if (RTEST(enum_yield(argc, i))) {
331 struct MEMO *memo = MEMO_CAST(memop);
332 MEMO_V1_SET(memo, i);
333 memo->u3.cnt = 1;
335 }
336 return Qnil;
337}
338
339/*
340 * call-seq:
341 * find(if_none_proc = nil) {|element| ... } -> object or nil
342 * find(if_none_proc = nil) -> enumerator
343 *
344 * Returns the first element for which the block returns a truthy value.
345 *
346 * With a block given, calls the block with successive elements of the collection;
347 * returns the first element for which the block returns a truthy value:
348 *
349 * (0..9).find {|element| element > 2} # => 3
350 *
351 * If no such element is found, calls +if_none_proc+ and returns its return value.
352 *
353 * (0..9).find(proc {false}) {|element| element > 12} # => false
354 * {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') } # => [:bar, 1]
355 * {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => []
356 *
357 * With no block given, returns an \Enumerator.
358 *
359 */
360static VALUE
361enum_find(int argc, VALUE *argv, VALUE obj)
362{
363 struct MEMO *memo;
364 VALUE if_none;
365
366 if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
367 RETURN_ENUMERATOR(obj, argc, argv);
368 memo = MEMO_NEW(Qundef, 0, 0);
369 rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
370 if (memo->u3.cnt) {
371 return memo->v1;
372 }
373 if (!NIL_P(if_none)) {
374 return rb_funcallv(if_none, id_call, 0, 0);
375 }
376 return Qnil;
377}
378
379static VALUE
380find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
381{
382 struct MEMO *memo = MEMO_CAST(memop);
383
384 ENUM_WANT_SVALUE();
385
386 if (rb_equal(i, memo->v2)) {
387 MEMO_V1_SET(memo, imemo_count_value(memo));
389 }
390 imemo_count_up(memo);
391 return Qnil;
392}
393
394static VALUE
395find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
396{
397 struct MEMO *memo = MEMO_CAST(memop);
398
399 if (RTEST(rb_yield_values2(argc, argv))) {
400 MEMO_V1_SET(memo, imemo_count_value(memo));
402 }
403 imemo_count_up(memo);
404 return Qnil;
405}
406
407/*
408 * call-seq:
409 * find_index(object) -> integer or nil
410 * find_index {|element| ... } -> integer or nil
411 * find_index -> enumerator
412 *
413 * Returns the index of the first element that meets a specified criterion,
414 * or +nil+ if no such element is found.
415 *
416 * With argument +object+ given,
417 * returns the index of the first element that is <tt>==</tt> +object+:
418 *
419 * ['a', 'b', 'c', 'b'].find_index('b') # => 1
420 *
421 * With a block given, calls the block with successive elements;
422 * returns the first element for which the block returns a truthy value:
423 *
424 * ['a', 'b', 'c', 'b'].find_index {|element| element.start_with?('b') } # => 1
425 * {foo: 0, bar: 1, baz: 2}.find_index {|key, value| value > 1 } # => 2
426 *
427 * With no argument and no block given, returns an \Enumerator.
428 *
429 */
430
431static VALUE
432enum_find_index(int argc, VALUE *argv, VALUE obj)
433{
434 struct MEMO *memo; /* [return value, current index, ] */
435 VALUE condition_value = Qnil;
436 rb_block_call_func *func;
437
438 if (argc == 0) {
439 RETURN_ENUMERATOR(obj, 0, 0);
440 func = find_index_iter_i;
441 }
442 else {
443 rb_scan_args(argc, argv, "1", &condition_value);
444 if (rb_block_given_p()) {
445 rb_warn("given block not used");
446 }
447 func = find_index_i;
448 }
449
450 memo = MEMO_NEW(Qnil, condition_value, 0);
451 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
452 return memo->v1;
453}
454
455static VALUE
456find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
457{
458 ENUM_WANT_SVALUE();
459
460 if (RTEST(enum_yield(argc, i))) {
461 rb_ary_push(ary, i);
462 }
463 return Qnil;
464}
465
466static VALUE
467enum_size(VALUE self, VALUE args, VALUE eobj)
468{
469 return rb_check_funcall_default(self, id_size, 0, 0, Qnil);
470}
471
472static long
473limit_by_enum_size(VALUE obj, long n)
474{
475 unsigned long limit;
476 VALUE size = rb_check_funcall(obj, id_size, 0, 0);
477 if (!FIXNUM_P(size)) return n;
478 limit = FIX2ULONG(size);
479 return ((unsigned long)n > limit) ? (long)limit : n;
480}
481
482static int
483enum_size_over_p(VALUE obj, long n)
484{
485 VALUE size = rb_check_funcall(obj, id_size, 0, 0);
486 if (!FIXNUM_P(size)) return 0;
487 return ((unsigned long)n > FIX2ULONG(size));
488}
489
490/*
491 * call-seq:
492 * select {|element| ... } -> array
493 * select -> enumerator
494 *
495 * Returns an array containing elements selected by the block.
496 *
497 * With a block given, calls the block with successive elements;
498 * returns an array of those elements for which the block returns a truthy value:
499 *
500 * (0..9).select {|element| element % 3 == 0 } # => [0, 3, 6, 9]
501 * a = {foo: 0, bar: 1, baz: 2}.select {|key, value| key.start_with?('b') }
502 * a # => {:bar=>1, :baz=>2}
503 *
504 * With no block given, returns an \Enumerator.
505 *
506 * Related: #reject.
507 */
508static VALUE
509enum_find_all(VALUE obj)
510{
511 VALUE ary;
512
513 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
514
515 ary = rb_ary_new();
516 rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
517
518 return ary;
519}
520
521static VALUE
522filter_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
523{
524 i = rb_yield_values2(argc, argv);
525
526 if (RTEST(i)) {
527 rb_ary_push(ary, i);
528 }
529
530 return Qnil;
531}
532
533/*
534 * call-seq:
535 * filter_map {|element| ... } -> array
536 * filter_map -> enumerator
537 *
538 * Returns an array containing truthy elements returned by the block.
539 *
540 * With a block given, calls the block with successive elements;
541 * returns an array containing each truthy value returned by the block:
542 *
543 * (0..9).filter_map {|i| i * 2 if i.even? } # => [0, 4, 8, 12, 16]
544 * {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz]
545 *
546 * When no block given, returns an \Enumerator.
547 *
548 */
549static VALUE
550enum_filter_map(VALUE obj)
551{
552 VALUE ary;
553
554 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
555
556 ary = rb_ary_new();
557 rb_block_call(obj, id_each, 0, 0, filter_map_i, ary);
558
559 return ary;
560}
561
562
563static VALUE
564reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
565{
566 ENUM_WANT_SVALUE();
567
568 if (!RTEST(enum_yield(argc, i))) {
569 rb_ary_push(ary, i);
570 }
571 return Qnil;
572}
573
574/*
575 * call-seq:
576 * reject {|element| ... } -> array
577 * reject -> enumerator
578 *
579 * Returns an array of objects rejected by the block.
580 *
581 * With a block given, calls the block with successive elements;
582 * returns an array of those elements for which the block returns +nil+ or +false+:
583 *
584 * (0..9).reject {|i| i * 2 if i.even? } # => [1, 3, 5, 7, 9]
585 * {foo: 0, bar: 1, baz: 2}.reject {|key, value| key if value.odd? } # => {:foo=>0, :baz=>2}
586 *
587 * When no block given, returns an \Enumerator.
588 *
589 * Related: #select.
590 */
591
592static VALUE
593enum_reject(VALUE obj)
594{
595 VALUE ary;
596
597 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
598
599 ary = rb_ary_new();
600 rb_block_call(obj, id_each, 0, 0, reject_i, ary);
601
602 return ary;
603}
604
605static VALUE
606collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
607{
608 rb_ary_push(ary, rb_yield_values2(argc, argv));
609
610 return Qnil;
611}
612
613static VALUE
614collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
615{
616 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
617
618 return Qnil;
619}
620
621/*
622 * call-seq:
623 * map {|element| ... } -> array
624 * map -> enumerator
625 *
626 * Returns an array of objects returned by the block.
627 *
628 * With a block given, calls the block with successive elements;
629 * returns an array of the objects returned by the block:
630 *
631 * (0..4).map {|i| i*i } # => [0, 1, 4, 9, 16]
632 * {foo: 0, bar: 1, baz: 2}.map {|key, value| value*2} # => [0, 2, 4]
633 *
634 * With no block given, returns an \Enumerator.
635 *
636 */
637static VALUE
638enum_collect(VALUE obj)
639{
640 VALUE ary;
641 int min_argc, max_argc;
642
643 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
644
645 ary = rb_ary_new();
646 min_argc = rb_block_min_max_arity(&max_argc);
647 rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
648
649 return ary;
650}
651
652static VALUE
653flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
654{
655 VALUE tmp;
656
657 i = rb_yield_values2(argc, argv);
658 tmp = rb_check_array_type(i);
659
660 if (NIL_P(tmp)) {
661 rb_ary_push(ary, i);
662 }
663 else {
664 rb_ary_concat(ary, tmp);
665 }
666 return Qnil;
667}
668
669/*
670 * call-seq:
671 * flat_map {|element| ... } -> array
672 * flat_map -> enumerator
673 *
674 * Returns an array of flattened objects returned by the block.
675 *
676 * With a block given, calls the block with successive elements;
677 * returns a flattened array of objects returned by the block:
678 *
679 * [0, 1, 2, 3].flat_map {|element| -element } # => [0, -1, -2, -3]
680 * [0, 1, 2, 3].flat_map {|element| [element, -element] } # => [0, 0, 1, -1, 2, -2, 3, -3]
681 * [[0, 1], [2, 3]].flat_map {|e| e + [100] } # => [0, 1, 100, 2, 3, 100]
682 * {foo: 0, bar: 1, baz: 2}.flat_map {|key, value| [key, value] } # => [:foo, 0, :bar, 1, :baz, 2]
683 *
684 * With no block given, returns an \Enumerator.
685 *
686 * Alias: #collect_concat.
687 */
688static VALUE
689enum_flat_map(VALUE obj)
690{
691 VALUE ary;
692
693 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
694
695 ary = rb_ary_new();
696 rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
697
698 return ary;
699}
700
701/*
702 * call-seq:
703 * to_a -> array
704 *
705 * Returns an array containing the items in +self+:
706 *
707 * (0..4).to_a # => [0, 1, 2, 3, 4]
708 *
709 * Enumerable#entries is an alias for Enumerable#to_a.
710 */
711static VALUE
712enum_to_a(int argc, VALUE *argv, VALUE obj)
713{
714 VALUE ary = rb_ary_new();
715
716 rb_block_call_kw(obj, id_each, argc, argv, collect_all, ary, RB_PASS_CALLED_KEYWORDS);
717
718 return ary;
719}
720
721static VALUE
722enum_hashify_into(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter, VALUE hash)
723{
724 rb_block_call(obj, id_each, argc, argv, iter, hash);
725 return hash;
726}
727
728static VALUE
729enum_hashify(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter)
730{
731 return enum_hashify_into(obj, argc, argv, iter, rb_hash_new());
732}
733
734static VALUE
735enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
736{
737 ENUM_WANT_SVALUE();
738 return rb_hash_set_pair(hash, i);
739}
740
741static VALUE
742enum_to_h_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
743{
744 return rb_hash_set_pair(hash, rb_yield_values2(argc, argv));
745}
746
747/*
748 * call-seq:
749 * to_h -> hash
750 * to_h {|element| ... } -> hash
751 *
752 * When +self+ consists of 2-element arrays,
753 * returns a hash each of whose entries is the key-value pair
754 * formed from one of those arrays:
755 *
756 * [[:foo, 0], [:bar, 1], [:baz, 2]].to_h # => {:foo=>0, :bar=>1, :baz=>2}
757 *
758 * When a block is given, the block is called with each element of +self+;
759 * the block should return a 2-element array which becomes a key-value pair
760 * in the returned hash:
761 *
762 * (0..3).to_h {|i| [i, i ** 2]} # => {0=>0, 1=>1, 2=>4, 3=>9}
763 *
764 * Raises an exception if an element of +self+ is not a 2-element array,
765 * and a block is not passed.
766 */
767
768static VALUE
769enum_to_h(int argc, VALUE *argv, VALUE obj)
770{
771 rb_block_call_func *iter = rb_block_given_p() ? enum_to_h_ii : enum_to_h_i;
772 return enum_hashify(obj, argc, argv, iter);
773}
774
775static VALUE
776inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
777{
778 struct MEMO *memo = MEMO_CAST(p);
779
780 ENUM_WANT_SVALUE();
781
782 if (UNDEF_P(memo->v1)) {
783 MEMO_V1_SET(memo, i);
784 }
785 else {
786 MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
787 }
788 return Qnil;
789}
790
791static VALUE
792inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
793{
794 struct MEMO *memo = MEMO_CAST(p);
795 VALUE name;
796
797 ENUM_WANT_SVALUE();
798
799 if (UNDEF_P(memo->v1)) {
800 MEMO_V1_SET(memo, i);
801 }
802 else if (SYMBOL_P(name = memo->u3.value)) {
803 const ID mid = SYM2ID(name);
804 MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i));
805 }
806 else {
807 VALUE args[2];
808 args[0] = name;
809 args[1] = i;
810 MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
811 }
812 return Qnil;
813}
814
815static VALUE
816ary_inject_op(VALUE ary, VALUE init, VALUE op)
817{
818 ID id;
819 VALUE v, e;
820 long i, n;
821
822 if (RARRAY_LEN(ary) == 0)
823 return UNDEF_P(init) ? Qnil : init;
824
825 if (UNDEF_P(init)) {
826 v = RARRAY_AREF(ary, 0);
827 i = 1;
828 if (RARRAY_LEN(ary) == 1)
829 return v;
830 }
831 else {
832 v = init;
833 i = 0;
834 }
835
836 id = SYM2ID(op);
837 if (id == idPLUS) {
838 if (RB_INTEGER_TYPE_P(v) &&
839 rb_method_basic_definition_p(rb_cInteger, idPLUS) &&
840 rb_obj_respond_to(v, idPLUS, FALSE)) {
841 n = 0;
842 for (; i < RARRAY_LEN(ary); i++) {
843 e = RARRAY_AREF(ary, i);
844 if (FIXNUM_P(e)) {
845 n += FIX2LONG(e); /* should not overflow long type */
846 if (!FIXABLE(n)) {
847 v = rb_big_plus(LONG2NUM(n), v);
848 n = 0;
849 }
850 }
851 else if (RB_BIGNUM_TYPE_P(e))
852 v = rb_big_plus(e, v);
853 else
854 goto not_integer;
855 }
856 if (n != 0)
857 v = rb_fix_plus(LONG2FIX(n), v);
858 return v;
859
860 not_integer:
861 if (n != 0)
862 v = rb_fix_plus(LONG2FIX(n), v);
863 }
864 }
865 for (; i < RARRAY_LEN(ary); i++) {
866 VALUE arg = RARRAY_AREF(ary, i);
867 v = rb_funcallv_public(v, id, 1, &arg);
868 }
869 return v;
870}
871
872/*
873 * call-seq:
874 * inject(symbol) -> object
875 * inject(initial_operand, symbol) -> object
876 * inject {|memo, operand| ... } -> object
877 * inject(initial_operand) {|memo, operand| ... } -> object
878 *
879 * Returns an object formed from operands via either:
880 *
881 * - A method named by +symbol+.
882 * - A block to which each operand is passed.
883 *
884 * With method-name argument +symbol+,
885 * combines operands using the method:
886 *
887 * # Sum, without initial_operand.
888 * (1..4).inject(:+) # => 10
889 * # Sum, with initial_operand.
890 * (1..4).inject(10, :+) # => 20
891 *
892 * With a block, passes each operand to the block:
893 *
894 * # Sum of squares, without initial_operand.
895 * (1..4).inject {|sum, n| sum + n*n } # => 30
896 * # Sum of squares, with initial_operand.
897 * (1..4).inject(2) {|sum, n| sum + n*n } # => 32
898 *
899 * <b>Operands</b>
900 *
901 * If argument +initial_operand+ is not given,
902 * the operands for +inject+ are simply the elements of +self+.
903 * Example calls and their operands:
904 *
905 * - <tt>(1..4).inject(:+)</tt>:: <tt>[1, 2, 3, 4]</tt>.
906 * - <tt>(1...4).inject(:+)</tt>:: <tt>[1, 2, 3]</tt>.
907 * - <tt>('a'..'d').inject(:+)</tt>:: <tt>['a', 'b', 'c', 'd']</tt>.
908 * - <tt>('a'...'d').inject(:+)</tt>:: <tt>['a', 'b', 'c']</tt>.
909 *
910 * Examples with first operand (which is <tt>self.first</tt>) of various types:
911 *
912 * # Integer.
913 * (1..4).inject(:+) # => 10
914 * # Float.
915 * [1.0, 2, 3, 4].inject(:+) # => 10.0
916 * # Character.
917 * ('a'..'d').inject(:+) # => "abcd"
918 * # Complex.
919 * [Complex(1, 2), 3, 4].inject(:+) # => (8+2i)
920 *
921 * If argument +initial_operand+ is given,
922 * the operands for +inject+ are that value plus the elements of +self+.
923 * Example calls their operands:
924 *
925 * - <tt>(1..4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3, 4]</tt>.
926 * - <tt>(1...4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3]</tt>.
927 * - <tt>('a'..'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c', 'd']</tt>.
928 * - <tt>('a'...'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c']</tt>.
929 *
930 * Examples with +initial_operand+ of various types:
931 *
932 * # Integer.
933 * (1..4).inject(2, :+) # => 12
934 * # Float.
935 * (1..4).inject(2.0, :+) # => 12.0
936 * # String.
937 * ('a'..'d').inject('foo', :+) # => "fooabcd"
938 * # Array.
939 * %w[a b c].inject(['x'], :push) # => ["x", "a", "b", "c"]
940 * # Complex.
941 * (1..4).inject(Complex(2, 2), :+) # => (12+2i)
942 *
943 * <b>Combination by Given \Method</b>
944 *
945 * If the method-name argument +symbol+ is given,
946 * the operands are combined by that method:
947 *
948 * - The first and second operands are combined.
949 * - That result is combined with the third operand.
950 * - That result is combined with the fourth operand.
951 * - And so on.
952 *
953 * The return value from +inject+ is the result of the last combination.
954 *
955 * This call to +inject+ computes the sum of the operands:
956 *
957 * (1..4).inject(:+) # => 10
958 *
959 * Examples with various methods:
960 *
961 * # Integer addition.
962 * (1..4).inject(:+) # => 10
963 * # Integer multiplication.
964 * (1..4).inject(:*) # => 24
965 * # Character range concatenation.
966 * ('a'..'d').inject('', :+) # => "abcd"
967 * # String array concatenation.
968 * %w[foo bar baz].inject('', :+) # => "foobarbaz"
969 * # Hash update.
970 * h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update)
971 * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
972 * # Hash conversion to nested arrays.
973 * h = {foo: 0, bar: 1}.inject([], :push)
974 * h # => [[:foo, 0], [:bar, 1]]
975 *
976 * <b>Combination by Given Block</b>
977 *
978 * If a block is given, the operands are passed to the block:
979 *
980 * - The first call passes the first and second operands.
981 * - The second call passes the result of the first call,
982 * along with the third operand.
983 * - The third call passes the result of the second call,
984 * along with the fourth operand.
985 * - And so on.
986 *
987 * The return value from +inject+ is the return value from the last block call.
988 *
989 * This call to +inject+ gives a block
990 * that writes the memo and element, and also sums the elements:
991 *
992 * (1..4).inject do |memo, element|
993 * p "Memo: #{memo}; element: #{element}"
994 * memo + element
995 * end # => 10
996 *
997 * Output:
998 *
999 * "Memo: 1; element: 2"
1000 * "Memo: 3; element: 3"
1001 * "Memo: 6; element: 4"
1002 *
1003 * Enumerable#reduce is an alias for Enumerable#inject.
1004 *
1005 */
1006static VALUE
1007enum_inject(int argc, VALUE *argv, VALUE obj)
1008{
1009 struct MEMO *memo;
1010 VALUE init, op;
1011 rb_block_call_func *iter = inject_i;
1012 ID id;
1013 int num_args;
1014
1015 if (rb_block_given_p()) {
1016 num_args = rb_scan_args(argc, argv, "02", &init, &op);
1017 }
1018 else {
1019 num_args = rb_scan_args(argc, argv, "11", &init, &op);
1020 }
1021
1022 switch (num_args) {
1023 case 0:
1024 init = Qundef;
1025 break;
1026 case 1:
1027 if (rb_block_given_p()) {
1028 break;
1029 }
1030 id = rb_check_id(&init);
1031 op = id ? ID2SYM(id) : init;
1032 init = Qundef;
1033 iter = inject_op_i;
1034 break;
1035 case 2:
1036 if (rb_block_given_p()) {
1037 rb_warning("given block not used");
1038 }
1039 id = rb_check_id(&op);
1040 if (id) op = ID2SYM(id);
1041 iter = inject_op_i;
1042 break;
1043 }
1044
1045 if (iter == inject_op_i &&
1046 SYMBOL_P(op) &&
1047 RB_TYPE_P(obj, T_ARRAY) &&
1048 rb_method_basic_definition_p(CLASS_OF(obj), id_each)) {
1049 return ary_inject_op(obj, init, op);
1050 }
1051
1052 memo = MEMO_NEW(init, Qnil, op);
1053 rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
1054 if (UNDEF_P(memo->v1)) return Qnil;
1055 return memo->v1;
1056}
1057
1058static VALUE
1059partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
1060{
1061 struct MEMO *memo = MEMO_CAST(arys);
1062 VALUE ary;
1063 ENUM_WANT_SVALUE();
1064
1065 if (RTEST(enum_yield(argc, i))) {
1066 ary = memo->v1;
1067 }
1068 else {
1069 ary = memo->v2;
1070 }
1071 rb_ary_push(ary, i);
1072 return Qnil;
1073}
1074
1075/*
1076 * call-seq:
1077 * partition {|element| ... } -> [true_array, false_array]
1078 * partition -> enumerator
1079 *
1080 * With a block given, returns an array of two arrays:
1081 *
1082 * - The first having those elements for which the block returns a truthy value.
1083 * - The other having all other elements.
1084 *
1085 * Examples:
1086 *
1087 * p = (1..4).partition {|i| i.even? }
1088 * p # => [[2, 4], [1, 3]]
1089 * p = ('a'..'d').partition {|c| c < 'c' }
1090 * p # => [["a", "b"], ["c", "d"]]
1091 * h = {foo: 0, bar: 1, baz: 2, bat: 3}
1092 * p = h.partition {|key, value| key.start_with?('b') }
1093 * p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]]
1094 * p = h.partition {|key, value| value < 2 }
1095 * p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]]
1096 *
1097 * With no block given, returns an Enumerator.
1098 *
1099 * Related: Enumerable#group_by.
1100 *
1101 */
1102
1103static VALUE
1104enum_partition(VALUE obj)
1105{
1106 struct MEMO *memo;
1107
1108 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1109
1110 memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
1111 rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
1112
1113 return rb_assoc_new(memo->v1, memo->v2);
1114}
1115
1116static VALUE
1117group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
1118{
1119 VALUE group;
1120 VALUE values;
1121
1122 ENUM_WANT_SVALUE();
1123
1124 group = enum_yield(argc, i);
1125 values = rb_hash_aref(hash, group);
1126 if (!RB_TYPE_P(values, T_ARRAY)) {
1127 values = rb_ary_new3(1, i);
1128 rb_hash_aset(hash, group, values);
1129 }
1130 else {
1131 rb_ary_push(values, i);
1132 }
1133 return Qnil;
1134}
1135
1136/*
1137 * call-seq:
1138 * group_by {|element| ... } -> hash
1139 * group_by -> enumerator
1140 *
1141 * With a block given returns a hash:
1142 *
1143 * - Each key is a return value from the block.
1144 * - Each value is an array of those elements for which the block returned that key.
1145 *
1146 * Examples:
1147 *
1148 * g = (1..6).group_by {|i| i%3 }
1149 * g # => {1=>[1, 4], 2=>[2, 5], 0=>[3, 6]}
1150 * h = {foo: 0, bar: 1, baz: 0, bat: 1}
1151 * g = h.group_by {|key, value| value }
1152 * g # => {0=>[[:foo, 0], [:baz, 0]], 1=>[[:bar, 1], [:bat, 1]]}
1153 *
1154 * With no block given, returns an Enumerator.
1155 *
1156 */
1157
1158static VALUE
1159enum_group_by(VALUE obj)
1160{
1161 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1162
1163 return enum_hashify(obj, 0, 0, group_by_i);
1164}
1165
1166static int
1167tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing)
1168{
1169 VALUE tally = (VALUE)*value;
1170 VALUE hash = (VALUE)arg;
1171 if (!existing) {
1172 tally = INT2FIX(1);
1173 }
1174 else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) {
1175 tally += INT2FIX(1) & ~FIXNUM_FLAG;
1176 }
1177 else {
1178 Check_Type(tally, T_BIGNUM);
1179 tally = rb_big_plus(tally, INT2FIX(1));
1180 RB_OBJ_WRITTEN(hash, Qundef, tally);
1181 }
1182 *value = (st_data_t)tally;
1183 if (!SPECIAL_CONST_P(*group)) RB_OBJ_WRITTEN(hash, Qundef, *group);
1184 return ST_CONTINUE;
1185}
1186
1187static VALUE
1188rb_enum_tally_up(VALUE hash, VALUE group)
1189{
1190 rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash);
1191 return hash;
1192}
1193
1194static VALUE
1195tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
1196{
1197 ENUM_WANT_SVALUE();
1198 rb_enum_tally_up(hash, i);
1199 return Qnil;
1200}
1201
1202/*
1203 * call-seq:
1204 * tally -> new_hash
1205 * tally(hash) -> hash
1206 *
1207 * Returns a hash containing the counts of equal elements:
1208 *
1209 * - Each key is an element of +self+.
1210 * - Each value is the number elements equal to that key.
1211 *
1212 * With no argument:
1213 *
1214 * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}
1215 *
1216 * With a hash argument, that hash is used for the tally (instead of a new hash),
1217 * and is returned;
1218 * this may be useful for accumulating tallies across multiple enumerables:
1219 *
1220 * hash = {}
1221 * hash = %w[a c d b c a].tally(hash)
1222 * hash # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
1223 * hash = %w[b a z].tally(hash)
1224 * hash # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
1225 * hash = %w[b a m].tally(hash)
1226 * hash # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=> 1}
1227 *
1228 */
1229
1230static VALUE
1231enum_tally(int argc, VALUE *argv, VALUE obj)
1232{
1233 VALUE hash;
1234 if (rb_check_arity(argc, 0, 1)) {
1235 hash = rb_to_hash_type(argv[0]);
1236 rb_check_frozen(hash);
1237 }
1238 else {
1239 hash = rb_hash_new();
1240 }
1241
1242 return enum_hashify_into(obj, 0, 0, tally_i, hash);
1243}
1244
1245NORETURN(static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params)));
1246static VALUE
1247first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
1248{
1249 struct MEMO *memo = MEMO_CAST(params);
1250 ENUM_WANT_SVALUE();
1251
1252 MEMO_V1_SET(memo, i);
1253 rb_iter_break();
1254
1256}
1257
1258static VALUE enum_take(VALUE obj, VALUE n);
1259
1260/*
1261 * call-seq:
1262 * first -> element or nil
1263 * first(n) -> array
1264 *
1265 * Returns the first element or elements.
1266 *
1267 * With no argument, returns the first element, or +nil+ if there is none:
1268 *
1269 * (1..4).first # => 1
1270 * %w[a b c].first # => "a"
1271 * {foo: 1, bar: 1, baz: 2}.first # => [:foo, 1]
1272 * [].first # => nil
1273 *
1274 * With integer argument +n+, returns an array
1275 * containing the first +n+ elements that exist:
1276 *
1277 * (1..4).first(2) # => [1, 2]
1278 * %w[a b c d].first(3) # => ["a", "b", "c"]
1279 * %w[a b c d].first(50) # => ["a", "b", "c", "d"]
1280 * {foo: 1, bar: 1, baz: 2}.first(2) # => [[:foo, 1], [:bar, 1]]
1281 * [].first(2) # => []
1282 *
1283 */
1284
1285static VALUE
1286enum_first(int argc, VALUE *argv, VALUE obj)
1287{
1288 struct MEMO *memo;
1289 rb_check_arity(argc, 0, 1);
1290 if (argc > 0) {
1291 return enum_take(obj, argv[0]);
1292 }
1293 else {
1294 memo = MEMO_NEW(Qnil, 0, 0);
1295 rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
1296 return memo->v1;
1297 }
1298}
1299
1300/*
1301 * call-seq:
1302 * sort -> array
1303 * sort {|a, b| ... } -> array
1304 *
1305 * Returns an array containing the sorted elements of +self+.
1306 * The ordering of equal elements is indeterminate and may be unstable.
1307 *
1308 * With no block given, the sort compares
1309 * using the elements' own method <tt><=></tt>:
1310 *
1311 * %w[b c a d].sort # => ["a", "b", "c", "d"]
1312 * {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]]
1313 *
1314 * With a block given, comparisons in the block determine the ordering.
1315 * The block is called with two elements +a+ and +b+, and must return:
1316 *
1317 * - A negative integer if <tt>a < b</tt>.
1318 * - Zero if <tt>a == b</tt>.
1319 * - A positive integer if <tt>a > b</tt>.
1320 *
1321 * Examples:
1322 *
1323 * a = %w[b c a d]
1324 * a.sort {|a, b| b <=> a } # => ["d", "c", "b", "a"]
1325 * h = {foo: 0, bar: 1, baz: 2}
1326 * h.sort {|a, b| b <=> a } # => [[:foo, 0], [:baz, 2], [:bar, 1]]
1327 *
1328 * See also #sort_by. It implements a Schwartzian transform
1329 * which is useful when key computation or comparison is expensive.
1330 */
1331
1332static VALUE
1333enum_sort(VALUE obj)
1334{
1335 return rb_ary_sort_bang(enum_to_a(0, 0, obj));
1336}
1337
1338#define SORT_BY_BUFSIZE 16
1340 const VALUE ary;
1341 const VALUE buf;
1342 long n;
1343};
1344
1345static VALUE
1346sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
1347{
1348 struct sort_by_data *data = (struct sort_by_data *)&MEMO_CAST(_data)->v1;
1349 VALUE ary = data->ary;
1350 VALUE v;
1351
1352 ENUM_WANT_SVALUE();
1353
1354 v = enum_yield(argc, i);
1355
1356 if (RBASIC(ary)->klass) {
1357 rb_raise(rb_eRuntimeError, "sort_by reentered");
1358 }
1359 if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
1360 rb_raise(rb_eRuntimeError, "sort_by reentered");
1361 }
1362
1363 RARRAY_ASET(data->buf, data->n*2, v);
1364 RARRAY_ASET(data->buf, data->n*2+1, i);
1365 data->n++;
1366 if (data->n == SORT_BY_BUFSIZE) {
1367 rb_ary_concat(ary, data->buf);
1368 data->n = 0;
1369 }
1370 return Qnil;
1371}
1372
1373static int
1374sort_by_cmp(const void *ap, const void *bp, void *data)
1375{
1376 VALUE a;
1377 VALUE b;
1378 VALUE ary = (VALUE)data;
1379
1380 if (RBASIC(ary)->klass) {
1381 rb_raise(rb_eRuntimeError, "sort_by reentered");
1382 }
1383
1384 a = *(VALUE *)ap;
1385 b = *(VALUE *)bp;
1386
1387 return OPTIMIZED_CMP(a, b);
1388}
1389
1390/*
1391 * call-seq:
1392 * sort_by {|element| ... } -> array
1393 * sort_by -> enumerator
1394 *
1395 * With a block given, returns an array of elements of +self+,
1396 * sorted according to the value returned by the block for each element.
1397 * The ordering of equal elements is indeterminate and may be unstable.
1398 *
1399 * Examples:
1400 *
1401 * a = %w[xx xxx x xxxx]
1402 * a.sort_by {|s| s.size } # => ["x", "xx", "xxx", "xxxx"]
1403 * a.sort_by {|s| -s.size } # => ["xxxx", "xxx", "xx", "x"]
1404 * h = {foo: 2, bar: 1, baz: 0}
1405 * h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]]
1406 * h.sort_by{|key, value| key } # => [[:bar, 1], [:baz, 0], [:foo, 2]]
1407 *
1408 * With no block given, returns an Enumerator.
1409 *
1410 * The current implementation of #sort_by generates an array of
1411 * tuples containing the original collection element and the mapped
1412 * value. This makes #sort_by fairly expensive when the keysets are
1413 * simple.
1414 *
1415 * require 'benchmark'
1416 *
1417 * a = (1..100000).map { rand(100000) }
1418 *
1419 * Benchmark.bm(10) do |b|
1420 * b.report("Sort") { a.sort }
1421 * b.report("Sort by") { a.sort_by { |a| a } }
1422 * end
1423 *
1424 * <em>produces:</em>
1425 *
1426 * user system total real
1427 * Sort 0.180000 0.000000 0.180000 ( 0.175469)
1428 * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
1429 *
1430 * However, consider the case where comparing the keys is a non-trivial
1431 * operation. The following code sorts some files on modification time
1432 * using the basic #sort method.
1433 *
1434 * files = Dir["*"]
1435 * sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
1436 * sorted #=> ["mon", "tues", "wed", "thurs"]
1437 *
1438 * This sort is inefficient: it generates two new File
1439 * objects during every comparison. A slightly better technique is to
1440 * use the Kernel#test method to generate the modification
1441 * times directly.
1442 *
1443 * files = Dir["*"]
1444 * sorted = files.sort { |a, b|
1445 * test(?M, a) <=> test(?M, b)
1446 * }
1447 * sorted #=> ["mon", "tues", "wed", "thurs"]
1448 *
1449 * This still generates many unnecessary Time objects. A more
1450 * efficient technique is to cache the sort keys (modification times
1451 * in this case) before the sort. Perl users often call this approach
1452 * a Schwartzian transform, after Randal Schwartz. We construct a
1453 * temporary array, where each element is an array containing our
1454 * sort key along with the filename. We sort this array, and then
1455 * extract the filename from the result.
1456 *
1457 * sorted = Dir["*"].collect { |f|
1458 * [test(?M, f), f]
1459 * }.sort.collect { |f| f[1] }
1460 * sorted #=> ["mon", "tues", "wed", "thurs"]
1461 *
1462 * This is exactly what #sort_by does internally.
1463 *
1464 * sorted = Dir["*"].sort_by { |f| test(?M, f) }
1465 * sorted #=> ["mon", "tues", "wed", "thurs"]
1466 *
1467 * To produce the reverse of a specific order, the following can be used:
1468 *
1469 * ary.sort_by { ... }.reverse!
1470 */
1471
1472static VALUE
1473enum_sort_by(VALUE obj)
1474{
1475 VALUE ary, buf;
1476 struct MEMO *memo;
1477 long i;
1478 struct sort_by_data *data;
1479
1480 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1481
1482 if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
1483 ary = rb_ary_new2(RARRAY_LEN(obj)*2);
1484 }
1485 else {
1486 ary = rb_ary_new();
1487 }
1488 RBASIC_CLEAR_CLASS(ary);
1489 buf = rb_ary_hidden_new(SORT_BY_BUFSIZE*2);
1490 rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
1491 memo = MEMO_NEW(0, 0, 0);
1492 data = (struct sort_by_data *)&memo->v1;
1493 RB_OBJ_WRITE(memo, &data->ary, ary);
1494 RB_OBJ_WRITE(memo, &data->buf, buf);
1495 data->n = 0;
1496 rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
1497 ary = data->ary;
1498 buf = data->buf;
1499 if (data->n) {
1500 rb_ary_resize(buf, data->n*2);
1501 rb_ary_concat(ary, buf);
1502 }
1503 if (RARRAY_LEN(ary) > 2) {
1504 RARRAY_PTR_USE(ary, ptr,
1505 ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
1506 sort_by_cmp, (void *)ary));
1507 }
1508 if (RBASIC(ary)->klass) {
1509 rb_raise(rb_eRuntimeError, "sort_by reentered");
1510 }
1511 for (i=1; i<RARRAY_LEN(ary); i+=2) {
1512 RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
1513 }
1514 rb_ary_resize(ary, RARRAY_LEN(ary)/2);
1515 RBASIC_SET_CLASS_RAW(ary, rb_cArray);
1516
1517 return ary;
1518}
1519
1520#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
1521
1522#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
1523
1524#define DEFINE_ENUMFUNCS(name) \
1525static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
1526\
1527static VALUE \
1528name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1529{ \
1530 return enum_##name##_func(rb_enum_values_pack(argc, argv), MEMO_CAST(memo)); \
1531} \
1532\
1533static VALUE \
1534name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1535{ \
1536 return enum_##name##_func(rb_yield_values2(argc, argv), MEMO_CAST(memo)); \
1537} \
1538\
1539static VALUE \
1540name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1541{ \
1542 ENUM_WANT_SVALUE(); \
1543 return enum_##name##_func(rb_funcallv(MEMO_CAST(memo)->v2, id_eqq, 1, &i), MEMO_CAST(memo)); \
1544} \
1545\
1546static VALUE \
1547enum_##name##_func(VALUE result, struct MEMO *memo)
1548
1549#define WARN_UNUSED_BLOCK(argc) do { \
1550 if ((argc) > 0 && rb_block_given_p()) { \
1551 rb_warn("given block not used"); \
1552 } \
1553} while (0)
1554
1555DEFINE_ENUMFUNCS(all)
1556{
1557 if (!RTEST(result)) {
1558 MEMO_V1_SET(memo, Qfalse);
1559 rb_iter_break();
1560 }
1561 return Qnil;
1562}
1563
1564/*
1565 * call-seq:
1566 * all? -> true or false
1567 * all?(pattern) -> true or false
1568 * all? {|element| ... } -> true or false
1569 *
1570 * Returns whether every element meets a given criterion.
1571 *
1572 * With no argument and no block,
1573 * returns whether every element is truthy:
1574 *
1575 * (1..4).all? # => true
1576 * %w[a b c d].all? # => true
1577 * [1, 2, nil].all? # => false
1578 * ['a','b', false].all? # => false
1579 * [].all? # => true
1580 *
1581 * With argument +pattern+ and no block,
1582 * returns whether for each element +element+,
1583 * <tt>pattern === element</tt>:
1584 *
1585 * (1..4).all?(Integer) # => true
1586 * (1..4).all?(Numeric) # => true
1587 * (1..4).all?(Float) # => false
1588 * %w[bar baz bat bam].all?(/ba/) # => true
1589 * %w[bar baz bat bam].all?(/bar/) # => false
1590 * %w[bar baz bat bam].all?('ba') # => false
1591 * {foo: 0, bar: 1, baz: 2}.all?(Array) # => true
1592 * {foo: 0, bar: 1, baz: 2}.all?(Hash) # => false
1593 * [].all?(Integer) # => true
1594 *
1595 * With a block given, returns whether the block returns a truthy value
1596 * for every element:
1597 *
1598 * (1..4).all? {|element| element < 5 } # => true
1599 * (1..4).all? {|element| element < 4 } # => false
1600 * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 3 } # => true
1601 * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 2 } # => false
1602 *
1603 * Related: #any?, #none? #one?.
1604 *
1605 */
1606
1607static VALUE
1608enum_all(int argc, VALUE *argv, VALUE obj)
1609{
1610 struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
1611 WARN_UNUSED_BLOCK(argc);
1612 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1613 return memo->v1;
1614}
1615
1616DEFINE_ENUMFUNCS(any)
1617{
1618 if (RTEST(result)) {
1619 MEMO_V1_SET(memo, Qtrue);
1620 rb_iter_break();
1621 }
1622 return Qnil;
1623}
1624
1625/*
1626 * call-seq:
1627 * any? -> true or false
1628 * any?(pattern) -> true or false
1629 * any? {|element| ... } -> true or false
1630 *
1631 * Returns whether any element meets a given criterion.
1632 *
1633 * With no argument and no block,
1634 * returns whether any element is truthy:
1635 *
1636 * (1..4).any? # => true
1637 * %w[a b c d].any? # => true
1638 * [1, false, nil].any? # => true
1639 * [].any? # => false
1640 *
1641 * With argument +pattern+ and no block,
1642 * returns whether for any element +element+,
1643 * <tt>pattern === element</tt>:
1644 *
1645 * [nil, false, 0].any?(Integer) # => true
1646 * [nil, false, 0].any?(Numeric) # => true
1647 * [nil, false, 0].any?(Float) # => false
1648 * %w[bar baz bat bam].any?(/m/) # => true
1649 * %w[bar baz bat bam].any?(/foo/) # => false
1650 * %w[bar baz bat bam].any?('ba') # => false
1651 * {foo: 0, bar: 1, baz: 2}.any?(Array) # => true
1652 * {foo: 0, bar: 1, baz: 2}.any?(Hash) # => false
1653 * [].any?(Integer) # => false
1654 *
1655 * With a block given, returns whether the block returns a truthy value
1656 * for any element:
1657 *
1658 * (1..4).any? {|element| element < 2 } # => true
1659 * (1..4).any? {|element| element < 1 } # => false
1660 * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 1 } # => true
1661 * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 0 } # => false
1662 *
1663 *
1664 * Related: #all?, #none?, #one?.
1665 */
1666
1667static VALUE
1668enum_any(int argc, VALUE *argv, VALUE obj)
1669{
1670 struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
1671 WARN_UNUSED_BLOCK(argc);
1672 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1673 return memo->v1;
1674}
1675
1676DEFINE_ENUMFUNCS(one)
1677{
1678 if (RTEST(result)) {
1679 if (UNDEF_P(memo->v1)) {
1680 MEMO_V1_SET(memo, Qtrue);
1681 }
1682 else if (memo->v1 == Qtrue) {
1683 MEMO_V1_SET(memo, Qfalse);
1684 rb_iter_break();
1685 }
1686 }
1687 return Qnil;
1688}
1689
1691 long n;
1692 long bufmax;
1693 long curlen;
1694 VALUE buf;
1695 VALUE limit;
1696 int (*cmpfunc)(const void *, const void *, void *);
1697 int rev: 1; /* max if 1 */
1698 int by: 1; /* min_by if 1 */
1699};
1700
1701static VALUE
1702cmpint_reenter_check(struct nmin_data *data, VALUE val)
1703{
1704 if (RBASIC(data->buf)->klass) {
1705 rb_raise(rb_eRuntimeError, "%s%s reentered",
1706 data->rev ? "max" : "min",
1707 data->by ? "_by" : "");
1708 }
1709 return val;
1710}
1711
1712static int
1713nmin_cmp(const void *ap, const void *bp, void *_data)
1714{
1715 struct nmin_data *data = (struct nmin_data *)_data;
1716 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1717#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
1718 return OPTIMIZED_CMP(a, b);
1719#undef rb_cmpint
1720}
1721
1722static int
1723nmin_block_cmp(const void *ap, const void *bp, void *_data)
1724{
1725 struct nmin_data *data = (struct nmin_data *)_data;
1726 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1727 VALUE cmp = rb_yield_values(2, a, b);
1728 cmpint_reenter_check(data, cmp);
1729 return rb_cmpint(cmp, a, b);
1730}
1731
1732static void
1733nmin_filter(struct nmin_data *data)
1734{
1735 long n;
1736 VALUE *beg;
1737 int eltsize;
1738 long numelts;
1739
1740 long left, right;
1741 long store_index;
1742
1743 long i, j;
1744
1745 if (data->curlen <= data->n)
1746 return;
1747
1748 n = data->n;
1749 beg = RARRAY_PTR(data->buf);
1750 eltsize = data->by ? 2 : 1;
1751 numelts = data->curlen;
1752
1753 left = 0;
1754 right = numelts-1;
1755
1756#define GETPTR(i) (beg+(i)*eltsize)
1757
1758#define SWAP(i, j) do { \
1759 VALUE tmp[2]; \
1760 memcpy(tmp, GETPTR(i), sizeof(VALUE)*eltsize); \
1761 memcpy(GETPTR(i), GETPTR(j), sizeof(VALUE)*eltsize); \
1762 memcpy(GETPTR(j), tmp, sizeof(VALUE)*eltsize); \
1763} while (0)
1764
1765 while (1) {
1766 long pivot_index = left + (right-left)/2;
1767 long num_pivots = 1;
1768
1769 SWAP(pivot_index, right);
1770 pivot_index = right;
1771
1772 store_index = left;
1773 i = left;
1774 while (i <= right-num_pivots) {
1775 int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
1776 if (data->rev)
1777 c = -c;
1778 if (c == 0) {
1779 SWAP(i, right-num_pivots);
1780 num_pivots++;
1781 continue;
1782 }
1783 if (c < 0) {
1784 SWAP(i, store_index);
1785 store_index++;
1786 }
1787 i++;
1788 }
1789 j = store_index;
1790 for (i = right; right-num_pivots < i; i--) {
1791 if (i <= j)
1792 break;
1793 SWAP(j, i);
1794 j++;
1795 }
1796
1797 if (store_index <= n && n <= store_index+num_pivots)
1798 break;
1799
1800 if (n < store_index) {
1801 right = store_index-1;
1802 }
1803 else {
1804 left = store_index+num_pivots;
1805 }
1806 }
1807#undef GETPTR
1808#undef SWAP
1809
1810 data->limit = RARRAY_AREF(data->buf, store_index*eltsize); /* the last pivot */
1811 data->curlen = data->n;
1812 rb_ary_resize(data->buf, data->n * eltsize);
1813}
1814
1815static VALUE
1816nmin_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
1817{
1818 struct nmin_data *data = (struct nmin_data *)_data;
1819 VALUE cmpv;
1820
1821 ENUM_WANT_SVALUE();
1822
1823 if (data->by)
1824 cmpv = enum_yield(argc, i);
1825 else
1826 cmpv = i;
1827
1828 if (!UNDEF_P(data->limit)) {
1829 int c = data->cmpfunc(&cmpv, &data->limit, data);
1830 if (data->rev)
1831 c = -c;
1832 if (c >= 0)
1833 return Qnil;
1834 }
1835
1836 if (data->by)
1837 rb_ary_push(data->buf, cmpv);
1838 rb_ary_push(data->buf, i);
1839
1840 data->curlen++;
1841
1842 if (data->curlen == data->bufmax) {
1843 nmin_filter(data);
1844 }
1845
1846 return Qnil;
1847}
1848
1849VALUE
1850rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
1851{
1852 VALUE result;
1853 struct nmin_data data;
1854
1855 data.n = NUM2LONG(num);
1856 if (data.n < 0)
1857 rb_raise(rb_eArgError, "negative size (%ld)", data.n);
1858 if (data.n == 0)
1859 return rb_ary_new2(0);
1860 if (LONG_MAX/4/(by ? 2 : 1) < data.n)
1861 rb_raise(rb_eArgError, "too big size");
1862 data.bufmax = data.n * 4;
1863 data.curlen = 0;
1864 data.buf = rb_ary_hidden_new(data.bufmax * (by ? 2 : 1));
1865 data.limit = Qundef;
1866 data.cmpfunc = by ? nmin_cmp :
1867 rb_block_given_p() ? nmin_block_cmp :
1868 nmin_cmp;
1869 data.rev = rev;
1870 data.by = by;
1871 if (ary) {
1872 long i;
1873 for (i = 0; i < RARRAY_LEN(obj); i++) {
1874 VALUE args[1];
1875 args[0] = RARRAY_AREF(obj, i);
1876 nmin_i(obj, (VALUE)&data, 1, args, Qundef);
1877 }
1878 }
1879 else {
1880 rb_block_call(obj, id_each, 0, 0, nmin_i, (VALUE)&data);
1881 }
1882 nmin_filter(&data);
1883 result = data.buf;
1884 if (by) {
1885 long i;
1886 RARRAY_PTR_USE(result, ptr, {
1887 ruby_qsort(ptr,
1888 RARRAY_LEN(result)/2,
1889 sizeof(VALUE)*2,
1890 data.cmpfunc, (void *)&data);
1891 for (i=1; i<RARRAY_LEN(result); i+=2) {
1892 ptr[i/2] = ptr[i];
1893 }
1894 });
1895 rb_ary_resize(result, RARRAY_LEN(result)/2);
1896 }
1897 else {
1898 RARRAY_PTR_USE(result, ptr, {
1899 ruby_qsort(ptr, RARRAY_LEN(result), sizeof(VALUE),
1900 data.cmpfunc, (void *)&data);
1901 });
1902 }
1903 if (rev) {
1904 rb_ary_reverse(result);
1905 }
1906 RBASIC_SET_CLASS(result, rb_cArray);
1907 return result;
1908
1909}
1910
1911/*
1912 * call-seq:
1913 * one? -> true or false
1914 * one?(pattern) -> true or false
1915 * one? {|element| ... } -> true or false
1916 *
1917 * Returns whether exactly one element meets a given criterion.
1918 *
1919 * With no argument and no block,
1920 * returns whether exactly one element is truthy:
1921 *
1922 * (1..1).one? # => true
1923 * [1, nil, false].one? # => true
1924 * (1..4).one? # => false
1925 * {foo: 0}.one? # => true
1926 * {foo: 0, bar: 1}.one? # => false
1927 * [].one? # => false
1928 *
1929 * With argument +pattern+ and no block,
1930 * returns whether for exactly one element +element+,
1931 * <tt>pattern === element</tt>:
1932 *
1933 * [nil, false, 0].one?(Integer) # => true
1934 * [nil, false, 0].one?(Numeric) # => true
1935 * [nil, false, 0].one?(Float) # => false
1936 * %w[bar baz bat bam].one?(/m/) # => true
1937 * %w[bar baz bat bam].one?(/foo/) # => false
1938 * %w[bar baz bat bam].one?('ba') # => false
1939 * {foo: 0, bar: 1, baz: 2}.one?(Array) # => false
1940 * {foo: 0}.one?(Array) # => true
1941 * [].one?(Integer) # => false
1942 *
1943 * With a block given, returns whether the block returns a truthy value
1944 * for exactly one element:
1945 *
1946 * (1..4).one? {|element| element < 2 } # => true
1947 * (1..4).one? {|element| element < 1 } # => false
1948 * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 1 } # => true
1949 * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 2 } # => false
1950 *
1951 * Related: #none?, #all?, #any?.
1952 *
1953 */
1954static VALUE
1955enum_one(int argc, VALUE *argv, VALUE obj)
1956{
1957 struct MEMO *memo = MEMO_ENUM_NEW(Qundef);
1958 VALUE result;
1959
1960 WARN_UNUSED_BLOCK(argc);
1961 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1962 result = memo->v1;
1963 if (UNDEF_P(result)) return Qfalse;
1964 return result;
1965}
1966
1967DEFINE_ENUMFUNCS(none)
1968{
1969 if (RTEST(result)) {
1970 MEMO_V1_SET(memo, Qfalse);
1971 rb_iter_break();
1972 }
1973 return Qnil;
1974}
1975
1976/*
1977 * call-seq:
1978 * none? -> true or false
1979 * none?(pattern) -> true or false
1980 * none? {|element| ... } -> true or false
1981 *
1982 * Returns whether no element meets a given criterion.
1983 *
1984 * With no argument and no block,
1985 * returns whether no element is truthy:
1986 *
1987 * (1..4).none? # => false
1988 * [nil, false].none? # => true
1989 * {foo: 0}.none? # => false
1990 * {foo: 0, bar: 1}.none? # => false
1991 * [].none? # => true
1992 *
1993 * With argument +pattern+ and no block,
1994 * returns whether for no element +element+,
1995 * <tt>pattern === element</tt>:
1996 *
1997 * [nil, false, 1.1].none?(Integer) # => true
1998 * %w[bar baz bat bam].none?(/m/) # => false
1999 * %w[bar baz bat bam].none?(/foo/) # => true
2000 * %w[bar baz bat bam].none?('ba') # => true
2001 * {foo: 0, bar: 1, baz: 2}.none?(Hash) # => true
2002 * {foo: 0}.none?(Array) # => false
2003 * [].none?(Integer) # => true
2004 *
2005 * With a block given, returns whether the block returns a truthy value
2006 * for no element:
2007 *
2008 * (1..4).none? {|element| element < 1 } # => true
2009 * (1..4).none? {|element| element < 2 } # => false
2010 * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 0 } # => true
2011 * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 1 } # => false
2012 *
2013 * Related: #one?, #all?, #any?.
2014 *
2015 */
2016static VALUE
2017enum_none(int argc, VALUE *argv, VALUE obj)
2018{
2019 struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
2020
2021 WARN_UNUSED_BLOCK(argc);
2022 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
2023 return memo->v1;
2024}
2025
2026struct min_t {
2027 VALUE min;
2028};
2029
2030static VALUE
2031min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2032{
2033 struct min_t *memo = MEMO_FOR(struct min_t, args);
2034
2035 ENUM_WANT_SVALUE();
2036
2037 if (UNDEF_P(memo->min)) {
2038 memo->min = i;
2039 }
2040 else {
2041 if (OPTIMIZED_CMP(i, memo->min) < 0) {
2042 memo->min = i;
2043 }
2044 }
2045 return Qnil;
2046}
2047
2048static VALUE
2049min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2050{
2051 VALUE cmp;
2052 struct min_t *memo = MEMO_FOR(struct min_t, args);
2053
2054 ENUM_WANT_SVALUE();
2055
2056 if (UNDEF_P(memo->min)) {
2057 memo->min = i;
2058 }
2059 else {
2060 cmp = rb_yield_values(2, i, memo->min);
2061 if (rb_cmpint(cmp, i, memo->min) < 0) {
2062 memo->min = i;
2063 }
2064 }
2065 return Qnil;
2066}
2067
2068
2069/*
2070 * call-seq:
2071 * min -> element
2072 * min(n) -> array
2073 * min {|a, b| ... } -> element
2074 * min(n) {|a, b| ... } -> array
2075 *
2076 * Returns the element with the minimum element according to a given criterion.
2077 * The ordering of equal elements is indeterminate and may be unstable.
2078 *
2079 * With no argument and no block, returns the minimum element,
2080 * using the elements' own method <tt><=></tt> for comparison:
2081 *
2082 * (1..4).min # => 1
2083 * (-4..-1).min # => -4
2084 * %w[d c b a].min # => "a"
2085 * {foo: 0, bar: 1, baz: 2}.min # => [:bar, 1]
2086 * [].min # => nil
2087 *
2088 * With positive integer argument +n+ given, and no block,
2089 * returns an array containing the first +n+ minimum elements that exist:
2090 *
2091 * (1..4).min(2) # => [1, 2]
2092 * (-4..-1).min(2) # => [-4, -3]
2093 * %w[d c b a].min(2) # => ["a", "b"]
2094 * {foo: 0, bar: 1, baz: 2}.min(2) # => [[:bar, 1], [:baz, 2]]
2095 * [].min(2) # => []
2096 *
2097 * With a block given, the block determines the minimum elements.
2098 * The block is called with two elements +a+ and +b+, and must return:
2099 *
2100 * - A negative integer if <tt>a < b</tt>.
2101 * - Zero if <tt>a == b</tt>.
2102 * - A positive integer if <tt>a > b</tt>.
2103 *
2104 * With a block given and no argument,
2105 * returns the minimum element as determined by the block:
2106 *
2107 * %w[xxx x xxxx xx].min {|a, b| a.size <=> b.size } # => "x"
2108 * h = {foo: 0, bar: 1, baz: 2}
2109 * h.min {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:foo, 0]
2110 * [].min {|a, b| a <=> b } # => nil
2111 *
2112 * With a block given and positive integer argument +n+ given,
2113 * returns an array containing the first +n+ minimum elements that exist,
2114 * as determined by the block.
2115 *
2116 * %w[xxx x xxxx xx].min(2) {|a, b| a.size <=> b.size } # => ["x", "xx"]
2117 * h = {foo: 0, bar: 1, baz: 2}
2118 * h.min(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
2119 * # => [[:foo, 0], [:bar, 1]]
2120 * [].min(2) {|a, b| a <=> b } # => []
2121 *
2122 * Related: #min_by, #minmax, #max.
2123 *
2124 */
2125
2126static VALUE
2127enum_min(int argc, VALUE *argv, VALUE obj)
2128{
2129 VALUE memo;
2130 struct min_t *m = NEW_MEMO_FOR(struct min_t, memo);
2131 VALUE result;
2132 VALUE num;
2133
2134 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
2135 return rb_nmin_run(obj, num, 0, 0, 0);
2136
2137 m->min = Qundef;
2138 if (rb_block_given_p()) {
2139 rb_block_call(obj, id_each, 0, 0, min_ii, memo);
2140 }
2141 else {
2142 rb_block_call(obj, id_each, 0, 0, min_i, memo);
2143 }
2144 result = m->min;
2145 if (UNDEF_P(result)) return Qnil;
2146 return result;
2147}
2148
2149struct max_t {
2150 VALUE max;
2151};
2152
2153static VALUE
2154max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2155{
2156 struct max_t *memo = MEMO_FOR(struct max_t, args);
2157
2158 ENUM_WANT_SVALUE();
2159
2160 if (UNDEF_P(memo->max)) {
2161 memo->max = i;
2162 }
2163 else {
2164 if (OPTIMIZED_CMP(i, memo->max) > 0) {
2165 memo->max = i;
2166 }
2167 }
2168 return Qnil;
2169}
2170
2171static VALUE
2172max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2173{
2174 struct max_t *memo = MEMO_FOR(struct max_t, args);
2175 VALUE cmp;
2176
2177 ENUM_WANT_SVALUE();
2178
2179 if (UNDEF_P(memo->max)) {
2180 memo->max = i;
2181 }
2182 else {
2183 cmp = rb_yield_values(2, i, memo->max);
2184 if (rb_cmpint(cmp, i, memo->max) > 0) {
2185 memo->max = i;
2186 }
2187 }
2188 return Qnil;
2189}
2190
2191/*
2192 * call-seq:
2193 * max -> element
2194 * max(n) -> array
2195 * max {|a, b| ... } -> element
2196 * max(n) {|a, b| ... } -> array
2197 *
2198 * Returns the element with the maximum element according to a given criterion.
2199 * The ordering of equal elements is indeterminate and may be unstable.
2200 *
2201 * With no argument and no block, returns the maximum element,
2202 * using the elements' own method <tt><=></tt> for comparison:
2203 *
2204 * (1..4).max # => 4
2205 * (-4..-1).max # => -1
2206 * %w[d c b a].max # => "d"
2207 * {foo: 0, bar: 1, baz: 2}.max # => [:foo, 0]
2208 * [].max # => nil
2209 *
2210 * With positive integer argument +n+ given, and no block,
2211 * returns an array containing the first +n+ maximum elements that exist:
2212 *
2213 * (1..4).max(2) # => [4, 3]
2214 * (-4..-1).max(2) # => [-1, -2]
2215 * %w[d c b a].max(2) # => ["d", "c"]
2216 * {foo: 0, bar: 1, baz: 2}.max(2) # => [[:foo, 0], [:baz, 2]]
2217 * [].max(2) # => []
2218 *
2219 * With a block given, the block determines the maximum elements.
2220 * The block is called with two elements +a+ and +b+, and must return:
2221 *
2222 * - A negative integer if <tt>a < b</tt>.
2223 * - Zero if <tt>a == b</tt>.
2224 * - A positive integer if <tt>a > b</tt>.
2225 *
2226 * With a block given and no argument,
2227 * returns the maximum element as determined by the block:
2228 *
2229 * %w[xxx x xxxx xx].max {|a, b| a.size <=> b.size } # => "xxxx"
2230 * h = {foo: 0, bar: 1, baz: 2}
2231 * h.max {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:baz, 2]
2232 * [].max {|a, b| a <=> b } # => nil
2233 *
2234 * With a block given and positive integer argument +n+ given,
2235 * returns an array containing the first +n+ maximum elements that exist,
2236 * as determined by the block.
2237 *
2238 * %w[xxx x xxxx xx].max(2) {|a, b| a.size <=> b.size } # => ["xxxx", "xxx"]
2239 * h = {foo: 0, bar: 1, baz: 2}
2240 * h.max(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
2241 * # => [[:baz, 2], [:bar, 1]]
2242 * [].max(2) {|a, b| a <=> b } # => []
2243 *
2244 * Related: #min, #minmax, #max_by.
2245 *
2246 */
2247
2248static VALUE
2249enum_max(int argc, VALUE *argv, VALUE obj)
2250{
2251 VALUE memo;
2252 struct max_t *m = NEW_MEMO_FOR(struct max_t, memo);
2253 VALUE result;
2254 VALUE num;
2255
2256 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
2257 return rb_nmin_run(obj, num, 0, 1, 0);
2258
2259 m->max = Qundef;
2260 if (rb_block_given_p()) {
2261 rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
2262 }
2263 else {
2264 rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
2265 }
2266 result = m->max;
2267 if (UNDEF_P(result)) return Qnil;
2268 return result;
2269}
2270
2271struct minmax_t {
2272 VALUE min;
2273 VALUE max;
2274 VALUE last;
2275};
2276
2277static void
2278minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
2279{
2280 int n;
2281
2282 if (UNDEF_P(memo->min)) {
2283 memo->min = i;
2284 memo->max = j;
2285 }
2286 else {
2287 n = OPTIMIZED_CMP(i, memo->min);
2288 if (n < 0) {
2289 memo->min = i;
2290 }
2291 n = OPTIMIZED_CMP(j, memo->max);
2292 if (n > 0) {
2293 memo->max = j;
2294 }
2295 }
2296}
2297
2298static VALUE
2299minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2300{
2301 struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
2302 int n;
2303 VALUE j;
2304
2305 ENUM_WANT_SVALUE();
2306
2307 if (UNDEF_P(memo->last)) {
2308 memo->last = i;
2309 return Qnil;
2310 }
2311 j = memo->last;
2312 memo->last = Qundef;
2313
2314 n = OPTIMIZED_CMP(j, i);
2315 if (n == 0)
2316 i = j;
2317 else if (n < 0) {
2318 VALUE tmp;
2319 tmp = i;
2320 i = j;
2321 j = tmp;
2322 }
2323
2324 minmax_i_update(i, j, memo);
2325
2326 return Qnil;
2327}
2328
2329static void
2330minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
2331{
2332 int n;
2333
2334 if (UNDEF_P(memo->min)) {
2335 memo->min = i;
2336 memo->max = j;
2337 }
2338 else {
2339 n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
2340 if (n < 0) {
2341 memo->min = i;
2342 }
2343 n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
2344 if (n > 0) {
2345 memo->max = j;
2346 }
2347 }
2348}
2349
2350static VALUE
2351minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2352{
2353 struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
2354 int n;
2355 VALUE j;
2356
2357 ENUM_WANT_SVALUE();
2358
2359 if (UNDEF_P(memo->last)) {
2360 memo->last = i;
2361 return Qnil;
2362 }
2363 j = memo->last;
2364 memo->last = Qundef;
2365
2366 n = rb_cmpint(rb_yield_values(2, j, i), j, i);
2367 if (n == 0)
2368 i = j;
2369 else if (n < 0) {
2370 VALUE tmp;
2371 tmp = i;
2372 i = j;
2373 j = tmp;
2374 }
2375
2376 minmax_ii_update(i, j, memo);
2377
2378 return Qnil;
2379}
2380
2381/*
2382 * call-seq:
2383 * minmax -> [minimum, maximum]
2384 * minmax {|a, b| ... } -> [minimum, maximum]
2385 *
2386 * Returns a 2-element array containing the minimum and maximum elements
2387 * according to a given criterion.
2388 * The ordering of equal elements is indeterminate and may be unstable.
2389 *
2390 * With no argument and no block, returns the minimum and maximum elements,
2391 * using the elements' own method <tt><=></tt> for comparison:
2392 *
2393 * (1..4).minmax # => [1, 4]
2394 * (-4..-1).minmax # => [-4, -1]
2395 * %w[d c b a].minmax # => ["a", "d"]
2396 * {foo: 0, bar: 1, baz: 2}.minmax # => [[:bar, 1], [:foo, 0]]
2397 * [].minmax # => [nil, nil]
2398 *
2399 * With a block given, returns the minimum and maximum elements
2400 * as determined by the block:
2401 *
2402 * %w[xxx x xxxx xx].minmax {|a, b| a.size <=> b.size } # => ["x", "xxxx"]
2403 * h = {foo: 0, bar: 1, baz: 2}
2404 * h.minmax {|pair1, pair2| pair1[1] <=> pair2[1] }
2405 * # => [[:foo, 0], [:baz, 2]]
2406 * [].minmax {|a, b| a <=> b } # => [nil, nil]
2407 *
2408 * Related: #min, #max, #minmax_by.
2409 *
2410 */
2411
2412static VALUE
2413enum_minmax(VALUE obj)
2414{
2415 VALUE memo;
2416 struct minmax_t *m = NEW_MEMO_FOR(struct minmax_t, memo);
2417
2418 m->min = Qundef;
2419 m->last = Qundef;
2420 if (rb_block_given_p()) {
2421 rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
2422 if (!UNDEF_P(m->last))
2423 minmax_ii_update(m->last, m->last, m);
2424 }
2425 else {
2426 rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
2427 if (!UNDEF_P(m->last))
2428 minmax_i_update(m->last, m->last, m);
2429 }
2430 if (!UNDEF_P(m->min)) {
2431 return rb_assoc_new(m->min, m->max);
2432 }
2433 return rb_assoc_new(Qnil, Qnil);
2434}
2435
2436static VALUE
2437min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2438{
2439 struct MEMO *memo = MEMO_CAST(args);
2440 VALUE v;
2441
2442 ENUM_WANT_SVALUE();
2443
2444 v = enum_yield(argc, i);
2445 if (UNDEF_P(memo->v1)) {
2446 MEMO_V1_SET(memo, v);
2447 MEMO_V2_SET(memo, i);
2448 }
2449 else if (OPTIMIZED_CMP(v, memo->v1) < 0) {
2450 MEMO_V1_SET(memo, v);
2451 MEMO_V2_SET(memo, i);
2452 }
2453 return Qnil;
2454}
2455
2456/*
2457 * call-seq:
2458 * min_by {|element| ... } -> element
2459 * min_by(n) {|element| ... } -> array
2460 * min_by -> enumerator
2461 * min_by(n) -> enumerator
2462 *
2463 * Returns the elements for which the block returns the minimum values.
2464 *
2465 * With a block given and no argument,
2466 * returns the element for which the block returns the minimum value:
2467 *
2468 * (1..4).min_by {|element| -element } # => 4
2469 * %w[a b c d].min_by {|element| -element.ord } # => "d"
2470 * {foo: 0, bar: 1, baz: 2}.min_by {|key, value| -value } # => [:baz, 2]
2471 * [].min_by {|element| -element } # => nil
2472 *
2473 * With a block given and positive integer argument +n+ given,
2474 * returns an array containing the +n+ elements
2475 * for which the block returns minimum values:
2476 *
2477 * (1..4).min_by(2) {|element| -element }
2478 * # => [4, 3]
2479 * %w[a b c d].min_by(2) {|element| -element.ord }
2480 * # => ["d", "c"]
2481 * {foo: 0, bar: 1, baz: 2}.min_by(2) {|key, value| -value }
2482 * # => [[:baz, 2], [:bar, 1]]
2483 * [].min_by(2) {|element| -element }
2484 * # => []
2485 *
2486 * Returns an Enumerator if no block is given.
2487 *
2488 * Related: #min, #minmax, #max_by.
2489 *
2490 */
2491
2492static VALUE
2493enum_min_by(int argc, VALUE *argv, VALUE obj)
2494{
2495 struct MEMO *memo;
2496 VALUE num;
2497
2498 rb_check_arity(argc, 0, 1);
2499
2500 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2501
2502 if (argc && !NIL_P(num = argv[0]))
2503 return rb_nmin_run(obj, num, 1, 0, 0);
2504
2505 memo = MEMO_NEW(Qundef, Qnil, 0);
2506 rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
2507 return memo->v2;
2508}
2509
2510static VALUE
2511max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2512{
2513 struct MEMO *memo = MEMO_CAST(args);
2514 VALUE v;
2515
2516 ENUM_WANT_SVALUE();
2517
2518 v = enum_yield(argc, i);
2519 if (UNDEF_P(memo->v1)) {
2520 MEMO_V1_SET(memo, v);
2521 MEMO_V2_SET(memo, i);
2522 }
2523 else if (OPTIMIZED_CMP(v, memo->v1) > 0) {
2524 MEMO_V1_SET(memo, v);
2525 MEMO_V2_SET(memo, i);
2526 }
2527 return Qnil;
2528}
2529
2530/*
2531 * call-seq:
2532 * max_by {|element| ... } -> element
2533 * max_by(n) {|element| ... } -> array
2534 * max_by -> enumerator
2535 * max_by(n) -> enumerator
2536 *
2537 * Returns the elements for which the block returns the maximum values.
2538 *
2539 * With a block given and no argument,
2540 * returns the element for which the block returns the maximum value:
2541 *
2542 * (1..4).max_by {|element| -element } # => 1
2543 * %w[a b c d].max_by {|element| -element.ord } # => "a"
2544 * {foo: 0, bar: 1, baz: 2}.max_by {|key, value| -value } # => [:foo, 0]
2545 * [].max_by {|element| -element } # => nil
2546 *
2547 * With a block given and positive integer argument +n+ given,
2548 * returns an array containing the +n+ elements
2549 * for which the block returns maximum values:
2550 *
2551 * (1..4).max_by(2) {|element| -element }
2552 * # => [1, 2]
2553 * %w[a b c d].max_by(2) {|element| -element.ord }
2554 * # => ["a", "b"]
2555 * {foo: 0, bar: 1, baz: 2}.max_by(2) {|key, value| -value }
2556 * # => [[:foo, 0], [:bar, 1]]
2557 * [].max_by(2) {|element| -element }
2558 * # => []
2559 *
2560 * Returns an Enumerator if no block is given.
2561 *
2562 * Related: #max, #minmax, #min_by.
2563 *
2564 */
2565
2566static VALUE
2567enum_max_by(int argc, VALUE *argv, VALUE obj)
2568{
2569 struct MEMO *memo;
2570 VALUE num;
2571
2572 rb_check_arity(argc, 0, 1);
2573
2574 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2575
2576 if (argc && !NIL_P(num = argv[0]))
2577 return rb_nmin_run(obj, num, 1, 1, 0);
2578
2579 memo = MEMO_NEW(Qundef, Qnil, 0);
2580 rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
2581 return memo->v2;
2582}
2583
2585 VALUE min_bv;
2586 VALUE max_bv;
2587 VALUE min;
2588 VALUE max;
2589 VALUE last_bv;
2590 VALUE last;
2591};
2592
2593static void
2594minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
2595{
2596 if (UNDEF_P(memo->min_bv)) {
2597 memo->min_bv = v1;
2598 memo->max_bv = v2;
2599 memo->min = i1;
2600 memo->max = i2;
2601 }
2602 else {
2603 if (OPTIMIZED_CMP(v1, memo->min_bv) < 0) {
2604 memo->min_bv = v1;
2605 memo->min = i1;
2606 }
2607 if (OPTIMIZED_CMP(v2, memo->max_bv) > 0) {
2608 memo->max_bv = v2;
2609 memo->max = i2;
2610 }
2611 }
2612}
2613
2614static VALUE
2615minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2616{
2617 struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
2618 VALUE vi, vj, j;
2619 int n;
2620
2621 ENUM_WANT_SVALUE();
2622
2623 vi = enum_yield(argc, i);
2624
2625 if (UNDEF_P(memo->last_bv)) {
2626 memo->last_bv = vi;
2627 memo->last = i;
2628 return Qnil;
2629 }
2630 vj = memo->last_bv;
2631 j = memo->last;
2632 memo->last_bv = Qundef;
2633
2634 n = OPTIMIZED_CMP(vj, vi);
2635 if (n == 0) {
2636 i = j;
2637 vi = vj;
2638 }
2639 else if (n < 0) {
2640 VALUE tmp;
2641 tmp = i;
2642 i = j;
2643 j = tmp;
2644 tmp = vi;
2645 vi = vj;
2646 vj = tmp;
2647 }
2648
2649 minmax_by_i_update(vi, vj, i, j, memo);
2650
2651 return Qnil;
2652}
2653
2654/*
2655 * call-seq:
2656 * minmax_by {|element| ... } -> [minimum, maximum]
2657 * minmax_by -> enumerator
2658 *
2659 * Returns a 2-element array containing the elements
2660 * for which the block returns minimum and maximum values:
2661 *
2662 * (1..4).minmax_by {|element| -element }
2663 * # => [4, 1]
2664 * %w[a b c d].minmax_by {|element| -element.ord }
2665 * # => ["d", "a"]
2666 * {foo: 0, bar: 1, baz: 2}.minmax_by {|key, value| -value }
2667 * # => [[:baz, 2], [:foo, 0]]
2668 * [].minmax_by {|element| -element }
2669 * # => [nil, nil]
2670 *
2671 * Returns an Enumerator if no block is given.
2672 *
2673 * Related: #max_by, #minmax, #min_by.
2674 *
2675 */
2676
2677static VALUE
2678enum_minmax_by(VALUE obj)
2679{
2680 VALUE memo;
2681 struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
2682
2683 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
2684
2685 m->min_bv = Qundef;
2686 m->max_bv = Qundef;
2687 m->min = Qnil;
2688 m->max = Qnil;
2689 m->last_bv = Qundef;
2690 m->last = Qundef;
2691 rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
2692 if (!UNDEF_P(m->last_bv))
2693 minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
2694 m = MEMO_FOR(struct minmax_by_t, memo);
2695 return rb_assoc_new(m->min, m->max);
2696}
2697
2698static VALUE
2699member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
2700{
2701 struct MEMO *memo = MEMO_CAST(args);
2702
2703 if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
2704 MEMO_V2_SET(memo, Qtrue);
2705 rb_iter_break();
2706 }
2707 return Qnil;
2708}
2709
2710/*
2711 * call-seq:
2712 * include?(object) -> true or false
2713 *
2714 * Returns whether for any element <tt>object == element</tt>:
2715 *
2716 * (1..4).include?(2) # => true
2717 * (1..4).include?(5) # => false
2718 * (1..4).include?('2') # => false
2719 * %w[a b c d].include?('b') # => true
2720 * %w[a b c d].include?('2') # => false
2721 * {foo: 0, bar: 1, baz: 2}.include?(:foo) # => true
2722 * {foo: 0, bar: 1, baz: 2}.include?('foo') # => false
2723 * {foo: 0, bar: 1, baz: 2}.include?(0) # => false
2724 *
2725 * Enumerable#member? is an alias for Enumerable#include?.
2726 *
2727 */
2728
2729static VALUE
2730enum_member(VALUE obj, VALUE val)
2731{
2732 struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
2733
2734 rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
2735 return memo->v2;
2736}
2737
2738static VALUE
2739each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
2740{
2741 struct MEMO *m = MEMO_CAST(memo);
2742 VALUE n = imemo_count_value(m);
2743
2744 imemo_count_up(m);
2745 return rb_yield_values(2, rb_enum_values_pack(argc, argv), n);
2746}
2747
2748/*
2749 * call-seq:
2750 * each_with_index(*args) {|element, i| ..... } -> self
2751 * each_with_index(*args) -> enumerator
2752 *
2753 * With a block given, calls the block with each element and its index;
2754 * returns +self+:
2755 *
2756 * h = {}
2757 * (1..4).each_with_index {|element, i| h[element] = i } # => 1..4
2758 * h # => {1=>0, 2=>1, 3=>2, 4=>3}
2759 *
2760 * h = {}
2761 * %w[a b c d].each_with_index {|element, i| h[element] = i }
2762 * # => ["a", "b", "c", "d"]
2763 * h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3}
2764 *
2765 * a = []
2766 * h = {foo: 0, bar: 1, baz: 2}
2767 * h.each_with_index {|element, i| a.push([i, element]) }
2768 * # => {:foo=>0, :bar=>1, :baz=>2}
2769 * a # => [[0, [:foo, 0]], [1, [:bar, 1]], [2, [:baz, 2]]]
2770 *
2771 * With no block given, returns an Enumerator.
2772 *
2773 */
2774
2775static VALUE
2776enum_each_with_index(int argc, VALUE *argv, VALUE obj)
2777{
2778 struct MEMO *memo;
2779
2780 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2781
2782 memo = MEMO_NEW(0, 0, 0);
2783 rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
2784 return obj;
2785}
2786
2787
2788/*
2789 * call-seq:
2790 * reverse_each(*args) {|element| ... } -> self
2791 * reverse_each(*args) -> enumerator
2792 *
2793 * With a block given, calls the block with each element,
2794 * but in reverse order; returns +self+:
2795 *
2796 * a = []
2797 * (1..4).reverse_each {|element| a.push(-element) } # => 1..4
2798 * a # => [-4, -3, -2, -1]
2799 *
2800 * a = []
2801 * %w[a b c d].reverse_each {|element| a.push(element) }
2802 * # => ["a", "b", "c", "d"]
2803 * a # => ["d", "c", "b", "a"]
2804 *
2805 * a = []
2806 * h.reverse_each {|element| a.push(element) }
2807 * # => {:foo=>0, :bar=>1, :baz=>2}
2808 * a # => [[:baz, 2], [:bar, 1], [:foo, 0]]
2809 *
2810 * With no block given, returns an Enumerator.
2811 *
2812 */
2813
2814static VALUE
2815enum_reverse_each(int argc, VALUE *argv, VALUE obj)
2816{
2817 VALUE ary;
2818 long len;
2819
2820 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2821
2822 ary = enum_to_a(argc, argv, obj);
2823
2824 len = RARRAY_LEN(ary);
2825 while (len--) {
2826 long nlen;
2827 rb_yield(RARRAY_AREF(ary, len));
2828 nlen = RARRAY_LEN(ary);
2829 if (nlen < len) {
2830 len = nlen;
2831 }
2832 }
2833
2834 return obj;
2835}
2836
2837
2838static VALUE
2839each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
2840{
2841 ENUM_WANT_SVALUE();
2842 enum_yield(argc, i);
2843 return Qnil;
2844}
2845
2846/*
2847 * call-seq:
2848 * each_entry(*args) {|element| ... } -> self
2849 * each_entry(*args) -> enumerator
2850 *
2851 * Calls the given block with each element,
2852 * converting multiple values from yield to an array; returns +self+:
2853 *
2854 * a = []
2855 * (1..4).each_entry {|element| a.push(element) } # => 1..4
2856 * a # => [1, 2, 3, 4]
2857 *
2858 * a = []
2859 * h = {foo: 0, bar: 1, baz:2}
2860 * h.each_entry {|element| a.push(element) }
2861 * # => {:foo=>0, :bar=>1, :baz=>2}
2862 * a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
2863 *
2864 * class Foo
2865 * include Enumerable
2866 * def each
2867 * yield 1
2868 * yield 1, 2
2869 * yield
2870 * end
2871 * end
2872 * Foo.new.each_entry {|yielded| p yielded }
2873 *
2874 * Output:
2875 *
2876 * 1
2877 * [1, 2]
2878 * nil
2879 *
2880 * With no block given, returns an Enumerator.
2881 *
2882 */
2883
2884static VALUE
2885enum_each_entry(int argc, VALUE *argv, VALUE obj)
2886{
2887 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2888 rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
2889 return obj;
2890}
2891
2892static VALUE
2893add_int(VALUE x, long n)
2894{
2895 const VALUE y = LONG2NUM(n);
2896 if (RB_INTEGER_TYPE_P(x)) return rb_int_plus(x, y);
2897 return rb_funcallv(x, '+', 1, &y);
2898}
2899
2900static VALUE
2901div_int(VALUE x, long n)
2902{
2903 const VALUE y = LONG2NUM(n);
2904 if (RB_INTEGER_TYPE_P(x)) return rb_int_idiv(x, y);
2905 return rb_funcallv(x, id_div, 1, &y);
2906}
2907
2908#define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) < 0)
2909
2910static VALUE
2911each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
2912{
2913 struct MEMO *memo = MEMO_CAST(m);
2914 VALUE ary = memo->v1;
2915 VALUE v = Qnil;
2916 long size = memo->u3.cnt;
2917 ENUM_WANT_SVALUE();
2918
2919 rb_ary_push(ary, i);
2920
2921 if (RARRAY_LEN(ary) == size) {
2922 v = rb_yield(ary);
2923
2924 if (memo->v2) {
2925 MEMO_V1_SET(memo, rb_ary_new2(size));
2926 }
2927 else {
2928 rb_ary_clear(ary);
2929 }
2930 }
2931
2932 return v;
2933}
2934
2935static VALUE
2936enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
2937{
2938 VALUE n, size;
2939 long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
2940 ID infinite_p;
2941 CONST_ID(infinite_p, "infinite?");
2942 if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
2943
2944 size = enum_size(obj, 0, 0);
2945 if (NIL_P(size)) return Qnil;
2946 if (RB_FLOAT_TYPE_P(size) && RTEST(rb_funcall(size, infinite_p, 0))) {
2947 return size;
2948 }
2949
2950 n = add_int(size, slice_size-1);
2951 return div_int(n, slice_size);
2952}
2953
2954/*
2955 * call-seq:
2956 * each_slice(n) { ... } -> self
2957 * each_slice(n) -> enumerator
2958 *
2959 * Calls the block with each successive disjoint +n+-tuple of elements;
2960 * returns +self+:
2961 *
2962 * a = []
2963 * (1..10).each_slice(3) {|tuple| a.push(tuple) }
2964 * a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
2965 *
2966 * a = []
2967 * h = {foo: 0, bar: 1, baz: 2, bat: 3, bam: 4}
2968 * h.each_slice(2) {|tuple| a.push(tuple) }
2969 * a # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]], [[:bam, 4]]]
2970 *
2971 * With no block given, returns an Enumerator.
2972 *
2973 */
2974static VALUE
2975enum_each_slice(VALUE obj, VALUE n)
2976{
2977 long size = NUM2LONG(n);
2978 VALUE ary;
2979 struct MEMO *memo;
2980 int arity;
2981
2982 if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
2983 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
2984 size = limit_by_enum_size(obj, size);
2985 ary = rb_ary_new2(size);
2986 arity = rb_block_arity();
2987 memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
2988 rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
2989 ary = memo->v1;
2990 if (RARRAY_LEN(ary) > 0) rb_yield(ary);
2991
2992 return obj;
2993}
2994
2995static VALUE
2996each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2997{
2998 struct MEMO *memo = MEMO_CAST(args);
2999 VALUE ary = memo->v1;
3000 VALUE v = Qnil;
3001 long size = memo->u3.cnt;
3002 ENUM_WANT_SVALUE();
3003
3004 if (RARRAY_LEN(ary) == size) {
3005 rb_ary_shift(ary);
3006 }
3007 rb_ary_push(ary, i);
3008 if (RARRAY_LEN(ary) == size) {
3009 if (memo->v2) {
3010 ary = rb_ary_dup(ary);
3011 }
3012 v = rb_yield(ary);
3013 }
3014 return v;
3015}
3016
3017static VALUE
3018enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
3019{
3020 const VALUE zero = LONG2FIX(0);
3021 VALUE n, size;
3022 long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
3023 if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
3024
3025 size = enum_size(obj, 0, 0);
3026 if (NIL_P(size)) return Qnil;
3027
3028 n = add_int(size, 1 - cons_size);
3029 return (OPTIMIZED_CMP(n, zero) == -1) ? zero : n;
3030}
3031
3032/*
3033 * call-seq:
3034 * each_cons(n) { ... } -> self
3035 * each_cons(n) -> enumerator
3036 *
3037 * Calls the block with each successive overlapped +n+-tuple of elements;
3038 * returns +self+:
3039 *
3040 * a = []
3041 * (1..5).each_cons(3) {|element| a.push(element) }
3042 * a # => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
3043 *
3044 * a = []
3045 * h = {foo: 0, bar: 1, baz: 2, bam: 3}
3046 * h.each_cons(2) {|element| a.push(element) }
3047 * a # => [[[:foo, 0], [:bar, 1]], [[:bar, 1], [:baz, 2]], [[:baz, 2], [:bam, 3]]]
3048 *
3049 * With no block given, returns an Enumerator.
3050 *
3051 */
3052static VALUE
3053enum_each_cons(VALUE obj, VALUE n)
3054{
3055 long size = NUM2LONG(n);
3056 struct MEMO *memo;
3057 int arity;
3058
3059 if (size <= 0) rb_raise(rb_eArgError, "invalid size");
3060 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
3061 arity = rb_block_arity();
3062 if (enum_size_over_p(obj, size)) return obj;
3063 memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
3064 rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
3065
3066 return obj;
3067}
3068
3069static VALUE
3070each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
3071{
3072 ENUM_WANT_SVALUE();
3073 return rb_yield_values(2, i, memo);
3074}
3075
3076/*
3077 * call-seq:
3078 * each_with_object(object) { |(*args), memo_object| ... } -> object
3079 * each_with_object(object) -> enumerator
3080 *
3081 * Calls the block once for each element, passing both the element
3082 * and the given object:
3083 *
3084 * (1..4).each_with_object([]) {|i, a| a.push(i**2) }
3085 * # => [1, 4, 9, 16]
3086 *
3087 * {foo: 0, bar: 1, baz: 2}.each_with_object({}) {|(k, v), h| h[v] = k }
3088 * # => {0=>:foo, 1=>:bar, 2=>:baz}
3089 *
3090 * With no block given, returns an Enumerator.
3091 *
3092 */
3093static VALUE
3094enum_each_with_object(VALUE obj, VALUE memo)
3095{
3096 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
3097
3098 rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
3099
3100 return memo;
3101}
3102
3103static VALUE
3104zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
3105{
3106 struct MEMO *memo = (struct MEMO *)memoval;
3107 VALUE result = memo->v1;
3108 VALUE args = memo->v2;
3109 long n = memo->u3.cnt++;
3110 VALUE tmp;
3111 int i;
3112
3113 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
3114 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
3115 for (i=0; i<RARRAY_LEN(args); i++) {
3116 VALUE e = RARRAY_AREF(args, i);
3117
3118 if (RARRAY_LEN(e) <= n) {
3119 rb_ary_push(tmp, Qnil);
3120 }
3121 else {
3122 rb_ary_push(tmp, RARRAY_AREF(e, n));
3123 }
3124 }
3125 if (NIL_P(result)) {
3126 enum_yield_array(tmp);
3127 }
3128 else {
3129 rb_ary_push(result, tmp);
3130 }
3131
3132 RB_GC_GUARD(args);
3133
3134 return Qnil;
3135}
3136
3137static VALUE
3138call_next(VALUE w)
3139{
3140 VALUE *v = (VALUE *)w;
3141 return v[0] = rb_funcallv(v[1], id_next, 0, 0);
3142}
3143
3144static VALUE
3145call_stop(VALUE w, VALUE _)
3146{
3147 VALUE *v = (VALUE *)w;
3148 return v[0] = Qundef;
3149}
3150
3151static VALUE
3152zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
3153{
3154 struct MEMO *memo = (struct MEMO *)memoval;
3155 VALUE result = memo->v1;
3156 VALUE args = memo->v2;
3157 VALUE tmp;
3158 int i;
3159
3160 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
3161 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
3162 for (i=0; i<RARRAY_LEN(args); i++) {
3163 if (NIL_P(RARRAY_AREF(args, i))) {
3164 rb_ary_push(tmp, Qnil);
3165 }
3166 else {
3167 VALUE v[2];
3168
3169 v[1] = RARRAY_AREF(args, i);
3170 rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
3171 if (UNDEF_P(v[0])) {
3172 RARRAY_ASET(args, i, Qnil);
3173 v[0] = Qnil;
3174 }
3175 rb_ary_push(tmp, v[0]);
3176 }
3177 }
3178 if (NIL_P(result)) {
3179 enum_yield_array(tmp);
3180 }
3181 else {
3182 rb_ary_push(result, tmp);
3183 }
3184
3185 RB_GC_GUARD(args);
3186
3187 return Qnil;
3188}
3189
3190/*
3191 * call-seq:
3192 * zip(*other_enums) -> array
3193 * zip(*other_enums) {|array| ... } -> nil
3194 *
3195 * With no block given, returns a new array +new_array+ of size self.size
3196 * whose elements are arrays.
3197 * Each nested array <tt>new_array[n]</tt>
3198 * is of size <tt>other_enums.size+1</tt>, and contains:
3199 *
3200 * - The +n+-th element of self.
3201 * - The +n+-th element of each of the +other_enums+.
3202 *
3203 * If all +other_enums+ and self are the same size,
3204 * all elements are included in the result, and there is no +nil+-filling:
3205 *
3206 * a = [:a0, :a1, :a2, :a3]
3207 * b = [:b0, :b1, :b2, :b3]
3208 * c = [:c0, :c1, :c2, :c3]
3209 * d = a.zip(b, c)
3210 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
3211 *
3212 * f = {foo: 0, bar: 1, baz: 2}
3213 * g = {goo: 3, gar: 4, gaz: 5}
3214 * h = {hoo: 6, har: 7, haz: 8}
3215 * d = f.zip(g, h)
3216 * d # => [
3217 * # [[:foo, 0], [:goo, 3], [:hoo, 6]],
3218 * # [[:bar, 1], [:gar, 4], [:har, 7]],
3219 * # [[:baz, 2], [:gaz, 5], [:haz, 8]]
3220 * # ]
3221 *
3222 * If any enumerable in other_enums is smaller than self,
3223 * fills to <tt>self.size</tt> with +nil+:
3224 *
3225 * a = [:a0, :a1, :a2, :a3]
3226 * b = [:b0, :b1, :b2]
3227 * c = [:c0, :c1]
3228 * d = a.zip(b, c)
3229 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
3230 *
3231 * If any enumerable in other_enums is larger than self,
3232 * its trailing elements are ignored:
3233 *
3234 * a = [:a0, :a1, :a2, :a3]
3235 * b = [:b0, :b1, :b2, :b3, :b4]
3236 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
3237 * d = a.zip(b, c)
3238 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
3239 *
3240 * When a block is given, calls the block with each of the sub-arrays
3241 * (formed as above); returns nil:
3242 *
3243 * a = [:a0, :a1, :a2, :a3]
3244 * b = [:b0, :b1, :b2, :b3]
3245 * c = [:c0, :c1, :c2, :c3]
3246 * a.zip(b, c) {|sub_array| p sub_array} # => nil
3247 *
3248 * Output:
3249 *
3250 * [:a0, :b0, :c0]
3251 * [:a1, :b1, :c1]
3252 * [:a2, :b2, :c2]
3253 * [:a3, :b3, :c3]
3254 *
3255 */
3256
3257static VALUE
3258enum_zip(int argc, VALUE *argv, VALUE obj)
3259{
3260 int i;
3261 ID conv;
3262 struct MEMO *memo;
3263 VALUE result = Qnil;
3264 VALUE args = rb_ary_new4(argc, argv);
3265 int allary = TRUE;
3266
3267 argv = RARRAY_PTR(args);
3268 for (i=0; i<argc; i++) {
3269 VALUE ary = rb_check_array_type(argv[i]);
3270 if (NIL_P(ary)) {
3271 allary = FALSE;
3272 break;
3273 }
3274 argv[i] = ary;
3275 }
3276 if (!allary) {
3277 static const VALUE sym_each = STATIC_ID2SYM(id_each);
3278 CONST_ID(conv, "to_enum");
3279 for (i=0; i<argc; i++) {
3280 if (!rb_respond_to(argv[i], id_each)) {
3281 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
3282 rb_obj_class(argv[i]));
3283 }
3284 argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
3285 }
3286 }
3287 if (!rb_block_given_p()) {
3288 result = rb_ary_new();
3289 }
3290
3291 /* TODO: use NODE_DOT2 as memo(v, v, -) */
3292 memo = MEMO_NEW(result, args, 0);
3293 rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
3294
3295 return result;
3296}
3297
3298static VALUE
3299take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3300{
3301 struct MEMO *memo = MEMO_CAST(args);
3302 rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3303 if (--memo->u3.cnt == 0) rb_iter_break();
3304 return Qnil;
3305}
3306
3307/*
3308 * call-seq:
3309 * take(n) -> array
3310 *
3311 * For non-negative integer +n+, returns the first +n+ elements:
3312 *
3313 * r = (1..4)
3314 * r.take(2) # => [1, 2]
3315 * r.take(0) # => []
3316 *
3317 * h = {foo: 0, bar: 1, baz: 2, bat: 3}
3318 * h.take(2) # => [[:foo, 0], [:bar, 1]]
3319 *
3320 */
3321
3322static VALUE
3323enum_take(VALUE obj, VALUE n)
3324{
3325 struct MEMO *memo;
3326 VALUE result;
3327 long len = NUM2LONG(n);
3328
3329 if (len < 0) {
3330 rb_raise(rb_eArgError, "attempt to take negative size");
3331 }
3332
3333 if (len == 0) return rb_ary_new2(0);
3334 result = rb_ary_new2(len);
3335 memo = MEMO_NEW(result, 0, len);
3336 rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
3337 return result;
3338}
3339
3340
3341static VALUE
3342take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
3343{
3344 if (!RTEST(rb_yield_values2(argc, argv))) rb_iter_break();
3345 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
3346 return Qnil;
3347}
3348
3349/*
3350 * call-seq:
3351 * take_while {|element| ... } -> array
3352 * take_while -> enumerator
3353 *
3354 * Calls the block with successive elements as long as the block
3355 * returns a truthy value;
3356 * returns an array of all elements up to that point:
3357 *
3358 *
3359 * (1..4).take_while{|i| i < 3 } # => [1, 2]
3360 * h = {foo: 0, bar: 1, baz: 2}
3361 * h.take_while{|element| key, value = *element; value < 2 }
3362 * # => [[:foo, 0], [:bar, 1]]
3363 *
3364 * With no block given, returns an Enumerator.
3365 *
3366 */
3367
3368static VALUE
3369enum_take_while(VALUE obj)
3370{
3371 VALUE ary;
3372
3373 RETURN_ENUMERATOR(obj, 0, 0);
3374 ary = rb_ary_new();
3375 rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
3376 return ary;
3377}
3378
3379static VALUE
3380drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3381{
3382 struct MEMO *memo = MEMO_CAST(args);
3383 if (memo->u3.cnt == 0) {
3384 rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3385 }
3386 else {
3387 memo->u3.cnt--;
3388 }
3389 return Qnil;
3390}
3391
3392/*
3393 * call-seq:
3394 * drop(n) -> array
3395 *
3396 * For positive integer +n+, returns an array containing
3397 * all but the first +n+ elements:
3398 *
3399 * r = (1..4)
3400 * r.drop(3) # => [4]
3401 * r.drop(2) # => [3, 4]
3402 * r.drop(1) # => [2, 3, 4]
3403 * r.drop(0) # => [1, 2, 3, 4]
3404 * r.drop(50) # => []
3405 *
3406 * h = {foo: 0, bar: 1, baz: 2, bat: 3}
3407 * h.drop(2) # => [[:baz, 2], [:bat, 3]]
3408 *
3409 */
3410
3411static VALUE
3412enum_drop(VALUE obj, VALUE n)
3413{
3414 VALUE result;
3415 struct MEMO *memo;
3416 long len = NUM2LONG(n);
3417
3418 if (len < 0) {
3419 rb_raise(rb_eArgError, "attempt to drop negative size");
3420 }
3421
3422 result = rb_ary_new();
3423 memo = MEMO_NEW(result, 0, len);
3424 rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
3425 return result;
3426}
3427
3428
3429static VALUE
3430drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3431{
3432 struct MEMO *memo = MEMO_CAST(args);
3433 ENUM_WANT_SVALUE();
3434
3435 if (!memo->u3.state && !RTEST(enum_yield(argc, i))) {
3436 memo->u3.state = TRUE;
3437 }
3438 if (memo->u3.state) {
3439 rb_ary_push(memo->v1, i);
3440 }
3441 return Qnil;
3442}
3443
3444/*
3445 * call-seq:
3446 * drop_while {|element| ... } -> array
3447 * drop_while -> enumerator
3448 *
3449 * Calls the block with successive elements as long as the block
3450 * returns a truthy value;
3451 * returns an array of all elements after that point:
3452 *
3453 *
3454 * (1..4).drop_while{|i| i < 3 } # => [3, 4]
3455 * h = {foo: 0, bar: 1, baz: 2}
3456 * a = h.drop_while{|element| key, value = *element; value < 2 }
3457 * a # => [[:baz, 2]]
3458 *
3459 * With no block given, returns an Enumerator.
3460 *
3461 */
3462
3463static VALUE
3464enum_drop_while(VALUE obj)
3465{
3466 VALUE result;
3467 struct MEMO *memo;
3468
3469 RETURN_ENUMERATOR(obj, 0, 0);
3470 result = rb_ary_new();
3471 memo = MEMO_NEW(result, 0, FALSE);
3472 rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
3473 return result;
3474}
3475
3476static VALUE
3477cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
3478{
3479 ENUM_WANT_SVALUE();
3480
3481 rb_ary_push(ary, argc > 1 ? i : rb_ary_new_from_values(argc, argv));
3482 enum_yield(argc, i);
3483 return Qnil;
3484}
3485
3486static VALUE
3487enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
3488{
3489 long mul = 0;
3490 VALUE n = Qnil;
3491 VALUE size;
3492
3493 if (args && (RARRAY_LEN(args) > 0)) {
3494 n = RARRAY_AREF(args, 0);
3495 if (!NIL_P(n)) mul = NUM2LONG(n);
3496 }
3497
3498 size = enum_size(self, args, 0);
3499 if (NIL_P(size) || FIXNUM_ZERO_P(size)) return size;
3500
3501 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
3502 if (mul <= 0) return INT2FIX(0);
3503 n = LONG2FIX(mul);
3504 return rb_funcallv(size, '*', 1, &n);
3505}
3506
3507/*
3508 * call-seq:
3509 * cycle(n = nil) {|element| ...} -> nil
3510 * cycle(n = nil) -> enumerator
3511 *
3512 * When called with positive integer argument +n+ and a block,
3513 * calls the block with each element, then does so again,
3514 * until it has done so +n+ times; returns +nil+:
3515 *
3516 * a = []
3517 * (1..4).cycle(3) {|element| a.push(element) } # => nil
3518 * a # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
3519 * a = []
3520 * ('a'..'d').cycle(2) {|element| a.push(element) }
3521 * a # => ["a", "b", "c", "d", "a", "b", "c", "d"]
3522 * a = []
3523 * {foo: 0, bar: 1, baz: 2}.cycle(2) {|element| a.push(element) }
3524 * a # => [[:foo, 0], [:bar, 1], [:baz, 2], [:foo, 0], [:bar, 1], [:baz, 2]]
3525 *
3526 * If count is zero or negative, does not call the block.
3527 *
3528 * When called with a block and +n+ is +nil+, cycles forever.
3529 *
3530 * When no block is given, returns an Enumerator.
3531 *
3532 */
3533
3534static VALUE
3535enum_cycle(int argc, VALUE *argv, VALUE obj)
3536{
3537 VALUE ary;
3538 VALUE nv = Qnil;
3539 long n, i, len;
3540
3541 rb_check_arity(argc, 0, 1);
3542
3543 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
3544 if (!argc || NIL_P(nv = argv[0])) {
3545 n = -1;
3546 }
3547 else {
3548 n = NUM2LONG(nv);
3549 if (n <= 0) return Qnil;
3550 }
3551 ary = rb_ary_new();
3552 RBASIC_CLEAR_CLASS(ary);
3553 rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
3554 len = RARRAY_LEN(ary);
3555 if (len == 0) return Qnil;
3556 while (n < 0 || 0 < --n) {
3557 for (i=0; i<len; i++) {
3558 enum_yield_array(RARRAY_AREF(ary, i));
3559 }
3560 }
3561 return Qnil;
3562}
3563
3565 VALUE categorize;
3566 VALUE prev_value;
3567 VALUE prev_elts;
3568 VALUE yielder;
3569};
3570
3571static VALUE
3572chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
3573{
3574 struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
3575 VALUE v, s;
3576 VALUE alone = ID2SYM(id__alone);
3577 VALUE separator = ID2SYM(id__separator);
3578
3579 ENUM_WANT_SVALUE();
3580
3581 v = rb_funcallv(argp->categorize, id_call, 1, &i);
3582
3583 if (v == alone) {
3584 if (!NIL_P(argp->prev_value)) {
3585 s = rb_assoc_new(argp->prev_value, argp->prev_elts);
3586 rb_funcallv(argp->yielder, id_lshift, 1, &s);
3587 argp->prev_value = argp->prev_elts = Qnil;
3588 }
3589 v = rb_assoc_new(v, rb_ary_new3(1, i));
3590 rb_funcallv(argp->yielder, id_lshift, 1, &v);
3591 }
3592 else if (NIL_P(v) || v == separator) {
3593 if (!NIL_P(argp->prev_value)) {
3594 v = rb_assoc_new(argp->prev_value, argp->prev_elts);
3595 rb_funcallv(argp->yielder, id_lshift, 1, &v);
3596 argp->prev_value = argp->prev_elts = Qnil;
3597 }
3598 }
3599 else if (SYMBOL_P(v) && (s = rb_sym2str(v), RSTRING_PTR(s)[0] == '_')) {
3600 rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
3601 }
3602 else {
3603 if (NIL_P(argp->prev_value)) {
3604 argp->prev_value = v;
3605 argp->prev_elts = rb_ary_new3(1, i);
3606 }
3607 else {
3608 if (rb_equal(argp->prev_value, v)) {
3609 rb_ary_push(argp->prev_elts, i);
3610 }
3611 else {
3612 s = rb_assoc_new(argp->prev_value, argp->prev_elts);
3613 rb_funcallv(argp->yielder, id_lshift, 1, &s);
3614 argp->prev_value = v;
3615 argp->prev_elts = rb_ary_new3(1, i);
3616 }
3617 }
3618 }
3619 return Qnil;
3620}
3621
3622static VALUE
3624{
3625 VALUE enumerable;
3626 VALUE arg;
3627 struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
3628
3629 enumerable = rb_ivar_get(enumerator, id_chunk_enumerable);
3630 memo->categorize = rb_ivar_get(enumerator, id_chunk_categorize);
3631 memo->prev_value = Qnil;
3632 memo->prev_elts = Qnil;
3633 memo->yielder = yielder;
3634
3635 rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
3636 memo = MEMO_FOR(struct chunk_arg, arg);
3637 if (!NIL_P(memo->prev_elts)) {
3638 arg = rb_assoc_new(memo->prev_value, memo->prev_elts);
3639 rb_funcallv(memo->yielder, id_lshift, 1, &arg);
3640 }
3641 return Qnil;
3642}
3643
3644/*
3645 * call-seq:
3646 * chunk {|array| ... } -> enumerator
3647 *
3648 * Each element in the returned enumerator is a 2-element array consisting of:
3649 *
3650 * - A value returned by the block.
3651 * - An array ("chunk") containing the element for which that value was returned,
3652 * and all following elements for which the block returned the same value:
3653 *
3654 * So that:
3655 *
3656 * - Each block return value that is different from its predecessor
3657 * begins a new chunk.
3658 * - Each block return value that is the same as its predecessor
3659 * continues the same chunk.
3660 *
3661 * Example:
3662 *
3663 * e = (0..10).chunk {|i| (i / 3).floor } # => #<Enumerator: ...>
3664 * # The enumerator elements.
3665 * e.next # => [0, [0, 1, 2]]
3666 * e.next # => [1, [3, 4, 5]]
3667 * e.next # => [2, [6, 7, 8]]
3668 * e.next # => [3, [9, 10]]
3669 *
3670 * \Method +chunk+ is especially useful for an enumerable that is already sorted.
3671 * This example counts words for each initial letter in a large array of words:
3672 *
3673 * # Get sorted words from a web page.
3674 * url = 'https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt'
3675 * words = URI::open(url).readlines
3676 * # Make chunks, one for each letter.
3677 * e = words.chunk {|word| word.upcase[0] } # => #<Enumerator: ...>
3678 * # Display 'A' through 'F'.
3679 * e.each {|c, words| p [c, words.length]; break if c == 'F' }
3680 *
3681 * Output:
3682 *
3683 * ["A", 17096]
3684 * ["B", 11070]
3685 * ["C", 19901]
3686 * ["D", 10896]
3687 * ["E", 8736]
3688 * ["F", 6860]
3689 *
3690 * You can use the special symbol <tt>:_alone</tt> to force an element
3691 * into its own separate chuck:
3692 *
3693 * a = [0, 0, 1, 1]
3694 * e = a.chunk{|i| i.even? ? :_alone : true }
3695 * e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]
3696 *
3697 * For example, you can put each line that contains a URL into its own chunk:
3698 *
3699 * pattern = /http/
3700 * open(filename) { |f|
3701 * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
3702 * pp lines
3703 * }
3704 * }
3705 *
3706 * You can use the special symbol <tt>:_separator</tt> or +nil+
3707 * to force an element to be ignored (not included in any chunk):
3708 *
3709 * a = [0, 0, -1, 1, 1]
3710 * e = a.chunk{|i| i < 0 ? :_separator : true }
3711 * e.to_a # => [[true, [0, 0]], [true, [1, 1]]]
3712 *
3713 * Note that the separator does end the chunk:
3714 *
3715 * a = [0, 0, -1, 1, -1, 1]
3716 * e = a.chunk{|i| i < 0 ? :_separator : true }
3717 * e.to_a # => [[true, [0, 0]], [true, [1]], [true, [1]]]
3718 *
3719 * For example, the sequence of hyphens in svn log can be eliminated as follows:
3720 *
3721 * sep = "-"*72 + "\n"
3722 * IO.popen("svn log README") { |f|
3723 * f.chunk { |line|
3724 * line != sep || nil
3725 * }.each { |_, lines|
3726 * pp lines
3727 * }
3728 * }
3729 * #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
3730 * # "\n",
3731 * # "* README, README.ja: Update the portability section.\n",
3732 * # "\n"]
3733 * # ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
3734 * # "\n",
3735 * # "* README, README.ja: Add a note about default C flags.\n",
3736 * # "\n"]
3737 * # ...
3738 *
3739 * Paragraphs separated by empty lines can be parsed as follows:
3740 *
3741 * File.foreach("README").chunk { |line|
3742 * /\A\s*\z/ !~ line || nil
3743 * }.each { |_, lines|
3744 * pp lines
3745 * }
3746 *
3747 */
3748static VALUE
3749enum_chunk(VALUE enumerable)
3750{
3752
3753 RETURN_SIZED_ENUMERATOR(enumerable, 0, 0, enum_size);
3754
3756 rb_ivar_set(enumerator, id_chunk_enumerable, enumerable);
3757 rb_ivar_set(enumerator, id_chunk_categorize, rb_block_proc());
3758 rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
3759 return enumerator;
3760}
3761
3762
3764 VALUE sep_pred;
3765 VALUE sep_pat;
3766 VALUE prev_elts;
3767 VALUE yielder;
3768};
3769
3770static VALUE
3771slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
3772{
3773 struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
3774 VALUE header_p;
3775
3776 ENUM_WANT_SVALUE();
3777
3778 if (!NIL_P(argp->sep_pat))
3779 header_p = rb_funcallv(argp->sep_pat, id_eqq, 1, &i);
3780 else
3781 header_p = rb_funcallv(argp->sep_pred, id_call, 1, &i);
3782 if (RTEST(header_p)) {
3783 if (!NIL_P(argp->prev_elts))
3784 rb_funcallv(argp->yielder, id_lshift, 1, &argp->prev_elts);
3785 argp->prev_elts = rb_ary_new3(1, i);
3786 }
3787 else {
3788 if (NIL_P(argp->prev_elts))
3789 argp->prev_elts = rb_ary_new3(1, i);
3790 else
3791 rb_ary_push(argp->prev_elts, i);
3792 }
3793
3794 return Qnil;
3795}
3796
3797static VALUE
3799{
3800 VALUE enumerable;
3801 VALUE arg;
3802 struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
3803
3804 enumerable = rb_ivar_get(enumerator, id_slicebefore_enumerable);
3805 memo->sep_pred = rb_attr_get(enumerator, id_slicebefore_sep_pred);
3806 memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, id_slicebefore_sep_pat) : Qnil;
3807 memo->prev_elts = Qnil;
3808 memo->yielder = yielder;
3809
3810 rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
3811 memo = MEMO_FOR(struct slicebefore_arg, arg);
3812 if (!NIL_P(memo->prev_elts))
3813 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3814 return Qnil;
3815}
3816
3817/*
3818 * call-seq:
3819 * slice_before(pattern) -> enumerator
3820 * slice_before {|elt| ... } -> enumerator
3821 *
3822 * With argument +pattern+, returns an enumerator that uses the pattern
3823 * to partition elements into arrays ("slices").
3824 * An element begins a new slice if <tt>element === pattern</tt>
3825 * (or if it is the first element).
3826 *
3827 * a = %w[foo bar fop for baz fob fog bam foy]
3828 * e = a.slice_before(/ba/) # => #<Enumerator: ...>
3829 * e.each {|array| p array }
3830 *
3831 * Output:
3832 *
3833 * ["foo"]
3834 * ["bar", "fop", "for"]
3835 * ["baz", "fob", "fog"]
3836 * ["bam", "foy"]
3837 *
3838 * With a block, returns an enumerator that uses the block
3839 * to partition elements into arrays.
3840 * An element begins a new slice if its block return is a truthy value
3841 * (or if it is the first element):
3842 *
3843 * e = (1..20).slice_before {|i| i % 4 == 2 } # => #<Enumerator: ...>
3844 * e.each {|array| p array }
3845 *
3846 * Output:
3847 *
3848 * [1]
3849 * [2, 3, 4, 5]
3850 * [6, 7, 8, 9]
3851 * [10, 11, 12, 13]
3852 * [14, 15, 16, 17]
3853 * [18, 19, 20]
3854 *
3855 * Other methods of the Enumerator class and Enumerable module,
3856 * such as +to_a+, +map+, etc., are also usable.
3857 *
3858 * For example, iteration over ChangeLog entries can be implemented as
3859 * follows:
3860 *
3861 * # iterate over ChangeLog entries.
3862 * open("ChangeLog") { |f|
3863 * f.slice_before(/\A\S/).each { |e| pp e }
3864 * }
3865 *
3866 * # same as above. block is used instead of pattern argument.
3867 * open("ChangeLog") { |f|
3868 * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
3869 * }
3870 *
3871 * "svn proplist -R" produces multiline output for each file.
3872 * They can be chunked as follows:
3873 *
3874 * IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
3875 * f.lines.slice_before(/\AProp/).each { |lines| p lines }
3876 * }
3877 * #=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
3878 * # ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
3879 * # ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
3880 * # ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
3881 * # ...
3882 *
3883 * If the block needs to maintain state over multiple elements,
3884 * local variables can be used.
3885 * For example, three or more consecutive increasing numbers can be squashed
3886 * as follows (see +chunk_while+ for a better way):
3887 *
3888 * a = [0, 2, 3, 4, 6, 7, 9]
3889 * prev = a[0]
3890 * p a.slice_before { |e|
3891 * prev, prev2 = e, prev
3892 * prev2 + 1 != e
3893 * }.map { |es|
3894 * es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
3895 * }.join(",")
3896 * #=> "0,2-4,6,7,9"
3897 *
3898 * However local variables should be used carefully
3899 * if the result enumerator is enumerated twice or more.
3900 * The local variables should be initialized for each enumeration.
3901 * Enumerator.new can be used to do it.
3902 *
3903 * # Word wrapping. This assumes all characters have same width.
3904 * def wordwrap(words, maxwidth)
3905 * Enumerator.new {|y|
3906 * # cols is initialized in Enumerator.new.
3907 * cols = 0
3908 * words.slice_before { |w|
3909 * cols += 1 if cols != 0
3910 * cols += w.length
3911 * if maxwidth < cols
3912 * cols = w.length
3913 * true
3914 * else
3915 * false
3916 * end
3917 * }.each {|ws| y.yield ws }
3918 * }
3919 * end
3920 * text = (1..20).to_a.join(" ")
3921 * enum = wordwrap(text.split(/\s+/), 10)
3922 * puts "-"*10
3923 * enum.each { |ws| puts ws.join(" ") } # first enumeration.
3924 * puts "-"*10
3925 * enum.each { |ws| puts ws.join(" ") } # second enumeration generates same result as the first.
3926 * puts "-"*10
3927 * #=> ----------
3928 * # 1 2 3 4 5
3929 * # 6 7 8 9 10
3930 * # 11 12 13
3931 * # 14 15 16
3932 * # 17 18 19
3933 * # 20
3934 * # ----------
3935 * # 1 2 3 4 5
3936 * # 6 7 8 9 10
3937 * # 11 12 13
3938 * # 14 15 16
3939 * # 17 18 19
3940 * # 20
3941 * # ----------
3942 *
3943 * mbox contains series of mails which start with Unix From line.
3944 * So each mail can be extracted by slice before Unix From line.
3945 *
3946 * # parse mbox
3947 * open("mbox") { |f|
3948 * f.slice_before { |line|
3949 * line.start_with? "From "
3950 * }.each { |mail|
3951 * unix_from = mail.shift
3952 * i = mail.index("\n")
3953 * header = mail[0...i]
3954 * body = mail[(i+1)..-1]
3955 * body.pop if body.last == "\n"
3956 * fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
3957 * p unix_from
3958 * pp fields
3959 * pp body
3960 * }
3961 * }
3962 *
3963 * # split mails in mbox (slice before Unix From line after an empty line)
3964 * open("mbox") { |f|
3965 * emp = true
3966 * f.slice_before { |line|
3967 * prevemp = emp
3968 * emp = line == "\n"
3969 * prevemp && line.start_with?("From ")
3970 * }.each { |mail|
3971 * mail.pop if mail.last == "\n"
3972 * pp mail
3973 * }
3974 * }
3975 *
3976 */
3977static VALUE
3978enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
3979{
3981
3982 if (rb_block_given_p()) {
3983 if (argc != 0)
3984 rb_error_arity(argc, 0, 0);
3986 rb_ivar_set(enumerator, id_slicebefore_sep_pred, rb_block_proc());
3987 }
3988 else {
3989 VALUE sep_pat;
3990 rb_scan_args(argc, argv, "1", &sep_pat);
3992 rb_ivar_set(enumerator, id_slicebefore_sep_pat, sep_pat);
3993 }
3994 rb_ivar_set(enumerator, id_slicebefore_enumerable, enumerable);
3995 rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
3996 return enumerator;
3997}
3998
3999
4001 VALUE pat;
4002 VALUE pred;
4003 VALUE prev_elts;
4004 VALUE yielder;
4005};
4006
4007static VALUE
4008sliceafter_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
4009{
4010#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct sliceafter_arg, _memo)))
4011 struct sliceafter_arg *memo;
4012 int split_p;
4013 UPDATE_MEMO;
4014
4015 ENUM_WANT_SVALUE();
4016
4017 if (NIL_P(memo->prev_elts)) {
4018 memo->prev_elts = rb_ary_new3(1, i);
4019 }
4020 else {
4021 rb_ary_push(memo->prev_elts, i);
4022 }
4023
4024 if (NIL_P(memo->pred)) {
4025 split_p = RTEST(rb_funcallv(memo->pat, id_eqq, 1, &i));
4026 UPDATE_MEMO;
4027 }
4028 else {
4029 split_p = RTEST(rb_funcallv(memo->pred, id_call, 1, &i));
4030 UPDATE_MEMO;
4031 }
4032
4033 if (split_p) {
4034 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4035 UPDATE_MEMO;
4036 memo->prev_elts = Qnil;
4037 }
4038
4039 return Qnil;
4040#undef UPDATE_MEMO
4041}
4042
4043static VALUE
4045{
4046 VALUE enumerable;
4047 VALUE arg;
4048 struct sliceafter_arg *memo = NEW_MEMO_FOR(struct sliceafter_arg, arg);
4049
4050 enumerable = rb_ivar_get(enumerator, id_sliceafter_enum);
4051 memo->pat = rb_ivar_get(enumerator, id_sliceafter_pat);
4052 memo->pred = rb_attr_get(enumerator, id_sliceafter_pred);
4053 memo->prev_elts = Qnil;
4054 memo->yielder = yielder;
4055
4056 rb_block_call(enumerable, id_each, 0, 0, sliceafter_ii, arg);
4057 memo = MEMO_FOR(struct sliceafter_arg, arg);
4058 if (!NIL_P(memo->prev_elts))
4059 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4060 return Qnil;
4061}
4062
4063/*
4064 * call-seq:
4065 * enum.slice_after(pattern) -> an_enumerator
4066 * enum.slice_after { |elt| bool } -> an_enumerator
4067 *
4068 * Creates an enumerator for each chunked elements.
4069 * The ends of chunks are defined by _pattern_ and the block.
4070 *
4071 * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
4072 * returns <code>true</code> for the element, the element is end of a
4073 * chunk.
4074 *
4075 * The <code>===</code> and _block_ is called from the first element to the last
4076 * element of _enum_.
4077 *
4078 * The result enumerator yields the chunked elements as an array.
4079 * So +each+ method can be called as follows:
4080 *
4081 * enum.slice_after(pattern).each { |ary| ... }
4082 * enum.slice_after { |elt| bool }.each { |ary| ... }
4083 *
4084 * Other methods of the Enumerator class and Enumerable module,
4085 * such as +map+, etc., are also usable.
4086 *
4087 * For example, continuation lines (lines end with backslash) can be
4088 * concatenated as follows:
4089 *
4090 * lines = ["foo\n", "bar\\\n", "baz\n", "\n", "qux\n"]
4091 * e = lines.slice_after(/(?<!\\‍)\n\z/)
4092 * p e.to_a
4093 * #=> [["foo\n"], ["bar\\\n", "baz\n"], ["\n"], ["qux\n"]]
4094 * p e.map {|ll| ll[0...-1].map {|l| l.sub(/\\\n\z/, "") }.join + ll.last }
4095 * #=>["foo\n", "barbaz\n", "\n", "qux\n"]
4096 *
4097 */
4098
4099static VALUE
4100enum_slice_after(int argc, VALUE *argv, VALUE enumerable)
4101{
4103 VALUE pat = Qnil, pred = Qnil;
4104
4105 if (rb_block_given_p()) {
4106 if (0 < argc)
4107 rb_raise(rb_eArgError, "both pattern and block are given");
4108 pred = rb_block_proc();
4109 }
4110 else {
4111 rb_scan_args(argc, argv, "1", &pat);
4112 }
4113
4115 rb_ivar_set(enumerator, id_sliceafter_enum, enumerable);
4116 rb_ivar_set(enumerator, id_sliceafter_pat, pat);
4117 rb_ivar_set(enumerator, id_sliceafter_pred, pred);
4118
4119 rb_block_call(enumerator, idInitialize, 0, 0, sliceafter_i, enumerator);
4120 return enumerator;
4121}
4122
4124 VALUE pred;
4125 VALUE prev_elt;
4126 VALUE prev_elts;
4127 VALUE yielder;
4128 int inverted; /* 0 for slice_when and 1 for chunk_while. */
4129};
4130
4131static VALUE
4132slicewhen_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
4133{
4134#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct slicewhen_arg, _memo)))
4135 struct slicewhen_arg *memo;
4136 int split_p;
4137 UPDATE_MEMO;
4138
4139 ENUM_WANT_SVALUE();
4140
4141 if (UNDEF_P(memo->prev_elt)) {
4142 /* The first element */
4143 memo->prev_elt = i;
4144 memo->prev_elts = rb_ary_new3(1, i);
4145 }
4146 else {
4147 VALUE args[2];
4148 args[0] = memo->prev_elt;
4149 args[1] = i;
4150 split_p = RTEST(rb_funcallv(memo->pred, id_call, 2, args));
4151 UPDATE_MEMO;
4152
4153 if (memo->inverted)
4154 split_p = !split_p;
4155
4156 if (split_p) {
4157 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4158 UPDATE_MEMO;
4159 memo->prev_elts = rb_ary_new3(1, i);
4160 }
4161 else {
4162 rb_ary_push(memo->prev_elts, i);
4163 }
4164
4165 memo->prev_elt = i;
4166 }
4167
4168 return Qnil;
4169#undef UPDATE_MEMO
4170}
4171
4172static VALUE
4174{
4175 VALUE enumerable;
4176 VALUE arg;
4177 struct slicewhen_arg *memo =
4178 NEW_PARTIAL_MEMO_FOR(struct slicewhen_arg, arg, inverted);
4179
4180 enumerable = rb_ivar_get(enumerator, id_slicewhen_enum);
4181 memo->pred = rb_attr_get(enumerator, id_slicewhen_pred);
4182 memo->prev_elt = Qundef;
4183 memo->prev_elts = Qnil;
4184 memo->yielder = yielder;
4185 memo->inverted = RTEST(rb_attr_get(enumerator, id_slicewhen_inverted));
4186
4187 rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg);
4188 memo = MEMO_FOR(struct slicewhen_arg, arg);
4189 if (!NIL_P(memo->prev_elts))
4190 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4191 return Qnil;
4192}
4193
4194/*
4195 * call-seq:
4196 * enum.slice_when {|elt_before, elt_after| bool } -> an_enumerator
4197 *
4198 * Creates an enumerator for each chunked elements.
4199 * The beginnings of chunks are defined by the block.
4200 *
4201 * This method splits each chunk using adjacent elements,
4202 * _elt_before_ and _elt_after_,
4203 * in the receiver enumerator.
4204 * This method split chunks between _elt_before_ and _elt_after_ where
4205 * the block returns <code>true</code>.
4206 *
4207 * The block is called the length of the receiver enumerator minus one.
4208 *
4209 * The result enumerator yields the chunked elements as an array.
4210 * So +each+ method can be called as follows:
4211 *
4212 * enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }
4213 *
4214 * Other methods of the Enumerator class and Enumerable module,
4215 * such as +to_a+, +map+, etc., are also usable.
4216 *
4217 * For example, one-by-one increasing subsequence can be chunked as follows:
4218 *
4219 * a = [1,2,4,9,10,11,12,15,16,19,20,21]
4220 * b = a.slice_when {|i, j| i+1 != j }
4221 * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
4222 * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
4223 * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
4224 * d = c.join(",")
4225 * p d #=> "1,2,4,9-12,15,16,19-21"
4226 *
4227 * Near elements (threshold: 6) in sorted array can be chunked as follows:
4228 *
4229 * a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57]
4230 * p a.slice_when {|i, j| 6 < j - i }.to_a
4231 * #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]]
4232 *
4233 * Increasing (non-decreasing) subsequence can be chunked as follows:
4234 *
4235 * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
4236 * p a.slice_when {|i, j| i > j }.to_a
4237 * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
4238 *
4239 * Adjacent evens and odds can be chunked as follows:
4240 * (Enumerable#chunk is another way to do it.)
4241 *
4242 * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
4243 * p a.slice_when {|i, j| i.even? != j.even? }.to_a
4244 * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
4245 *
4246 * Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows:
4247 * (See Enumerable#chunk to ignore empty lines.)
4248 *
4249 * lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"]
4250 * p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a
4251 * #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]]
4252 *
4253 * Enumerable#chunk_while does the same, except splitting when the block
4254 * returns <code>false</code> instead of <code>true</code>.
4255 */
4256static VALUE
4257enum_slice_when(VALUE enumerable)
4258{
4260 VALUE pred;
4261
4262 pred = rb_block_proc();
4263
4265 rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
4266 rb_ivar_set(enumerator, id_slicewhen_pred, pred);
4267 rb_ivar_set(enumerator, id_slicewhen_inverted, Qfalse);
4268
4269 rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
4270 return enumerator;
4271}
4272
4273/*
4274 * call-seq:
4275 * enum.chunk_while {|elt_before, elt_after| bool } -> an_enumerator
4276 *
4277 * Creates an enumerator for each chunked elements.
4278 * The beginnings of chunks are defined by the block.
4279 *
4280 * This method splits each chunk using adjacent elements,
4281 * _elt_before_ and _elt_after_,
4282 * in the receiver enumerator.
4283 * This method split chunks between _elt_before_ and _elt_after_ where
4284 * the block returns <code>false</code>.
4285 *
4286 * The block is called the length of the receiver enumerator minus one.
4287 *
4288 * The result enumerator yields the chunked elements as an array.
4289 * So +each+ method can be called as follows:
4290 *
4291 * enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... }
4292 *
4293 * Other methods of the Enumerator class and Enumerable module,
4294 * such as +to_a+, +map+, etc., are also usable.
4295 *
4296 * For example, one-by-one increasing subsequence can be chunked as follows:
4297 *
4298 * a = [1,2,4,9,10,11,12,15,16,19,20,21]
4299 * b = a.chunk_while {|i, j| i+1 == j }
4300 * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
4301 * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
4302 * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
4303 * d = c.join(",")
4304 * p d #=> "1,2,4,9-12,15,16,19-21"
4305 *
4306 * Increasing (non-decreasing) subsequence can be chunked as follows:
4307 *
4308 * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
4309 * p a.chunk_while {|i, j| i <= j }.to_a
4310 * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
4311 *
4312 * Adjacent evens and odds can be chunked as follows:
4313 * (Enumerable#chunk is another way to do it.)
4314 *
4315 * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
4316 * p a.chunk_while {|i, j| i.even? == j.even? }.to_a
4317 * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
4318 *
4319 * Enumerable#slice_when does the same, except splitting when the block
4320 * returns <code>true</code> instead of <code>false</code>.
4321 */
4322static VALUE
4323enum_chunk_while(VALUE enumerable)
4324{
4326 VALUE pred;
4327
4328 pred = rb_block_proc();
4329
4331 rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
4332 rb_ivar_set(enumerator, id_slicewhen_pred, pred);
4333 rb_ivar_set(enumerator, id_slicewhen_inverted, Qtrue);
4334
4335 rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
4336 return enumerator;
4337}
4338
4340 VALUE v, r;
4341 long n;
4342 double f, c;
4343 int block_given;
4344 int float_value;
4345};
4346
4347static void
4348sum_iter_normalize_memo(struct enum_sum_memo *memo)
4349{
4350 assert(FIXABLE(memo->n));
4351 memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v);
4352 memo->n = 0;
4353
4354 switch (TYPE(memo->r)) {
4355 case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v); break;
4356 case T_UNDEF: break;
4357 default: UNREACHABLE; /* or ...? */
4358 }
4359 memo->r = Qundef;
4360}
4361
4362static void
4363sum_iter_fixnum(VALUE i, struct enum_sum_memo *memo)
4364{
4365 memo->n += FIX2LONG(i); /* should not overflow long type */
4366 if (! FIXABLE(memo->n)) {
4367 memo->v = rb_big_plus(LONG2NUM(memo->n), memo->v);
4368 memo->n = 0;
4369 }
4370}
4371
4372static void
4373sum_iter_bignum(VALUE i, struct enum_sum_memo *memo)
4374{
4375 memo->v = rb_big_plus(i, memo->v);
4376}
4377
4378static void
4379sum_iter_rational(VALUE i, struct enum_sum_memo *memo)
4380{
4381 if (UNDEF_P(memo->r)) {
4382 memo->r = i;
4383 }
4384 else {
4385 memo->r = rb_rational_plus(memo->r, i);
4386 }
4387}
4388
4389static void
4390sum_iter_some_value(VALUE i, struct enum_sum_memo *memo)
4391{
4392 memo->v = rb_funcallv(memo->v, idPLUS, 1, &i);
4393}
4394
4395static void
4396sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo)
4397{
4398 /*
4399 * Kahan-Babuska balancing compensated summation algorithm
4400 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
4401 */
4402 double x;
4403
4404 switch (TYPE(i)) {
4405 case T_FLOAT: x = RFLOAT_VALUE(i); break;
4406 case T_FIXNUM: x = FIX2LONG(i); break;
4407 case T_BIGNUM: x = rb_big2dbl(i); break;
4408 case T_RATIONAL: x = rb_num2dbl(i); break;
4409 default:
4410 memo->v = DBL2NUM(memo->f);
4411 memo->float_value = 0;
4412 sum_iter_some_value(i, memo);
4413 return;
4414 }
4415
4416 double f = memo->f;
4417
4418 if (isnan(f)) {
4419 return;
4420 }
4421 else if (! isfinite(x)) {
4422 if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
4423 i = DBL2NUM(f);
4424 x = nan("");
4425 }
4426 memo->v = i;
4427 memo->f = x;
4428 return;
4429 }
4430 else if (isinf(f)) {
4431 return;
4432 }
4433
4434 double c = memo->c;
4435 double t = f + x;
4436
4437 if (fabs(f) >= fabs(x)) {
4438 c += ((f - t) + x);
4439 }
4440 else {
4441 c += ((x - t) + f);
4442 }
4443 f = t;
4444
4445 memo->f = f;
4446 memo->c = c;
4447}
4448
4449static void
4450sum_iter(VALUE i, struct enum_sum_memo *memo)
4451{
4452 assert(memo != NULL);
4453 if (memo->block_given) {
4454 i = rb_yield(i);
4455 }
4456
4457 if (memo->float_value) {
4458 sum_iter_Kahan_Babuska(i, memo);
4459 }
4460 else switch (TYPE(memo->v)) {
4461 default: sum_iter_some_value(i, memo); return;
4462 case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
4463 case T_FIXNUM:
4464 case T_BIGNUM:
4465 case T_RATIONAL:
4466 switch (TYPE(i)) {
4467 case T_FIXNUM: sum_iter_fixnum(i, memo); return;
4468 case T_BIGNUM: sum_iter_bignum(i, memo); return;
4469 case T_RATIONAL: sum_iter_rational(i, memo); return;
4470 case T_FLOAT:
4471 sum_iter_normalize_memo(memo);
4472 memo->f = NUM2DBL(memo->v);
4473 memo->c = 0.0;
4474 memo->float_value = 1;
4475 sum_iter_Kahan_Babuska(i, memo);
4476 return;
4477 default:
4478 sum_iter_normalize_memo(memo);
4479 sum_iter_some_value(i, memo);
4480 return;
4481 }
4482 }
4483}
4484
4485static VALUE
4486enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
4487{
4488 ENUM_WANT_SVALUE();
4489 sum_iter(i, (struct enum_sum_memo *) args);
4490 return Qnil;
4491}
4492
4493static int
4494hash_sum_i(VALUE key, VALUE value, VALUE arg)
4495{
4496 sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg);
4497 return ST_CONTINUE;
4498}
4499
4500static void
4501hash_sum(VALUE hash, struct enum_sum_memo *memo)
4502{
4503 assert(RB_TYPE_P(hash, T_HASH));
4504 assert(memo != NULL);
4505
4506 rb_hash_foreach(hash, hash_sum_i, (VALUE)memo);
4507}
4508
4509static VALUE
4510int_range_sum(VALUE beg, VALUE end, int excl, VALUE init)
4511{
4512 if (excl) {
4513 if (FIXNUM_P(end))
4514 end = LONG2FIX(FIX2LONG(end) - 1);
4515 else
4516 end = rb_big_minus(end, LONG2FIX(1));
4517 }
4518
4519 if (rb_int_ge(end, beg)) {
4520 VALUE a;
4521 a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
4522 a = rb_int_mul(a, rb_int_plus(end, beg));
4523 a = rb_int_idiv(a, LONG2FIX(2));
4524 return rb_int_plus(init, a);
4525 }
4526
4527 return init;
4528}
4529
4530/*
4531 * call-seq:
4532 * sum(initial_value = 0) -> number
4533 * sum(initial_value = 0) {|element| ... } -> object
4534 *
4535 * With no block given,
4536 * returns the sum of +initial_value+ and the elements:
4537 *
4538 * (1..100).sum # => 5050
4539 * (1..100).sum(1) # => 5051
4540 * ('a'..'d').sum('foo') # => "fooabcd"
4541 *
4542 * Generally, the sum is computed using methods <tt>+</tt> and +each+;
4543 * for performance optimizations, those methods may not be used,
4544 * and so any redefinition of those methods may not have effect here.
4545 *
4546 * One such optimization: When possible, computes using Gauss's summation
4547 * formula <em>n(n+1)/2</em>:
4548 *
4549 * 100 * (100 + 1) / 2 # => 5050
4550 *
4551 * With a block given, calls the block with each element;
4552 * returns the sum of +initial_value+ and the block return values:
4553 *
4554 * (1..4).sum {|i| i*i } # => 30
4555 * (1..4).sum(100) {|i| i*i } # => 130
4556 * h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5}
4557 * h.sum {|key, value| value.odd? ? value : 0 } # => 9
4558 * ('a'..'f').sum('x') {|c| c < 'd' ? c : '' } # => "xabc"
4559 *
4560 */
4561static VALUE
4562enum_sum(int argc, VALUE* argv, VALUE obj)
4563{
4564 struct enum_sum_memo memo;
4565 VALUE beg, end;
4566 int excl;
4567
4568 memo.v = (rb_check_arity(argc, 0, 1) == 0) ? LONG2FIX(0) : argv[0];
4569 memo.block_given = rb_block_given_p();
4570 memo.n = 0;
4571 memo.r = Qundef;
4572
4573 if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
4574 memo.f = RFLOAT_VALUE(memo.v);
4575 memo.c = 0.0;
4576 }
4577 else {
4578 memo.f = 0.0;
4579 memo.c = 0.0;
4580 }
4581
4582 if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
4583 if (!memo.block_given && !memo.float_value &&
4584 (FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
4585 (FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
4586 return int_range_sum(beg, end, excl, memo.v);
4587 }
4588 }
4589
4590 if (RB_TYPE_P(obj, T_HASH) &&
4591 rb_method_basic_definition_p(CLASS_OF(obj), id_each))
4592 hash_sum(obj, &memo);
4593 else
4594 rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
4595
4596 if (memo.float_value) {
4597 return DBL2NUM(memo.f + memo.c);
4598 }
4599 else {
4600 if (memo.n != 0)
4601 memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
4602 if (!UNDEF_P(memo.r)) {
4603 memo.v = rb_rational_plus(memo.r, memo.v);
4604 }
4605 return memo.v;
4606 }
4607}
4608
4609static VALUE
4610uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
4611{
4612 ENUM_WANT_SVALUE();
4613 rb_hash_add_new_element(hash, i, i);
4614 return Qnil;
4615}
4616
4617static VALUE
4618uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
4619{
4620 ENUM_WANT_SVALUE();
4621 rb_hash_add_new_element(hash, rb_yield_values2(argc, argv), i);
4622 return Qnil;
4623}
4624
4625/*
4626 * call-seq:
4627 * uniq -> array
4628 * uniq {|element| ... } -> array
4629 *
4630 * With no block, returns a new array containing only unique elements;
4631 * the array has no two elements +e0+ and +e1+ such that <tt>e0.eql?(e1)</tt>:
4632 *
4633 * %w[a b c c b a a b c].uniq # => ["a", "b", "c"]
4634 * [0, 1, 2, 2, 1, 0, 0, 1, 2].uniq # => [0, 1, 2]
4635 *
4636 * With a block, returns a new array containing only for which the block
4637 * returns a unique value:
4638 *
4639 * a = [0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1]
4640 * a.uniq {|i| i.even? ? i : 0 } # => [0, 2, 4]
4641 * a = %w[a b c d e e d c b a a b c d e]
4642 a.uniq {|c| c < 'c' } # => ["a", "c"]
4643 *
4644 */
4645
4646static VALUE
4647enum_uniq(VALUE obj)
4648{
4649 VALUE hash, ret;
4650 rb_block_call_func *const func =
4651 rb_block_given_p() ? uniq_iter : uniq_func;
4652
4653 hash = rb_obj_hide(rb_hash_new());
4654 rb_block_call(obj, id_each, 0, 0, func, hash);
4655 ret = rb_hash_values(hash);
4656 rb_hash_clear(hash);
4657 return ret;
4658}
4659
4660static VALUE
4661compact_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
4662{
4663 ENUM_WANT_SVALUE();
4664
4665 if (!NIL_P(i)) {
4666 rb_ary_push(ary, i);
4667 }
4668 return Qnil;
4669}
4670
4671/*
4672 * call-seq:
4673 * compact -> array
4674 *
4675 * Returns an array of all non-+nil+ elements:
4676 *
4677 * a = [nil, 0, nil, 'a', false, nil, false, nil, 'a', nil, 0, nil]
4678 * a.compact # => [0, "a", false, false, "a", 0]
4679 *
4680 */
4681
4682static VALUE
4683enum_compact(VALUE obj)
4684{
4685 VALUE ary;
4686
4687 ary = rb_ary_new();
4688 rb_block_call(obj, id_each, 0, 0, compact_i, ary);
4689
4690 return ary;
4691}
4692
4693
4694/*
4695 * == What's Here
4696 *
4697 * \Module \Enumerable provides methods that are useful to a collection class for:
4698 *
4699 * - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying]
4700 * - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching]
4701 * - {Searching}[rdoc-ref:Enumerable@Methods+for+Searching]
4702 * - {Sorting}[rdoc-ref:Enumerable@Methods+for+Sorting]
4703 * - {Iterating}[rdoc-ref:Enumerable@Methods+for+Iterating]
4704 * - {And more....}[rdoc-ref:Enumerable@Other+Methods]
4705 *
4706 * === Methods for Querying
4707 *
4708 * These methods return information about the \Enumerable other than the elements themselves:
4709 *
4710 * - #include?, #member?: Returns +true+ if <tt>self == object</tt>, +false+ otherwise.
4711 * - #all?: Returns +true+ if all elements meet a specified criterion; +false+ otherwise.
4712 * - #any?: Returns +true+ if any element meets a specified criterion; +false+ otherwise.
4713 * - #none?: Returns +true+ if no element meets a specified criterion; +false+ otherwise.
4714 * - #one?: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise.
4715 * - #count: Returns the count of elements,
4716 * based on an argument or block criterion, if given.
4717 * - #tally: Returns a new \Hash containing the counts of occurrences of each element.
4718 *
4719 * === Methods for Fetching
4720 *
4721 * These methods return entries from the \Enumerable, without modifying it:
4722 *
4723 * <i>Leading, trailing, or all elements</i>:
4724 *
4725 * - #entries, #to_a: Returns all elements.
4726 * - #first: Returns the first element or leading elements.
4727 * - #take: Returns a specified number of leading elements.
4728 * - #drop: Returns a specified number of trailing elements.
4729 * - #take_while: Returns leading elements as specified by the given block.
4730 * - #drop_while: Returns trailing elements as specified by the given block.
4731 *
4732 * <i>Minimum and maximum value elements</i>:
4733 *
4734 * - #min: Returns the elements whose values are smallest among the elements,
4735 * as determined by <tt><=></tt> or a given block.
4736 * - #max: Returns the elements whose values are largest among the elements,
4737 * as determined by <tt><=></tt> or a given block.
4738 * - #minmax: Returns a 2-element \Array containing the smallest and largest elements.
4739 * - #min_by: Returns the smallest element, as determined by the given block.
4740 * - #max_by: Returns the largest element, as determined by the given block.
4741 * - #minmax_by: Returns the smallest and largest elements, as determined by the given block.
4742 *
4743 * <i>Groups, slices, and partitions</i>:
4744 *
4745 * - #group_by: Returns a \Hash that partitions the elements into groups.
4746 * - #partition: Returns elements partitioned into two new Arrays, as determined by the given block.
4747 * - #slice_after: Returns a new \Enumerator whose entries are a partition of +self+,
4748 based either on a given +object+ or a given block.
4749 * - #slice_before: Returns a new \Enumerator whose entries are a partition of +self+,
4750 based either on a given +object+ or a given block.
4751 * - #slice_when: Returns a new \Enumerator whose entries are a partition of +self+
4752 based on the given block.
4753 * - #chunk: Returns elements organized into chunks as specified by the given block.
4754 * - #chunk_while: Returns elements organized into chunks as specified by the given block.
4755 *
4756 * === Methods for Searching and Filtering
4757 *
4758 * These methods return elements that meet a specified criterion:
4759 *
4760 * - #find, #detect: Returns an element selected by the block.
4761 * - #find_all, #filter, #select: Returns elements selected by the block.
4762 * - #find_index: Returns the index of an element selected by a given object or block.
4763 * - #reject: Returns elements not rejected by the block.
4764 * - #uniq: Returns elements that are not duplicates.
4765 *
4766 * === Methods for Sorting
4767 *
4768 * These methods return elements in sorted order:
4769 *
4770 * - #sort: Returns the elements, sorted by <tt><=></tt> or the given block.
4771 * - #sort_by: Returns the elements, sorted by the given block.
4772 *
4773 * === Methods for Iterating
4774 *
4775 * - #each_entry: Calls the block with each successive element
4776 * (slightly different from #each).
4777 * - #each_with_index: Calls the block with each successive element and its index.
4778 * - #each_with_object: Calls the block with each successive element and a given object.
4779 * - #each_slice: Calls the block with successive non-overlapping slices.
4780 * - #each_cons: Calls the block with successive overlapping slices.
4781 * (different from #each_slice).
4782 * - #reverse_each: Calls the block with each successive element, in reverse order.
4783 *
4784 * === Other Methods
4785 *
4786 * - #map, #collect: Returns objects returned by the block.
4787 * - #filter_map: Returns truthy objects returned by the block.
4788 * - #flat_map, #collect_concat: Returns flattened objects returned by the block.
4789 * - #grep: Returns elements selected by a given object
4790 * or objects returned by a given block.
4791 * - #grep_v: Returns elements selected by a given object
4792 * or objects returned by a given block.
4793 * - #reduce, #inject: Returns the object formed by combining all elements.
4794 * - #sum: Returns the sum of the elements, using method <tt>+</tt>.
4795 * - #zip: Combines each element with elements from other enumerables;
4796 * returns the n-tuples or calls the block with each.
4797 * - #cycle: Calls the block with each element, cycling repeatedly.
4798 *
4799 * == Usage
4800 *
4801 * To use module \Enumerable in a collection class:
4802 *
4803 * - Include it:
4804 *
4805 * include Enumerable
4806 *
4807 * - Implement method <tt>#each</tt>
4808 * which must yield successive elements of the collection.
4809 * The method will be called by almost any \Enumerable method.
4810 *
4811 * Example:
4812 *
4813 * class Foo
4814 * include Enumerable
4815 * def each
4816 * yield 1
4817 * yield 1, 2
4818 * yield
4819 * end
4820 * end
4821 * Foo.new.each_entry{ |element| p element }
4822 *
4823 * Output:
4824 *
4825 * 1
4826 * [1, 2]
4827 * nil
4828 *
4829 * == \Enumerable in Ruby Classes
4830 *
4831 * These Ruby core classes include (or extend) \Enumerable:
4832 *
4833 * - ARGF
4834 * - Array
4835 * - Dir
4836 * - Enumerator
4837 * - ENV (extends)
4838 * - Hash
4839 * - IO
4840 * - Range
4841 * - Struct
4842 *
4843 * These Ruby standard library classes include \Enumerable:
4844 *
4845 * - CSV
4846 * - CSV::Table
4847 * - CSV::Row
4848 * - Set
4849 *
4850 * Virtually all methods in \Enumerable call method +#each+ in the including class:
4851 *
4852 * - <tt>Hash#each</tt> yields the next key-value pair as a 2-element \Array.
4853 * - <tt>Struct#each</tt> yields the next name-value pair as a 2-element \Array.
4854 * - For the other classes above, +#each+ yields the next object from the collection.
4855 *
4856 * == About the Examples
4857 *
4858 * The example code snippets for the \Enumerable methods:
4859 *
4860 * - Always show the use of one or more \Array-like classes (often \Array itself).
4861 * - Sometimes show the use of a \Hash-like class.
4862 * For some methods, though, the usage would not make sense,
4863 * and so it is not shown. Example: #tally would find exactly one of each \Hash entry.
4864 *
4865 */
4866
4867void
4868Init_Enumerable(void)
4869{
4870 rb_mEnumerable = rb_define_module("Enumerable");
4871
4872 rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
4873 rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
4874 rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
4875
4876 rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
4877 rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
4878 rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
4879 rb_define_method(rb_mEnumerable, "grep_v", enum_grep_v, 1);
4880 rb_define_method(rb_mEnumerable, "count", enum_count, -1);
4881 rb_define_method(rb_mEnumerable, "find", enum_find, -1);
4882 rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
4883 rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
4884 rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
4885 rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
4886 rb_define_method(rb_mEnumerable, "filter", enum_find_all, 0);
4887 rb_define_method(rb_mEnumerable, "filter_map", enum_filter_map, 0);
4888 rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
4889 rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
4890 rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
4891 rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
4892 rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
4893 rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
4894 rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
4895 rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
4896 rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
4897 rb_define_method(rb_mEnumerable, "tally", enum_tally, -1);
4898 rb_define_method(rb_mEnumerable, "first", enum_first, -1);
4899 rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
4900 rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
4901 rb_define_method(rb_mEnumerable, "one?", enum_one, -1);
4902 rb_define_method(rb_mEnumerable, "none?", enum_none, -1);
4903 rb_define_method(rb_mEnumerable, "min", enum_min, -1);
4904 rb_define_method(rb_mEnumerable, "max", enum_max, -1);
4905 rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
4906 rb_define_method(rb_mEnumerable, "min_by", enum_min_by, -1);
4907 rb_define_method(rb_mEnumerable, "max_by", enum_max_by, -1);
4908 rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
4909 rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
4910 rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
4911 rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
4912 rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
4913 rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
4914 rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
4915 rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
4916 rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
4917 rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
4918 rb_define_method(rb_mEnumerable, "take", enum_take, 1);
4919 rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
4920 rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
4921 rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
4922 rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
4923 rb_define_method(rb_mEnumerable, "chunk", enum_chunk, 0);
4924 rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
4925 rb_define_method(rb_mEnumerable, "slice_after", enum_slice_after, -1);
4926 rb_define_method(rb_mEnumerable, "slice_when", enum_slice_when, 0);
4927 rb_define_method(rb_mEnumerable, "chunk_while", enum_chunk_while, 0);
4928 rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
4929 rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0);
4930 rb_define_method(rb_mEnumerable, "compact", enum_compact, 0);
4931
4932 id__alone = rb_intern_const("_alone");
4933 id__separator = rb_intern_const("_separator");
4934 id_chunk_categorize = rb_intern_const("chunk_categorize");
4935 id_chunk_enumerable = rb_intern_const("chunk_enumerable");
4936 id_next = rb_intern_const("next");
4937 id_sliceafter_enum = rb_intern_const("sliceafter_enum");
4938 id_sliceafter_pat = rb_intern_const("sliceafter_pat");
4939 id_sliceafter_pred = rb_intern_const("sliceafter_pred");
4940 id_slicebefore_enumerable = rb_intern_const("slicebefore_enumerable");
4941 id_slicebefore_sep_pat = rb_intern_const("slicebefore_sep_pat");
4942 id_slicebefore_sep_pred = rb_intern_const("slicebefore_sep_pred");
4943 id_slicewhen_enum = rb_intern_const("slicewhen_enum");
4944 id_slicewhen_inverted = rb_intern_const("slicewhen_inverted");
4945 id_slicewhen_pred = rb_intern_const("slicewhen_pred");
4946}
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
VALUE rb_define_module(const char *name)
Defines a top-level module.
Definition class.c:1033
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:2574
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:868
#define TYPE(_)
Old name of rb_type.
Definition value_type.h:107
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition value_type.h:87
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition double.h:28
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
Definition assume.h:28
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition value_type.h:64
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
Definition long.h:60
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
#define SYM2ID
Old name of RB_SYM2ID.
Definition symbol.h:45
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:203
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition array.h:653
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
#define FIX2ULONG
Old name of RB_FIX2ULONG.
Definition long.h:47
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
#define T_HASH
Old name of RUBY_T_HASH.
Definition value_type.h:65
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:652
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
#define T_UNDEF
Old name of RUBY_T_UNDEF.
Definition value_type.h:82
#define Qtrue
Old name of RUBY_Qtrue.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
Definition fixnum.h:26
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition symbol.h:47
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:651
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition value_type.h:77
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition error.c:3150
void rb_iter_break(void)
Breaks from a block.
Definition vm.c:1901
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1091
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1089
VALUE rb_eStopIteration
StopIteration exception.
Definition enumerator.c:176
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
Definition error.c:411
VALUE rb_eArgError
ArgumentError exception.
Definition error.c:1092
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:442
VALUE rb_cArray
Array class.
Definition array.c:40
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition object.c:1939
VALUE rb_mEnumerable
Enumerable module.
Definition enum.c:27
VALUE rb_cEnumerator
Enumerator class.
Definition enumerator.c:158
VALUE rb_cInteger
Module class.
Definition numeric.c:192
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:84
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:190
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3623
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:122
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition rgengc.h:232
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition rgengc.h:220
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1102
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it only takes public methods into account.
Definition vm_eval.c:1153
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:206
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition enumerator.h:239
#define rb_check_frozen
Just another name of rb_check_frozen.
Definition error.h:264
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:280
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
Definition proc.c:848
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
Definition range.c:1490
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:2640
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition variable.c:1226
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1606
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1218
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:2805
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition vm_eval.c:664
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
Definition vm_method.c:2789
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:276
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition symbol.c:1085
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
Definition symbol.c:943
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1369
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition vm_eval.c:1391
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1357
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition iterator.h:88
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
Definition iterator.h:83
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
Definition vm_eval.c:1602
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:161
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:68
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition rarray.h:566
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
Definition rarray.h:518
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
Definition rarray.h:546
#define RARRAY_AREF(a, i)
Definition rarray.h:583
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition rstring.h:498
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
MEMO.
Definition imemo.h:104
Definition enum.c:2149
Definition enum.c:2026
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:263
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:432
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:375