Ruby  2.1.10p492(2016-04-01revision54464)
enum.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  enum.c -
4 
5  $Author: nagachika $
6  created at: Fri Oct 1 15:15:19 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 #include "ruby/util.h"
14 #include "node.h"
15 #include "id.h"
16 #include "internal.h"
17 
18 VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
19 
21 
22 static ID id_next;
23 static ID id_div;
24 static ID id_call;
25 static ID id_size;
26 
27 #define id_each idEach
28 #define id_eqq idEqq
29 #define id_cmp idCmp
30 #define id_lshift idLTLT
31 
32 VALUE
34 {
35  if (argc == 0) return Qnil;
36  if (argc == 1) return argv[0];
37  return rb_ary_new4(argc, argv);
38 }
39 
40 #define ENUM_WANT_SVALUE() do { \
41  i = rb_enum_values_pack(argc, argv); \
42 } while (0)
43 
44 #define enum_yield rb_yield_values2
45 
46 static VALUE
48 {
49  NODE *memo = RNODE(args);
51 
52  if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
53  rb_ary_push(memo->u2.value, i);
54  }
55  return Qnil;
56 }
57 
58 static VALUE
59 grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
60 {
61  NODE *memo = RNODE(args);
63 
64  if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
65  rb_ary_push(memo->u2.value, rb_yield(i));
66  }
67  return Qnil;
68 }
69 
70 /*
71  * call-seq:
72  * enum.grep(pattern) -> array
73  * enum.grep(pattern) { |obj| block } -> array
74  *
75  * Returns an array of every element in <i>enum</i> for which
76  * <code>Pattern === element</code>. If the optional <em>block</em> is
77  * supplied, each matching element is passed to it, and the block's
78  * result is stored in the output array.
79  *
80  * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
81  * c = IO.constants
82  * c.grep(/SEEK/) #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
83  * res = c.grep(/SEEK/) { |v| IO.const_get(v) }
84  * res #=> [0, 1, 2]
85  *
86  */
87 
88 static VALUE
90 {
91  VALUE ary = rb_ary_new();
92  NODE *memo = NEW_MEMO(pat, ary, 0);
93 
94  rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
95 
96  return ary;
97 }
98 
99 static VALUE
100 count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
101 {
102  NODE *memo = RNODE(memop);
103 
105 
106  if (rb_equal(i, memo->u1.value)) {
107  memo->u3.cnt++;
108  }
109  return Qnil;
110 }
111 
112 static VALUE
113 count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
114 {
115  NODE *memo = RNODE(memop);
116 
118  memo->u3.cnt++;
119  }
120  return Qnil;
121 }
122 
123 static VALUE
124 count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
125 {
126  NODE *memo = RNODE(memop);
127 
128  memo->u3.cnt++;
129  return Qnil;
130 }
131 
132 /*
133  * call-seq:
134  * enum.count -> int
135  * enum.count(item) -> int
136  * enum.count { |obj| block } -> int
137  *
138  * Returns the number of items in +enum+ through enumeration.
139  * If an argument is given, the number of items in +enum+ that
140  * are equal to +item+ are counted. If a block is given, it
141  * counts the number of elements yielding a true value.
142  *
143  * ary = [1, 2, 4, 2]
144  * ary.count #=> 4
145  * ary.count(2) #=> 2
146  * ary.count{ |x| x%2==0 } #=> 3
147  *
148  */
149 
150 static VALUE
152 {
153  VALUE item = Qnil;
154  NODE *memo;
156 
157  if (argc == 0) {
158  if (rb_block_given_p()) {
159  func = count_iter_i;
160  }
161  else {
162  func = count_all_i;
163  }
164  }
165  else {
166  rb_scan_args(argc, argv, "1", &item);
167  if (rb_block_given_p()) {
168  rb_warn("given block not used");
169  }
170  func = count_i;
171  }
172 
173  memo = NEW_MEMO(item, 0, 0);
174  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
175  return INT2NUM(memo->u3.cnt);
176 }
177 
178 static VALUE
179 find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
180 {
182 
183  if (RTEST(rb_yield(i))) {
184  NODE *memo = RNODE(memop);
185  memo->u1.value = i;
186  memo->u3.cnt = 1;
187  rb_iter_break();
188  }
189  return Qnil;
190 }
191 
192 /*
193  * call-seq:
194  * enum.detect(ifnone = nil) { |obj| block } -> obj or nil
195  * enum.find(ifnone = nil) { |obj| block } -> obj or nil
196  * enum.detect(ifnone = nil) -> an_enumerator
197  * enum.find(ifnone = nil) -> an_enumerator
198  *
199  * Passes each entry in <i>enum</i> to <em>block</em>. Returns the
200  * first for which <em>block</em> is not false. If no
201  * object matches, calls <i>ifnone</i> and returns its result when it
202  * is specified, or returns <code>nil</code> otherwise.
203  *
204  * If no block is given, an enumerator is returned instead.
205  *
206  * (1..10).detect { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
207  * (1..100).find { |i| i % 5 == 0 and i % 7 == 0 } #=> 35
208  *
209  */
210 
211 static VALUE
213 {
214  NODE *memo;
215  VALUE if_none;
216 
217  rb_scan_args(argc, argv, "01", &if_none);
218  RETURN_ENUMERATOR(obj, argc, argv);
219  memo = NEW_MEMO(Qundef, 0, 0);
220  rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
221  if (memo->u3.cnt) {
222  return memo->u1.value;
223  }
224  if (!NIL_P(if_none)) {
225  return rb_funcall(if_none, id_call, 0, 0);
226  }
227  return Qnil;
228 }
229 
230 static VALUE
231 find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
232 {
233  NODE *memo = RNODE(memop);
234 
236 
237  if (rb_equal(i, memo->u2.value)) {
238  memo->u1.value = UINT2NUM(memo->u3.cnt);
239  rb_iter_break();
240  }
241  memo->u3.cnt++;
242  return Qnil;
243 }
244 
245 static VALUE
246 find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
247 {
248  NODE *memo = RNODE(memop);
249 
250  if (RTEST(enum_yield(argc, argv))) {
251  memo->u1.value = UINT2NUM(memo->u3.cnt);
252  rb_iter_break();
253  }
254  memo->u3.cnt++;
255  return Qnil;
256 }
257 
258 /*
259  * call-seq:
260  * enum.find_index(value) -> int or nil
261  * enum.find_index { |obj| block } -> int or nil
262  * enum.find_index -> an_enumerator
263  *
264  * Compares each entry in <i>enum</i> with <em>value</em> or passes
265  * to <em>block</em>. Returns the index for the first for which the
266  * evaluated value is non-false. If no object matches, returns
267  * <code>nil</code>
268  *
269  * If neither block nor argument is given, an enumerator is returned instead.
270  *
271  * (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
272  * (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
273  * (1..100).find_index(50) #=> 49
274  *
275  */
276 
277 static VALUE
279 {
280  NODE *memo; /* [return value, current index, ] */
281  VALUE condition_value = Qnil;
283 
284  if (argc == 0) {
285  RETURN_ENUMERATOR(obj, 0, 0);
286  func = find_index_iter_i;
287  }
288  else {
289  rb_scan_args(argc, argv, "1", &condition_value);
290  if (rb_block_given_p()) {
291  rb_warn("given block not used");
292  }
293  func = find_index_i;
294  }
295 
296  memo = NEW_MEMO(Qnil, condition_value, 0);
297  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
298  return memo->u1.value;
299 }
300 
301 static VALUE
302 find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
303 {
305 
306  if (RTEST(rb_yield(i))) {
307  rb_ary_push(ary, i);
308  }
309  return Qnil;
310 }
311 
312 static VALUE
314 {
315  VALUE r;
316  r = rb_check_funcall(self, id_size, 0, 0);
317  return (r == Qundef) ? Qnil : r;
318 }
319 
320 /*
321  * call-seq:
322  * enum.find_all { |obj| block } -> array
323  * enum.select { |obj| block } -> array
324  * enum.find_all -> an_enumerator
325  * enum.select -> an_enumerator
326  *
327  * Returns an array containing all elements of +enum+
328  * for which the given +block+ returns a true value.
329  *
330  * If no block is given, an Enumerator is returned instead.
331  *
332  *
333  * (1..10).find_all { |i| i % 3 == 0 } #=> [3, 6, 9]
334  *
335  * [1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
336  *
337  * See also Enumerable#reject.
338  */
339 
340 static VALUE
342 {
343  VALUE ary;
344 
346 
347  ary = rb_ary_new();
348  rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
349 
350  return ary;
351 }
352 
353 static VALUE
355 {
357 
358  if (!RTEST(rb_yield(i))) {
359  rb_ary_push(ary, i);
360  }
361  return Qnil;
362 }
363 
364 /*
365  * call-seq:
366  * enum.reject { |obj| block } -> array
367  * enum.reject -> an_enumerator
368  *
369  * Returns an array for all elements of +enum+ for which the given
370  * +block+ returns false.
371  *
372  * If no block is given, an Enumerator is returned instead.
373  *
374  * (1..10).reject { |i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
375  *
376  * [1, 2, 3, 4, 5].reject { |num| num.even? } #=> [1, 3, 5]
377  *
378  * See also Enumerable#find_all.
379  */
380 
381 static VALUE
383 {
384  VALUE ary;
385 
387 
388  ary = rb_ary_new();
389  rb_block_call(obj, id_each, 0, 0, reject_i, ary);
390 
391  return ary;
392 }
393 
394 static VALUE
395 collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
396 {
398 
399  return Qnil;
400 }
401 
402 static VALUE
403 collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
404 {
407 
408  return Qnil;
409 }
410 
411 /*
412  * call-seq:
413  * enum.collect { |obj| block } -> array
414  * enum.map { |obj| block } -> array
415  * enum.collect -> an_enumerator
416  * enum.map -> an_enumerator
417  *
418  * Returns a new array with the results of running <em>block</em> once
419  * for every element in <i>enum</i>.
420  *
421  * If no block is given, an enumerator is returned instead.
422  *
423  * (1..4).map { |i| i*i } #=> [1, 4, 9, 16]
424  * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
425  *
426  */
427 
428 static VALUE
430 {
431  VALUE ary;
432 
434 
435  ary = rb_ary_new();
436  rb_block_call(obj, id_each, 0, 0, collect_i, ary);
437 
438  return ary;
439 }
440 
441 static VALUE
442 flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
443 {
444  VALUE tmp;
445 
448 
449  if (NIL_P(tmp)) {
450  rb_ary_push(ary, i);
451  }
452  else {
453  rb_ary_concat(ary, tmp);
454  }
455  return Qnil;
456 }
457 
458 /*
459  * call-seq:
460  * enum.flat_map { |obj| block } -> array
461  * enum.collect_concat { |obj| block } -> array
462  * enum.flat_map -> an_enumerator
463  * enum.collect_concat -> an_enumerator
464  *
465  * Returns a new array with the concatenated results of running
466  * <em>block</em> once for every element in <i>enum</i>.
467  *
468  * If no block is given, an enumerator is returned instead.
469  *
470  * [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
471  * [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
472  *
473  */
474 
475 static VALUE
477 {
478  VALUE ary;
479 
481 
482  ary = rb_ary_new();
483  rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
484 
485  return ary;
486 }
487 
488 /*
489  * call-seq:
490  * enum.to_a(*args) -> array
491  * enum.entries(*args) -> array
492  *
493  * Returns an array containing the items in <i>enum</i>.
494  *
495  * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
496  * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
497  *
498  * require 'prime'
499  * Prime.entries 10 #=> [2, 3, 5, 7]
500  */
501 static VALUE
503 {
504  VALUE ary = rb_ary_new();
505 
506  rb_block_call(obj, id_each, argc, argv, collect_all, ary);
507  OBJ_INFECT(ary, obj);
508 
509  return ary;
510 }
511 
512 static VALUE
513 enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
514 {
518  key_value_pair = rb_check_array_type(i);
519  if (NIL_P(key_value_pair)) {
520  rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
522  }
523  if (RARRAY_LEN(key_value_pair) != 2) {
524  rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
525  RARRAY_LEN(key_value_pair));
526  }
527  rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
528  return Qnil;
529 }
530 
531 /*
532  * call-seq:
533  * enum.to_h(*args) -> hash
534  *
535  * Returns the result of interpreting <i>enum</i> as a list of
536  * <tt>[key, value]</tt> pairs.
537  *
538  * %i[hello world].each_with_index.to_h
539  * # => {:hello => 0, :world => 1}
540  */
541 
542 static VALUE
544 {
545  VALUE hash = rb_hash_new();
546  rb_block_call(obj, id_each, argc, argv, enum_to_h_i, hash);
547  OBJ_INFECT(hash, obj);
548  return hash;
549 }
550 
551 static VALUE
552 inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
553 {
554  NODE *memo = RNODE(p);
555 
557 
558  if (memo->u2.argc == 0) {
559  memo->u2.argc = 1;
560  memo->u1.value = i;
561  }
562  else {
563  memo->u1.value = rb_yield_values(2, memo->u1.value, i);
564  }
565  return Qnil;
566 }
567 
568 static VALUE
569 inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
570 {
571  NODE *memo = RNODE(p);
573 
575 
576  if (memo->u2.argc == 0) {
577  memo->u2.argc = 1;
578  memo->u1.value = i;
579  }
580  else if (SYMBOL_P(name = memo->u3.value)) {
581  memo->u1.value = rb_funcall(memo->u1.value, SYM2ID(name), 1, i);
582  }
583  else {
584  VALUE args[2];
585  args[0] = name;
586  args[1] = i;
587  memo->u1.value = rb_f_send(numberof(args), args, memo->u1.value);
588  }
589  return Qnil;
590 }
591 
592 /*
593  * call-seq:
594  * enum.inject(initial, sym) -> obj
595  * enum.inject(sym) -> obj
596  * enum.inject(initial) { |memo, obj| block } -> obj
597  * enum.inject { |memo, obj| block } -> obj
598  * enum.reduce(initial, sym) -> obj
599  * enum.reduce(sym) -> obj
600  * enum.reduce(initial) { |memo, obj| block } -> obj
601  * enum.reduce { |memo, obj| block } -> obj
602  *
603  * Combines all elements of <i>enum</i> by applying a binary
604  * operation, specified by a block or a symbol that names a
605  * method or operator.
606  *
607  * If you specify a block, then for each element in <i>enum</i>
608  * the block is passed an accumulator value (<i>memo</i>) and the element.
609  * If you specify a symbol instead, then each element in the collection
610  * will be passed to the named method of <i>memo</i>.
611  * In either case, the result becomes the new value for <i>memo</i>.
612  * At the end of the iteration, the final value of <i>memo</i> is the
613  * return value for the method.
614  *
615  * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
616  * then the first element of collection is used as the initial value
617  * of <i>memo</i>.
618  *
619  *
620  * # Sum some numbers
621  * (5..10).reduce(:+) #=> 45
622  * # Same using a block and inject
623  * (5..10).inject { |sum, n| sum + n } #=> 45
624  * # Multiply some numbers
625  * (5..10).reduce(1, :*) #=> 151200
626  * # Same using a block
627  * (5..10).inject(1) { |product, n| product * n } #=> 151200
628  * # find the longest word
629  * longest = %w{ cat sheep bear }.inject do |memo, word|
630  * memo.length > word.length ? memo : word
631  * end
632  * longest #=> "sheep"
633  *
634  */
635 static VALUE
637 {
638  NODE *memo;
639  VALUE init, op;
640  rb_block_call_func *iter = inject_i;
641  ID id;
642 
643  switch (rb_scan_args(argc, argv, "02", &init, &op)) {
644  case 0:
645  break;
646  case 1:
647  if (rb_block_given_p()) {
648  break;
649  }
650  id = rb_check_id(&init);
651  op = id ? ID2SYM(id) : init;
652  argc = 0;
653  init = Qnil;
654  iter = inject_op_i;
655  break;
656  case 2:
657  if (rb_block_given_p()) {
658  rb_warning("given block not used");
659  }
660  id = rb_check_id(&op);
661  if (id) op = ID2SYM(id);
662  iter = inject_op_i;
663  break;
664  }
665  memo = NEW_MEMO(init, argc, op);
666  rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
667  return memo->u1.value;
668 }
669 
670 static VALUE
671 partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
672 {
673  NODE *memo = RNODE(arys);
676 
677  if (RTEST(rb_yield(i))) {
678  ary = memo->u1.value;
679  }
680  else {
681  ary = memo->u2.value;
682  }
683  rb_ary_push(ary, i);
684  return Qnil;
685 }
686 
687 /*
688  * call-seq:
689  * enum.partition { |obj| block } -> [ true_array, false_array ]
690  * enum.partition -> an_enumerator
691  *
692  * Returns two arrays, the first containing the elements of
693  * <i>enum</i> for which the block evaluates to true, the second
694  * containing the rest.
695  *
696  * If no block is given, an enumerator is returned instead.
697  *
698  * (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
699  *
700  */
701 
702 static VALUE
704 {
705  NODE *memo;
706 
708 
709  memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
710  rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
711 
712  return rb_assoc_new(memo->u1.value, memo->u2.value);
713 }
714 
715 static VALUE
716 group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
717 {
718  VALUE group;
720 
722 
723  group = rb_yield(i);
724  values = rb_hash_aref(hash, group);
725  if (!RB_TYPE_P(values, T_ARRAY)) {
726  values = rb_ary_new3(1, i);
727  rb_hash_aset(hash, group, values);
728  }
729  else {
730  rb_ary_push(values, i);
731  }
732  return Qnil;
733 }
734 
735 /*
736  * call-seq:
737  * enum.group_by { |obj| block } -> a_hash
738  * enum.group_by -> an_enumerator
739  *
740  * Groups the collection by result of the block. Returns a hash where the
741  * keys are the evaluated result from the block and the values are
742  * arrays of elements in the collection that correspond to the key.
743  *
744  * If no block is given an enumerator is returned.
745  *
746  * (1..6).group_by { |i| i%3 } #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
747  *
748  */
749 
750 static VALUE
752 {
753  VALUE hash;
754 
756 
757  hash = rb_hash_new();
758  rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
759  OBJ_INFECT(hash, obj);
760 
761  return hash;
762 }
763 
764 static VALUE
765 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
766 {
767  NODE *memo = RNODE(params);
769 
770  memo->u1.value = i;
771  rb_iter_break();
772 
774 }
775 
776 static VALUE enum_take(VALUE obj, VALUE n);
777 
778 /*
779  * call-seq:
780  * enum.first -> obj or nil
781  * enum.first(n) -> an_array
782  *
783  * Returns the first element, or the first +n+ elements, of the enumerable.
784  * If the enumerable is empty, the first form returns <code>nil</code>, and the
785  * second form returns an empty array.
786  *
787  * %w[foo bar baz].first #=> "foo"
788  * %w[foo bar baz].first(2) #=> ["foo", "bar"]
789  * %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
790  * [].first #=> nil
791  *
792  */
793 
794 static VALUE
796 {
797  NODE *memo;
798  rb_check_arity(argc, 0, 1);
799  if (argc > 0) {
800  return enum_take(obj, argv[0]);
801  }
802  else {
803  memo = NEW_MEMO(Qnil, 0, 0);
804  rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
805  return memo->u1.value;
806  }
807 }
808 
809 
810 /*
811  * call-seq:
812  * enum.sort -> array
813  * enum.sort { |a, b| block } -> array
814  *
815  * Returns an array containing the items in <i>enum</i> sorted,
816  * either according to their own <code><=></code> method, or by using
817  * the results of the supplied block. The block should return -1, 0, or
818  * +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
819  * Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
820  * built-in Schwartzian Transform, useful when key computation or
821  * comparison is expensive.
822  *
823  * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
824  * (1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
825  */
826 
827 static VALUE
829 {
830  return rb_ary_sort(enum_to_a(0, 0, obj));
831 }
832 
833 #define SORT_BY_BUFSIZE 16
834 struct sort_by_data {
837  long n;
838 };
839 
840 static VALUE
841 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
842 {
843  struct sort_by_data *data = (struct sort_by_data *)&RNODE(_data)->u1;
844  VALUE ary = data->ary;
846 
848 
849  v = rb_yield(i);
850 
851  if (RBASIC(ary)->klass) {
852  rb_raise(rb_eRuntimeError, "sort_by reentered");
853  }
854  if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
855  rb_raise(rb_eRuntimeError, "sort_by reentered");
856  }
857 
858  RARRAY_ASET(data->buf, data->n*2, v);
859  RARRAY_ASET(data->buf, data->n*2+1, i);
860  data->n++;
861  if (data->n == SORT_BY_BUFSIZE) {
862  rb_ary_concat(ary, data->buf);
863  data->n = 0;
864  }
865  return Qnil;
866 }
867 
868 static int
869 sort_by_cmp(const void *ap, const void *bp, void *data)
870 {
871  VALUE a;
872  VALUE b;
873  VALUE ary = (VALUE)data;
874 
875  if (RBASIC(ary)->klass) {
876  rb_raise(rb_eRuntimeError, "sort_by reentered");
877  }
878 
879  a = *(VALUE *)ap;
880  b = *(VALUE *)bp;
881 
882  return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
883 }
884 
885 /*
886  * call-seq:
887  * enum.sort_by { |obj| block } -> array
888  * enum.sort_by -> an_enumerator
889  *
890  * Sorts <i>enum</i> using a set of keys generated by mapping the
891  * values in <i>enum</i> through the given block.
892  *
893  * If no block is given, an enumerator is returned instead.
894  *
895  * %w{apple pear fig}.sort_by { |word| word.length}
896  * #=> ["fig", "pear", "apple"]
897  *
898  * The current implementation of <code>sort_by</code> generates an
899  * array of tuples containing the original collection element and the
900  * mapped value. This makes <code>sort_by</code> fairly expensive when
901  * the keysets are simple.
902  *
903  * require 'benchmark'
904  *
905  * a = (1..100000).map { rand(100000) }
906  *
907  * Benchmark.bm(10) do |b|
908  * b.report("Sort") { a.sort }
909  * b.report("Sort by") { a.sort_by { |a| a } }
910  * end
911  *
912  * <em>produces:</em>
913  *
914  * user system total real
915  * Sort 0.180000 0.000000 0.180000 ( 0.175469)
916  * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
917  *
918  * However, consider the case where comparing the keys is a non-trivial
919  * operation. The following code sorts some files on modification time
920  * using the basic <code>sort</code> method.
921  *
922  * files = Dir["*"]
923  * sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
924  * sorted #=> ["mon", "tues", "wed", "thurs"]
925  *
926  * This sort is inefficient: it generates two new <code>File</code>
927  * objects during every comparison. A slightly better technique is to
928  * use the <code>Kernel#test</code> method to generate the modification
929  * times directly.
930  *
931  * files = Dir["*"]
932  * sorted = files.sort { |a, b|
933  * test(?M, a) <=> test(?M, b)
934  * }
935  * sorted #=> ["mon", "tues", "wed", "thurs"]
936  *
937  * This still generates many unnecessary <code>Time</code> objects. A
938  * more efficient technique is to cache the sort keys (modification
939  * times in this case) before the sort. Perl users often call this
940  * approach a Schwartzian Transform, after Randal Schwartz. We
941  * construct a temporary array, where each element is an array
942  * containing our sort key along with the filename. We sort this array,
943  * and then extract the filename from the result.
944  *
945  * sorted = Dir["*"].collect { |f|
946  * [test(?M, f), f]
947  * }.sort.collect { |f| f[1] }
948  * sorted #=> ["mon", "tues", "wed", "thurs"]
949  *
950  * This is exactly what <code>sort_by</code> does internally.
951  *
952  * sorted = Dir["*"].sort_by { |f| test(?M, f) }
953  * sorted #=> ["mon", "tues", "wed", "thurs"]
954  */
955 
956 static VALUE
958 {
959  VALUE ary, buf;
960  NODE *memo;
961  long i;
962  struct sort_by_data *data;
963 
965 
966  if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
967  ary = rb_ary_new2(RARRAY_LEN(obj)*2);
968  }
969  else {
970  ary = rb_ary_new();
971  }
972  RBASIC_CLEAR_CLASS(ary);
974  rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
975  memo = NEW_MEMO(0, 0, 0);
976  OBJ_INFECT(memo, obj);
977  data = (struct sort_by_data *)&memo->u1;
978  data->ary = ary;
979  data->buf = buf;
980  data->n = 0;
981  rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
982  ary = data->ary;
983  buf = data->buf;
984  if (data->n) {
985  rb_ary_resize(buf, data->n*2);
986  rb_ary_concat(ary, buf);
987  }
988  if (RARRAY_LEN(ary) > 2) {
989  RARRAY_PTR_USE(ary, ptr,
990  ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
991  sort_by_cmp, (void *)ary));
992  }
993  if (RBASIC(ary)->klass) {
994  rb_raise(rb_eRuntimeError, "sort_by reentered");
995  }
996  for (i=1; i<RARRAY_LEN(ary); i+=2) {
997  RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
998  }
999  rb_ary_resize(ary, RARRAY_LEN(ary)/2);
1001  OBJ_INFECT(ary, memo);
1002 
1003  return ary;
1004 }
1005 
1006 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
1007 
1008 #define DEFINE_ENUMFUNCS(name) \
1009 static VALUE enum_##name##_func(VALUE result, NODE *memo); \
1010 \
1011 static VALUE \
1012 name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1013 { \
1014  return enum_##name##_func(rb_enum_values_pack(argc, argv), RNODE(memo)); \
1015 } \
1016 \
1017 static VALUE \
1018 name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1019 { \
1020  return enum_##name##_func(enum_yield(argc, argv), RNODE(memo)); \
1021 } \
1022 \
1023 static VALUE \
1024 enum_##name##_func(VALUE result, NODE *memo)
1025 
1027 {
1028  if (!RTEST(result)) {
1029  memo->u1.value = Qfalse;
1030  rb_iter_break();
1031  }
1032  return Qnil;
1033 }
1034 
1035 /*
1036  * call-seq:
1037  * enum.all? [{ |obj| block } ] -> true or false
1038  *
1039  * Passes each element of the collection to the given block. The method
1040  * returns <code>true</code> if the block never returns
1041  * <code>false</code> or <code>nil</code>. If the block is not given,
1042  * Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
1043  * cause #all? to return +true+ when none of the collection members are
1044  * +false+ or +nil+.
1045  *
1046  * %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
1047  * %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
1048  * [nil, true, 99].all? #=> false
1049  *
1050  */
1051 
1052 static VALUE
1054 {
1055  NODE *memo = NEW_MEMO(Qtrue, 0, 0);
1056  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1057  return memo->u1.value;
1058 }
1059 
1061 {
1062  if (RTEST(result)) {
1063  memo->u1.value = Qtrue;
1064  rb_iter_break();
1065  }
1066  return Qnil;
1067 }
1068 
1069 /*
1070  * call-seq:
1071  * enum.any? [{ |obj| block }] -> true or false
1072  *
1073  * Passes each element of the collection to the given block. The method
1074  * returns <code>true</code> if the block ever returns a value other
1075  * than <code>false</code> or <code>nil</code>. If the block is not
1076  * given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
1077  * will cause #any? to return +true+ if at least one of the collection
1078  * members is not +false+ or +nil+.
1079  *
1080  * %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
1081  * %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
1082  * [nil, true, 99].any? #=> true
1083  *
1084  */
1085 
1086 static VALUE
1088 {
1089  NODE *memo = NEW_MEMO(Qfalse, 0, 0);
1090  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1091  return memo->u1.value;
1092 }
1093 
1095 {
1096  if (RTEST(result)) {
1097  if (memo->u1.value == Qundef) {
1098  memo->u1.value = Qtrue;
1099  }
1100  else if (memo->u1.value == Qtrue) {
1101  memo->u1.value = Qfalse;
1102  rb_iter_break();
1103  }
1104  }
1105  return Qnil;
1106 }
1107 
1108 /*
1109  * call-seq:
1110  * enum.one? [{ |obj| block }] -> true or false
1111  *
1112  * Passes each element of the collection to the given block. The method
1113  * returns <code>true</code> if the block returns <code>true</code>
1114  * exactly once. If the block is not given, <code>one?</code> will return
1115  * <code>true</code> only if exactly one of the collection members is
1116  * true.
1117  *
1118  * %w{ant bear cat}.one? { |word| word.length == 4 } #=> true
1119  * %w{ant bear cat}.one? { |word| word.length > 4 } #=> false
1120  * %w{ant bear cat}.one? { |word| word.length < 4 } #=> false
1121  * [ nil, true, 99 ].one? #=> false
1122  * [ nil, true, false ].one? #=> true
1123  *
1124  */
1125 
1126 static VALUE
1128 {
1129  NODE *memo = NEW_MEMO(Qundef, 0, 0);
1130  VALUE result;
1131 
1132  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1133  result = memo->u1.value;
1134  if (result == Qundef) return Qfalse;
1135  return result;
1136 }
1137 
1139 {
1140  if (RTEST(result)) {
1141  memo->u1.value = Qfalse;
1142  rb_iter_break();
1143  }
1144  return Qnil;
1145 }
1146 
1147 /*
1148  * call-seq:
1149  * enum.none? [{ |obj| block }] -> true or false
1150  *
1151  * Passes each element of the collection to the given block. The method
1152  * returns <code>true</code> if the block never returns <code>true</code>
1153  * for all elements. If the block is not given, <code>none?</code> will return
1154  * <code>true</code> only if none of the collection members is true.
1155  *
1156  * %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
1157  * %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
1158  * [].none? #=> true
1159  * [nil].none? #=> true
1160  * [nil, false].none? #=> true
1161  */
1162 static VALUE
1164 {
1165  NODE *memo = NEW_MEMO(Qtrue, 0, 0);
1166  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
1167  return memo->u1.value;
1168 }
1169 
1170 static VALUE
1172 {
1173  VALUE cmp;
1174  NODE *memo = RNODE(args);
1175 
1176  ENUM_WANT_SVALUE();
1177 
1178  if (memo->u1.value == Qundef) {
1179  memo->u1.value = i;
1180  }
1181  else {
1182  cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
1183  if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
1184  memo->u1.value = i;
1185  }
1186  }
1187  return Qnil;
1188 }
1189 
1190 static VALUE
1192 {
1193  VALUE cmp;
1194  NODE *memo = RNODE(args);
1195 
1196  ENUM_WANT_SVALUE();
1197 
1198  if (memo->u1.value == Qundef) {
1199  memo->u1.value = i;
1200  }
1201  else {
1202  cmp = rb_yield_values(2, i, memo->u1.value);
1203  if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
1204  memo->u1.value = i;
1205  }
1206  }
1207  return Qnil;
1208 }
1209 
1210 
1211 /*
1212  * call-seq:
1213  * enum.min -> obj
1214  * enum.min { |a, b| block } -> obj
1215  *
1216  * Returns the object in <i>enum</i> with the minimum value. The
1217  * first form assumes all objects implement <code>Comparable</code>;
1218  * the second uses the block to return <em>a <=> b</em>.
1219  *
1220  * a = %w(albatross dog horse)
1221  * a.min #=> "albatross"
1222  * a.min { |a, b| a.length <=> b.length } #=> "dog"
1223  */
1224 
1225 static VALUE
1227 {
1228  NODE *memo = NEW_MEMO(Qundef, 0, 0);
1229  VALUE result;
1230 
1231  if (rb_block_given_p()) {
1232  rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)memo);
1233  }
1234  else {
1235  rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)memo);
1236  }
1237  result = memo->u1.value;
1238  if (result == Qundef) return Qnil;
1239  return result;
1240 }
1241 
1242 static VALUE
1244 {
1245  NODE *memo = RNODE(args);
1247 
1248  ENUM_WANT_SVALUE();
1249 
1250  if (memo->u1.value == Qundef) {
1251  memo->u1.value = i;
1252  }
1253  else {
1254  cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
1255  if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
1256  memo->u1.value = i;
1257  }
1258  }
1259  return Qnil;
1260 }
1261 
1262 static VALUE
1264 {
1265  NODE *memo = RNODE(args);
1266  VALUE cmp;
1267 
1268  ENUM_WANT_SVALUE();
1269 
1270  if (memo->u1.value == Qundef) {
1271  memo->u1.value = i;
1272  }
1273  else {
1274  cmp = rb_yield_values(2, i, memo->u1.value);
1275  if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
1276  memo->u1.value = i;
1277  }
1278  }
1279  return Qnil;
1280 }
1281 
1282 /*
1283  * call-seq:
1284  * enum.max -> obj
1285  * enum.max { |a, b| block } -> obj
1286  *
1287  * Returns the object in _enum_ with the maximum value. The
1288  * first form assumes all objects implement <code>Comparable</code>;
1289  * the second uses the block to return <em>a <=> b</em>.
1290  *
1291  * a = %w(albatross dog horse)
1292  * a.max #=> "horse"
1293  * a.max { |a, b| a.length <=> b.length } #=> "albatross"
1294  */
1295 
1296 static VALUE
1298 {
1299  NODE *memo = NEW_MEMO(Qundef, 0, 0);
1300  VALUE result;
1301 
1302  if (rb_block_given_p()) {
1303  rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
1304  }
1305  else {
1306  rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
1307  }
1308  result = memo->u1.value;
1309  if (result == Qundef) return Qnil;
1310  return result;
1311 }
1312 
1313 struct minmax_t {
1317 };
1318 
1319 STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(NODE) - offsetof(NODE, u1));
1320 
1321 static void
1323 {
1324  int n;
1325 
1326  if (memo->min == Qundef) {
1327  memo->min = i;
1328  memo->max = j;
1329  }
1330  else {
1331  n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo->min), i, memo->min);
1332  if (n < 0) {
1333  memo->min = i;
1334  }
1335  n = rb_cmpint(rb_funcall(j, id_cmp, 1, memo->max), j, memo->max);
1336  if (n > 0) {
1337  memo->max = j;
1338  }
1339  }
1340 }
1341 
1342 static VALUE
1343 minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1344 {
1345  struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
1346  int n;
1348 
1349  ENUM_WANT_SVALUE();
1350 
1351  if (memo->last == Qundef) {
1352  memo->last = i;
1353  return Qnil;
1354  }
1355  j = memo->last;
1356  memo->last = Qundef;
1357 
1358  n = rb_cmpint(rb_funcall(j, id_cmp, 1, i), j, i);
1359  if (n == 0)
1360  i = j;
1361  else if (n < 0) {
1362  VALUE tmp;
1363  tmp = i;
1364  i = j;
1365  j = tmp;
1366  }
1367 
1368  minmax_i_update(i, j, memo);
1369 
1370  return Qnil;
1371 }
1372 
1373 static void
1375 {
1376  int n;
1377 
1378  if (memo->min == Qundef) {
1379  memo->min = i;
1380  memo->max = j;
1381  }
1382  else {
1383  n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
1384  if (n < 0) {
1385  memo->min = i;
1386  }
1387  n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
1388  if (n > 0) {
1389  memo->max = j;
1390  }
1391  }
1392 }
1393 
1394 static VALUE
1395 minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1396 {
1397  struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
1398  int n;
1399  VALUE j;
1400 
1401  ENUM_WANT_SVALUE();
1402 
1403  if (memo->last == Qundef) {
1404  memo->last = i;
1405  return Qnil;
1406  }
1407  j = memo->last;
1408  memo->last = Qundef;
1409 
1410  n = rb_cmpint(rb_yield_values(2, j, i), j, i);
1411  if (n == 0)
1412  i = j;
1413  else if (n < 0) {
1414  VALUE tmp;
1415  tmp = i;
1416  i = j;
1417  j = tmp;
1418  }
1419 
1420  minmax_ii_update(i, j, memo);
1421 
1422  return Qnil;
1423 }
1424 
1425 /*
1426  * call-seq:
1427  * enum.minmax -> [min, max]
1428  * enum.minmax { |a, b| block } -> [min, max]
1429  *
1430  * Returns two elements array which contains the minimum and the
1431  * maximum value in the enumerable. The first form assumes all
1432  * objects implement <code>Comparable</code>; the second uses the
1433  * block to return <em>a <=> b</em>.
1434  *
1435  * a = %w(albatross dog horse)
1436  * a.minmax #=> ["albatross", "horse"]
1437  * a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
1438  */
1439 
1440 static VALUE
1442 {
1443  NODE *memo = NEW_MEMO(Qundef, Qundef, Qundef);
1444  struct minmax_t *m = (struct minmax_t *)&memo->u1.value;
1445  VALUE ary = rb_ary_new3(2, Qnil, Qnil);
1446 
1447  m->min = Qundef;
1448  m->last = Qundef;
1449  if (rb_block_given_p()) {
1450  rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)memo);
1451  if (m->last != Qundef)
1452  minmax_ii_update(m->last, m->last, m);
1453  }
1454  else {
1455  rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)memo);
1456  if (m->last != Qundef)
1457  minmax_i_update(m->last, m->last, m);
1458  }
1459  if (m->min != Qundef) {
1460  rb_ary_store(ary, 0, m->min);
1461  rb_ary_store(ary, 1, m->max);
1462  }
1463  return ary;
1464 }
1465 
1466 static VALUE
1467 min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1468 {
1469  NODE *memo = RNODE(args);
1470  VALUE v;
1471 
1472  ENUM_WANT_SVALUE();
1473 
1474  v = rb_yield(i);
1475  if (memo->u1.value == Qundef) {
1476  memo->u1.value = v;
1477  memo->u2.value = i;
1478  }
1479  else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
1480  memo->u1.value = v;
1481  memo->u2.value = i;
1482  }
1483  return Qnil;
1484 }
1485 
1486 /*
1487  * call-seq:
1488  * enum.min_by { |obj| block } -> obj
1489  * enum.min_by -> an_enumerator
1490  *
1491  * Returns the object in <i>enum</i> that gives the minimum
1492  * value from the given block.
1493  *
1494  * If no block is given, an enumerator is returned instead.
1495  *
1496  * a = %w(albatross dog horse)
1497  * a.min_by { |x| x.length } #=> "dog"
1498  */
1499 
1500 static VALUE
1502 {
1503  NODE *memo;
1504 
1505  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1506 
1507  memo = NEW_MEMO(Qundef, Qnil, 0);
1508  rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
1509  return memo->u2.value;
1510 }
1511 
1512 static VALUE
1513 max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1514 {
1515  NODE *memo = RNODE(args);
1516  VALUE v;
1517 
1518  ENUM_WANT_SVALUE();
1519 
1520  v = rb_yield(i);
1521  if (memo->u1.value == Qundef) {
1522  memo->u1.value = v;
1523  memo->u2.value = i;
1524  }
1525  else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
1526  memo->u1.value = v;
1527  memo->u2.value = i;
1528  }
1529  return Qnil;
1530 }
1531 
1532 /*
1533  * call-seq:
1534  * enum.max_by { |obj| block } -> obj
1535  * enum.max_by -> an_enumerator
1536  *
1537  * Returns the object in <i>enum</i> that gives the maximum
1538  * value from the given block.
1539  *
1540  * If no block is given, an enumerator is returned instead.
1541  *
1542  * a = %w(albatross dog horse)
1543  * a.max_by { |x| x.length } #=> "albatross"
1544  */
1545 
1546 static VALUE
1548 {
1549  NODE *memo;
1550 
1551  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1552 
1553  memo = NEW_MEMO(Qundef, Qnil, 0);
1554  rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
1555  return memo->u2.value;
1556 }
1557 
1558 struct minmax_by_t {
1565 };
1566 
1567 static void
1568 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
1569 {
1570  if (memo->min_bv == Qundef) {
1571  memo->min_bv = v1;
1572  memo->max_bv = v2;
1573  memo->min = i1;
1574  memo->max = i2;
1575  }
1576  else {
1577  if (rb_cmpint(rb_funcall(v1, id_cmp, 1, memo->min_bv), v1, memo->min_bv) < 0) {
1578  memo->min_bv = v1;
1579  memo->min = i1;
1580  }
1581  if (rb_cmpint(rb_funcall(v2, id_cmp, 1, memo->max_bv), v2, memo->max_bv) > 0) {
1582  memo->max_bv = v2;
1583  memo->max = i2;
1584  }
1585  }
1586 }
1587 
1588 static VALUE
1589 minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1590 {
1591  struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
1593  int n;
1594 
1595  ENUM_WANT_SVALUE();
1596 
1597  vi = rb_yield(i);
1598 
1599  if (memo->last_bv == Qundef) {
1600  memo->last_bv = vi;
1601  memo->last = i;
1602  return Qnil;
1603  }
1604  vj = memo->last_bv;
1605  j = memo->last;
1606  memo->last_bv = Qundef;
1607 
1608  n = rb_cmpint(rb_funcall(vj, id_cmp, 1, vi), vj, vi);
1609  if (n == 0) {
1610  i = j;
1611  vi = vj;
1612  }
1613  else if (n < 0) {
1614  VALUE tmp;
1615  tmp = i;
1616  i = j;
1617  j = tmp;
1618  tmp = vi;
1619  vi = vj;
1620  vj = tmp;
1621  }
1622 
1623  minmax_by_i_update(vi, vj, i, j, memo);
1624 
1625  return Qnil;
1626 }
1627 
1628 /*
1629  * call-seq:
1630  * enum.minmax_by { |obj| block } -> [min, max]
1631  * enum.minmax_by -> an_enumerator
1632  *
1633  * Returns a two element array containing the objects in
1634  * <i>enum</i> that correspond to the minimum and maximum values respectively
1635  * from the given block.
1636  *
1637  * If no block is given, an enumerator is returned instead.
1638  *
1639  * a = %w(albatross dog horse)
1640  * a.minmax_by { |x| x.length } #=> ["dog", "albatross"]
1641  */
1642 
1643 static VALUE
1645 {
1646  VALUE memo;
1647  struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
1648 
1649  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1650 
1651  m->min_bv = Qundef;
1652  m->max_bv = Qundef;
1653  m->min = Qnil;
1654  m->max = Qnil;
1655  m->last_bv = Qundef;
1656  m->last = Qundef;
1657  rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
1658  if (m->last_bv != Qundef)
1659  minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
1660  m = MEMO_FOR(struct minmax_by_t, memo);
1661  return rb_assoc_new(m->min, m->max);
1662 }
1663 
1664 static VALUE
1665 member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
1666 {
1667  NODE *memo = RNODE(args);
1668 
1670  memo->u2.value = Qtrue;
1671  rb_iter_break();
1672  }
1673  return Qnil;
1674 }
1675 
1676 /*
1677  * call-seq:
1678  * enum.include?(obj) -> true or false
1679  * enum.member?(obj) -> true or false
1680  *
1681  * Returns <code>true</code> if any member of <i>enum</i> equals
1682  * <i>obj</i>. Equality is tested using <code>==</code>.
1683  *
1684  * IO.constants.include? :SEEK_SET #=> true
1685  * IO.constants.include? :SEEK_NO_FURTHER #=> false
1686  *
1687  */
1688 
1689 static VALUE
1691 {
1692  NODE *memo = NEW_MEMO(val, Qfalse, 0);
1693 
1694  rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
1695  return memo->u2.value;
1696 }
1697 
1698 static VALUE
1699 each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
1700 {
1701  long n = RNODE(memo)->u3.cnt++;
1702 
1704 }
1705 
1706 /*
1707  * call-seq:
1708  * enum.each_with_index(*args) { |obj, i| block } -> enum
1709  * enum.each_with_index(*args) -> an_enumerator
1710  *
1711  * Calls <em>block</em> with two arguments, the item and its index,
1712  * for each item in <i>enum</i>. Given arguments are passed through
1713  * to #each().
1714  *
1715  * If no block is given, an enumerator is returned instead.
1716  *
1717  * hash = Hash.new
1718  * %w(cat dog wombat).each_with_index { |item, index|
1719  * hash[item] = index
1720  * }
1721  * hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
1722  *
1723  */
1724 
1725 static VALUE
1727 {
1728  NODE *memo;
1729 
1730  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1731 
1732  memo = NEW_MEMO(0, 0, 0);
1733  rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
1734  return obj;
1735 }
1736 
1737 
1738 /*
1739  * call-seq:
1740  * enum.reverse_each(*args) { |item| block } -> enum
1741  * enum.reverse_each(*args) -> an_enumerator
1742  *
1743  * Builds a temporary array and traverses that array in reverse order.
1744  *
1745  * If no block is given, an enumerator is returned instead.
1746  *
1747  * (1..3).reverse_each { |v| p v }
1748  *
1749  * produces:
1750  *
1751  * 3
1752  * 2
1753  * 1
1754  */
1755 
1756 static VALUE
1758 {
1759  VALUE ary;
1760  long i;
1761 
1762  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1763 
1764  ary = enum_to_a(argc, argv, obj);
1765 
1766  for (i = RARRAY_LEN(ary); --i >= 0; ) {
1767  rb_yield(RARRAY_AREF(ary, i));
1768  }
1769 
1770  return obj;
1771 }
1772 
1773 
1774 static VALUE
1775 each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
1776 {
1777  ENUM_WANT_SVALUE();
1778  rb_yield(i);
1779  return Qnil;
1780 }
1781 
1782 /*
1783  * call-seq:
1784  * enum.each_entry { |obj| block } -> enum
1785  * enum.each_entry -> an_enumerator
1786  *
1787  * Calls <i>block</i> once for each element in +self+, passing that
1788  * element as a parameter, converting multiple values from yield to an
1789  * array.
1790  *
1791  * If no block is given, an enumerator is returned instead.
1792  *
1793  * class Foo
1794  * include Enumerable
1795  * def each
1796  * yield 1
1797  * yield 1, 2
1798  * yield
1799  * end
1800  * end
1801  * Foo.new.each_entry{ |o| p o }
1802  *
1803  * produces:
1804  *
1805  * 1
1806  * [1, 2]
1807  * nil
1808  *
1809  */
1810 
1811 static VALUE
1813 {
1814  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1815  rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
1816  return obj;
1817 }
1818 
1819 static VALUE
1820 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
1821 {
1822  NODE *memo = RNODE(m);
1823  VALUE ary = memo->u1.value;
1824  VALUE v = Qnil;
1825  long size = memo->u3.cnt;
1826  ENUM_WANT_SVALUE();
1827 
1828  rb_ary_push(ary, i);
1829 
1830  if (RARRAY_LEN(ary) == size) {
1831  v = rb_yield(ary);
1832  memo->u1.value = rb_ary_new2(size);
1833  }
1834 
1835  return v;
1836 }
1837 
1838 static VALUE
1840 {
1841  VALUE n, size;
1842  long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
1843  if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
1844 
1845  size = enum_size(obj, 0, 0);
1846  if (size == Qnil) return Qnil;
1847 
1848  n = rb_funcall(size, '+', 1, LONG2NUM(slice_size-1));
1849  return rb_funcall(n, id_div, 1, LONG2FIX(slice_size));
1850 }
1851 
1852 /*
1853  * call-seq:
1854  * enum.each_slice(n) { ... } -> nil
1855  * enum.each_slice(n) -> an_enumerator
1856  *
1857  * Iterates the given block for each slice of <n> elements. If no
1858  * block is given, returns an enumerator.
1859  *
1860  * (1..10).each_slice(3) { |a| p a }
1861  * # outputs below
1862  * [1, 2, 3]
1863  * [4, 5, 6]
1864  * [7, 8, 9]
1865  * [10]
1866  *
1867  */
1868 static VALUE
1870 {
1871  long size = NUM2LONG(n);
1872  VALUE ary;
1873  NODE *memo;
1874 
1875  if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
1877  ary = rb_ary_new2(size);
1878  memo = NEW_MEMO(ary, 0, size);
1879  rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
1880  ary = memo->u1.value;
1881  if (RARRAY_LEN(ary) > 0) rb_yield(ary);
1882 
1883  return Qnil;
1884 }
1885 
1886 static VALUE
1887 each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1888 {
1889  NODE *memo = RNODE(args);
1890  VALUE ary = memo->u1.value;
1891  VALUE v = Qnil;
1892  long size = memo->u3.cnt;
1893  ENUM_WANT_SVALUE();
1894 
1895  if (RARRAY_LEN(ary) == size) {
1896  rb_ary_shift(ary);
1897  }
1898  rb_ary_push(ary, i);
1899  if (RARRAY_LEN(ary) == size) {
1900  v = rb_yield(rb_ary_dup(ary));
1901  }
1902  return v;
1903 }
1904 
1905 static VALUE
1907 {
1908  VALUE n, size;
1909  long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
1910  if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
1911 
1912  size = enum_size(obj, 0, 0);
1913  if (size == Qnil) return Qnil;
1914 
1915  n = rb_funcall(size, '+', 1, LONG2NUM(1 - cons_size));
1916  return (rb_cmpint(rb_funcall(n, id_cmp, 1, LONG2FIX(0)), n, LONG2FIX(0)) == -1) ? LONG2FIX(0) : n;
1917 }
1918 
1919 /*
1920  * call-seq:
1921  * enum.each_cons(n) { ... } -> nil
1922  * enum.each_cons(n) -> an_enumerator
1923  *
1924  * Iterates the given block for each array of consecutive <n>
1925  * elements. If no block is given, returns an enumerator.
1926  *
1927  * e.g.:
1928  * (1..10).each_cons(3) { |a| p a }
1929  * # outputs below
1930  * [1, 2, 3]
1931  * [2, 3, 4]
1932  * [3, 4, 5]
1933  * [4, 5, 6]
1934  * [5, 6, 7]
1935  * [6, 7, 8]
1936  * [7, 8, 9]
1937  * [8, 9, 10]
1938  *
1939  */
1940 static VALUE
1942 {
1943  long size = NUM2LONG(n);
1944  NODE *memo;
1945 
1946  if (size <= 0) rb_raise(rb_eArgError, "invalid size");
1948  memo = NEW_MEMO(rb_ary_new2(size), 0, size);
1949  rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
1950 
1951  return Qnil;
1952 }
1953 
1954 static VALUE
1955 each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
1956 {
1957  ENUM_WANT_SVALUE();
1958  return rb_yield_values(2, i, memo);
1959 }
1960 
1961 /*
1962  * call-seq:
1963  * enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
1964  * enum.each_with_object(obj) -> an_enumerator
1965  *
1966  * Iterates the given block for each element with an arbitrary
1967  * object given, and returns the initially given object.
1968  *
1969  * If no block is given, returns an enumerator.
1970  *
1971  * evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
1972  * #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
1973  *
1974  */
1975 static VALUE
1977 {
1978  RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
1979 
1980  rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
1981 
1982  return memo;
1983 }
1984 
1985 static VALUE
1986 zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
1987 {
1988  NODE *memo = (NODE *)memoval;
1989  volatile VALUE result = memo->u1.value;
1990  volatile VALUE args = memo->u2.value;
1991  long n = memo->u3.cnt++;
1992  volatile VALUE tmp;
1993  int i;
1994 
1995  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
1997  for (i=0; i<RARRAY_LEN(args); i++) {
1998  VALUE e = RARRAY_AREF(args, i);
1999 
2000  if (RARRAY_LEN(e) <= n) {
2001  rb_ary_push(tmp, Qnil);
2002  }
2003  else {
2004  rb_ary_push(tmp, RARRAY_AREF(e, n));
2005  }
2006  }
2007  if (NIL_P(result)) {
2008  rb_yield(tmp);
2009  }
2010  else {
2011  rb_ary_push(result, tmp);
2012  }
2013  return Qnil;
2014 }
2015 
2016 static VALUE
2018 {
2019  return v[0] = rb_funcall(v[1], id_next, 0, 0);
2020 }
2021 
2022 static VALUE
2024 {
2025  return v[0] = Qundef;
2026 }
2027 
2028 static VALUE
2029 zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
2030 {
2031  NODE *memo = (NODE *)memoval;
2032  volatile VALUE result = memo->u1.value;
2033  volatile VALUE args = memo->u2.value;
2034  volatile VALUE tmp;
2035  int i;
2036 
2037  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
2039  for (i=0; i<RARRAY_LEN(args); i++) {
2040  if (NIL_P(RARRAY_AREF(args, i))) {
2041  rb_ary_push(tmp, Qnil);
2042  }
2043  else {
2044  VALUE v[2];
2045 
2046  v[1] = RARRAY_AREF(args, i);
2048  if (v[0] == Qundef) {
2049  RARRAY_ASET(args, i, Qnil);
2050  v[0] = Qnil;
2051  }
2052  rb_ary_push(tmp, v[0]);
2053  }
2054  }
2055  if (NIL_P(result)) {
2056  rb_yield(tmp);
2057  }
2058  else {
2059  rb_ary_push(result, tmp);
2060  }
2061  return Qnil;
2062 }
2063 
2064 /*
2065  * call-seq:
2066  * enum.zip(arg, ...) -> an_array_of_array
2067  * enum.zip(arg, ...) { |arr| block } -> nil
2068  *
2069  * Takes one element from <i>enum</i> and merges corresponding
2070  * elements from each <i>args</i>. This generates a sequence of
2071  * <em>n</em>-element arrays, where <em>n</em> is one more than the
2072  * count of arguments. The length of the resulting sequence will be
2073  * <code>enum#size</code>. If the size of any argument is less than
2074  * <code>enum#size</code>, <code>nil</code> values are supplied. If
2075  * a block is given, it is invoked for each output array, otherwise
2076  * an array of arrays is returned.
2077  *
2078  * a = [ 4, 5, 6 ]
2079  * b = [ 7, 8, 9 ]
2080  *
2081  * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2082  * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
2083  * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
2084  *
2085  */
2086 
2087 static VALUE
2089 {
2090  int i;
2091  ID conv;
2092  NODE *memo;
2093  VALUE result = Qnil;
2094  VALUE args = rb_ary_new4(argc, argv);
2095  int allary = TRUE;
2096 
2097  argv = RARRAY_PTR(args);
2098  for (i=0; i<argc; i++) {
2099  VALUE ary = rb_check_array_type(argv[i]);
2100  if (NIL_P(ary)) {
2101  allary = FALSE;
2102  break;
2103  }
2104  argv[i] = ary;
2105  }
2106  if (!allary) {
2107  CONST_ID(conv, "to_enum");
2108  for (i=0; i<argc; i++) {
2109  if (!rb_respond_to(argv[i], id_each)) {
2110  rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
2111  rb_obj_classname(argv[i]));
2112  }
2113  argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
2114  }
2115  }
2116  if (!rb_block_given_p()) {
2117  result = rb_ary_new();
2118  }
2119  /* use NODE_DOT2 as memo(v, v, -) */
2120  memo = rb_node_newnode(NODE_DOT2, result, args, 0);
2121  rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
2122 
2123  return result;
2124 }
2125 
2126 static VALUE
2127 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2128 {
2129  NODE *memo = RNODE(args);
2131  if (--memo->u3.cnt == 0) rb_iter_break();
2132  return Qnil;
2133 }
2134 
2135 /*
2136  * call-seq:
2137  * enum.take(n) -> array
2138  *
2139  * Returns first n elements from <i>enum</i>.
2140  *
2141  * a = [1, 2, 3, 4, 5, 0]
2142  * a.take(3) #=> [1, 2, 3]
2143  *
2144  */
2145 
2146 static VALUE
2148 {
2149  NODE *memo;
2150  VALUE result;
2151  long len = NUM2LONG(n);
2152 
2153  if (len < 0) {
2154  rb_raise(rb_eArgError, "attempt to take negative size");
2155  }
2156 
2157  if (len == 0) return rb_ary_new2(0);
2158  result = rb_ary_new2(len);
2159  memo = NEW_MEMO(result, 0, len);
2160  rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
2161  return result;
2162 }
2163 
2164 
2165 static VALUE
2166 take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2167 {
2168  if (!RTEST(enum_yield(argc, argv))) rb_iter_break();
2170  return Qnil;
2171 }
2172 
2173 /*
2174  * call-seq:
2175  * enum.take_while { |arr| block } -> array
2176  * enum.take_while -> an_enumerator
2177  *
2178  * Passes elements to the block until the block returns +nil+ or +false+,
2179  * then stops iterating and returns an array of all prior elements.
2180  *
2181  * If no block is given, an enumerator is returned instead.
2182  *
2183  * a = [1, 2, 3, 4, 5, 0]
2184  * a.take_while { |i| i < 3 } #=> [1, 2]
2185  *
2186  */
2187 
2188 static VALUE
2190 {
2191  VALUE ary;
2192 
2193  RETURN_ENUMERATOR(obj, 0, 0);
2194  ary = rb_ary_new();
2195  rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
2196  return ary;
2197 }
2198 
2199 static VALUE
2200 drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2201 {
2202  NODE *memo = RNODE(args);
2203  if (memo->u3.cnt == 0) {
2205  }
2206  else {
2207  memo->u3.cnt--;
2208  }
2209  return Qnil;
2210 }
2211 
2212 /*
2213  * call-seq:
2214  * enum.drop(n) -> array
2215  *
2216  * Drops first n elements from <i>enum</i>, and returns rest elements
2217  * in an array.
2218  *
2219  * a = [1, 2, 3, 4, 5, 0]
2220  * a.drop(3) #=> [4, 5, 0]
2221  *
2222  */
2223 
2224 static VALUE
2226 {
2227  VALUE result;
2228  NODE *memo;
2229  long len = NUM2LONG(n);
2230 
2231  if (len < 0) {
2232  rb_raise(rb_eArgError, "attempt to drop negative size");
2233  }
2234 
2235  result = rb_ary_new();
2236  memo = NEW_MEMO(result, 0, len);
2237  rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
2238  return result;
2239 }
2240 
2241 
2242 static VALUE
2243 drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2244 {
2245  NODE *memo = RNODE(args);
2246  ENUM_WANT_SVALUE();
2247 
2248  if (!memo->u3.state && !RTEST(rb_yield(i))) {
2249  memo->u3.state = TRUE;
2250  }
2251  if (memo->u3.state) {
2252  rb_ary_push(memo->u1.value, i);
2253  }
2254  return Qnil;
2255 }
2256 
2257 /*
2258  * call-seq:
2259  * enum.drop_while { |arr| block } -> array
2260  * enum.drop_while -> an_enumerator
2261  *
2262  * Drops elements up to, but not including, the first element for
2263  * which the block returns +nil+ or +false+ and returns an array
2264  * containing the remaining elements.
2265  *
2266  * If no block is given, an enumerator is returned instead.
2267  *
2268  * a = [1, 2, 3, 4, 5, 0]
2269  * a.drop_while { |i| i < 3 } #=> [3, 4, 5, 0]
2270  *
2271  */
2272 
2273 static VALUE
2275 {
2276  VALUE result;
2277  NODE *memo;
2278 
2279  RETURN_ENUMERATOR(obj, 0, 0);
2280  result = rb_ary_new();
2281  memo = NEW_MEMO(result, 0, FALSE);
2282  rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
2283  return result;
2284 }
2285 
2286 static VALUE
2287 cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2288 {
2289  ENUM_WANT_SVALUE();
2290 
2291  rb_ary_push(ary, i);
2292  rb_yield(i);
2293  return Qnil;
2294 }
2295 
2296 static VALUE
2298 {
2299  long mul;
2300  VALUE n = Qnil;
2301  VALUE size = enum_size(self, args, 0);
2302 
2303  if (size == Qnil) return Qnil;
2304 
2305  if (args && (RARRAY_LEN(args) > 0)) {
2306  n = RARRAY_AREF(args, 0);
2307  }
2308  if (n == Qnil) return DBL2NUM(INFINITY);
2309  mul = NUM2LONG(n);
2310  if (mul <= 0) return INT2FIX(0);
2311  return rb_funcall(size, '*', 1, LONG2FIX(mul));
2312 }
2313 
2314 /*
2315  * call-seq:
2316  * enum.cycle(n=nil) { |obj| block } -> nil
2317  * enum.cycle(n=nil) -> an_enumerator
2318  *
2319  * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
2320  * times or forever if none or +nil+ is given. If a non-positive
2321  * number is given or the collection is empty, does nothing. Returns
2322  * +nil+ if the loop has finished without getting interrupted.
2323  *
2324  * Enumerable#cycle saves elements in an internal array so changes
2325  * to <i>enum</i> after the first pass have no effect.
2326  *
2327  * If no block is given, an enumerator is returned instead.
2328  *
2329  * a = ["a", "b", "c"]
2330  * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
2331  * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
2332  *
2333  */
2334 
2335 static VALUE
2337 {
2338  VALUE ary;
2339  VALUE nv = Qnil;
2340  long n, i, len;
2341 
2342  rb_scan_args(argc, argv, "01", &nv);
2343 
2344  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
2345  if (NIL_P(nv)) {
2346  n = -1;
2347  }
2348  else {
2349  n = NUM2LONG(nv);
2350  if (n <= 0) return Qnil;
2351  }
2352  ary = rb_ary_new();
2353  RBASIC_CLEAR_CLASS(ary);
2354  rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
2355  len = RARRAY_LEN(ary);
2356  if (len == 0) return Qnil;
2357  while (n < 0 || 0 < --n) {
2358  for (i=0; i<len; i++) {
2359  rb_yield(RARRAY_AREF(ary, i));
2360  }
2361  }
2362  return Qnil;
2363 }
2364 
2365 struct chunk_arg {
2371 };
2372 
2373 static VALUE
2374 chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
2375 {
2376  struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
2377  VALUE v;
2378  VALUE alone = ID2SYM(rb_intern("_alone"));
2379  VALUE separator = ID2SYM(rb_intern("_separator"));
2380 
2381  ENUM_WANT_SVALUE();
2382 
2383  if (NIL_P(argp->state))
2384  v = rb_funcall(argp->categorize, id_call, 1, i);
2385  else
2386  v = rb_funcall(argp->categorize, id_call, 2, i, argp->state);
2387 
2388  if (v == alone) {
2389  if (!NIL_P(argp->prev_value)) {
2390  rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2391  argp->prev_value = argp->prev_elts = Qnil;
2392  }
2393  rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(v, rb_ary_new3(1, i)));
2394  }
2395  else if (NIL_P(v) || v == separator) {
2396  if (!NIL_P(argp->prev_value)) {
2397  rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2398  argp->prev_value = argp->prev_elts = Qnil;
2399  }
2400  }
2401  else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
2402  rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
2403  }
2404  else {
2405  if (NIL_P(argp->prev_value)) {
2406  argp->prev_value = v;
2407  argp->prev_elts = rb_ary_new3(1, i);
2408  }
2409  else {
2410  if (rb_equal(argp->prev_value, v)) {
2411  rb_ary_push(argp->prev_elts, i);
2412  }
2413  else {
2414  rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2415  argp->prev_value = v;
2416  argp->prev_elts = rb_ary_new3(1, i);
2417  }
2418  }
2419  }
2420  return Qnil;
2421 }
2422 
2423 static VALUE
2425 {
2426  VALUE enumerable;
2428  struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
2429 
2430  enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
2431  memo->categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
2432  memo->state = rb_ivar_get(enumerator, rb_intern("chunk_initial_state"));
2433  memo->prev_value = Qnil;
2434  memo->prev_elts = Qnil;
2435  memo->yielder = yielder;
2436 
2437  if (!NIL_P(memo->state))
2438  memo->state = rb_obj_dup(memo->state);
2439 
2440  rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
2441  memo = MEMO_FOR(struct chunk_arg, arg);
2442  if (!NIL_P(memo->prev_elts))
2443  rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts));
2444  return Qnil;
2445 }
2446 
2447 /*
2448  * call-seq:
2449  * enum.chunk { |elt| ... } -> an_enumerator
2450  * enum.chunk(initial_state) { |elt, state| ... } -> an_enumerator
2451  *
2452  * Enumerates over the items, chunking them together based on the return
2453  * value of the block.
2454  *
2455  * Consecutive elements which return the same block value are chunked together.
2456  *
2457  * For example, consecutive even numbers and odd numbers can be
2458  * chunked as follows.
2459  *
2460  * [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
2461  * n.even?
2462  * }.each { |even, ary|
2463  * p [even, ary]
2464  * }
2465  * #=> [false, [3, 1]]
2466  * # [true, [4]]
2467  * # [false, [1, 5, 9]]
2468  * # [true, [2, 6]]
2469  * # [false, [5, 3, 5]]
2470  *
2471  * This method is especially useful for sorted series of elements.
2472  * The following example counts words for each initial letter.
2473  *
2474  * open("/usr/share/dict/words", "r:iso-8859-1") { |f|
2475  * f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] }
2476  * }
2477  * #=> ["\n", 1]
2478  * # ["A", 1327]
2479  * # ["B", 1372]
2480  * # ["C", 1507]
2481  * # ["D", 791]
2482  * # ...
2483  *
2484  * The following key values have special meaning:
2485  * - +nil+ and +:_separator+ specifies that the elements should be dropped.
2486  * - +:_alone+ specifies that the element should be chunked by itself.
2487  *
2488  * Any other symbols that begin with an underscore will raise an error:
2489  *
2490  * items.chunk { |item| :_underscore }
2491  * #=> RuntimeError: symbols beginning with an underscore are reserved
2492  *
2493  * +nil+ and +:_separator+ can be used to ignore some elements.
2494  *
2495  * For example, the sequence of hyphens in svn log can be eliminated as follows:
2496  *
2497  * sep = "-"*72 + "\n"
2498  * IO.popen("svn log README") { |f|
2499  * f.chunk { |line|
2500  * line != sep || nil
2501  * }.each { |_, lines|
2502  * pp lines
2503  * }
2504  * }
2505  * #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
2506  * # "\n",
2507  * # "* README, README.ja: Update the portability section.\n",
2508  * # "\n"]
2509  * # ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
2510  * # "\n",
2511  * # "* README, README.ja: Add a note about default C flags.\n",
2512  * # "\n"]
2513  * # ...
2514  *
2515  * Paragraphs separated by empty lines can be parsed as follows:
2516  *
2517  * File.foreach("README").chunk { |line|
2518  * /\A\s*\z/ !~ line || nil
2519  * }.each { |_, lines|
2520  * pp lines
2521  * }
2522  *
2523  * +:_alone+ can be used to force items into their own chunk.
2524  * For example, you can put lines that contain a URL by themselves,
2525  * and chunk the rest of the lines together, like this:
2526  *
2527  * pattern = /http/
2528  * open(filename) { |f|
2529  * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
2530  * pp lines
2531  * }
2532  * }
2533  *
2534  * If the block needs to maintain state over multiple elements,
2535  * an +initial_state+ argument can be used.
2536  * If a non-nil value is given,
2537  * a reference to it is passed as the 2nd argument of the block for the
2538  * +chunk+ method, so state-changes to it persist across block calls.
2539  *
2540  */
2541 static VALUE
2542 enum_chunk(int argc, VALUE *argv, VALUE enumerable)
2543 {
2544  VALUE initial_state;
2545  VALUE enumerator;
2546 
2547  if (!rb_block_given_p())
2548  rb_raise(rb_eArgError, "no block given");
2549  rb_scan_args(argc, argv, "01", &initial_state);
2550 
2551  enumerator = rb_obj_alloc(rb_cEnumerator);
2552  rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
2553  rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
2554  rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
2555  rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
2556  return enumerator;
2557 }
2558 
2559 
2566 };
2567 
2568 static VALUE
2569 slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
2570 {
2571  struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
2573 
2574  ENUM_WANT_SVALUE();
2575 
2576  if (!NIL_P(argp->sep_pat))
2577  header_p = rb_funcall(argp->sep_pat, id_eqq, 1, i);
2578  else if (NIL_P(argp->state))
2579  header_p = rb_funcall(argp->sep_pred, id_call, 1, i);
2580  else
2581  header_p = rb_funcall(argp->sep_pred, id_call, 2, i, argp->state);
2582  if (RTEST(header_p)) {
2583  if (!NIL_P(argp->prev_elts))
2584  rb_funcall(argp->yielder, id_lshift, 1, argp->prev_elts);
2585  argp->prev_elts = rb_ary_new3(1, i);
2586  }
2587  else {
2588  if (NIL_P(argp->prev_elts))
2589  argp->prev_elts = rb_ary_new3(1, i);
2590  else
2591  rb_ary_push(argp->prev_elts, i);
2592  }
2593 
2594  return Qnil;
2595 }
2596 
2597 static VALUE
2599 {
2600  VALUE enumerable;
2601  VALUE arg;
2602  struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
2603 
2604  enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
2605  memo->sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
2606  memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
2607  memo->state = rb_attr_get(enumerator, rb_intern("slicebefore_initial_state"));
2608  memo->prev_elts = Qnil;
2609  memo->yielder = yielder;
2610 
2611  if (!NIL_P(memo->state))
2612  memo->state = rb_obj_dup(memo->state);
2613 
2614  rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
2615  memo = MEMO_FOR(struct slicebefore_arg, arg);
2616  if (!NIL_P(memo->prev_elts))
2617  rb_funcall(memo->yielder, id_lshift, 1, memo->prev_elts);
2618  return Qnil;
2619 }
2620 
2621 /*
2622  * call-seq:
2623  * enum.slice_before(pattern) -> an_enumerator
2624  * enum.slice_before { |elt| bool } -> an_enumerator
2625  * enum.slice_before(initial_state) { |elt, state| bool } -> an_enumerator
2626  *
2627  * Creates an enumerator for each chunked elements.
2628  * The beginnings of chunks are defined by _pattern_ and the block.
2629 
2630  * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
2631  * returns <code>true</code> for the element, the element is beginning of a
2632  * chunk.
2633 
2634  * The <code>===</code> and _block_ is called from the first element to the last
2635  * element of _enum_. The result for the first element is ignored.
2636 
2637  * The result enumerator yields the chunked elements as an array.
2638  * So +each+ method can be called as follows:
2639  *
2640  * enum.slice_before(pattern).each { |ary| ... }
2641  * enum.slice_before { |elt| bool }.each { |ary| ... }
2642  * enum.slice_before(initial_state) { |elt, state| bool }.each { |ary| ... }
2643  *
2644  * Other methods of the Enumerator class and Enumerable module,
2645  * such as map, etc., are also usable.
2646  *
2647  * For example, iteration over ChangeLog entries can be implemented as
2648  * follows:
2649  *
2650  * # iterate over ChangeLog entries.
2651  * open("ChangeLog") { |f|
2652  * f.slice_before(/\A\S/).each { |e| pp e }
2653  * }
2654  *
2655  * # same as above. block is used instead of pattern argument.
2656  * open("ChangeLog") { |f|
2657  * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
2658  * }
2659  *
2660  *
2661  * "svn proplist -R" produces multiline output for each file.
2662  * They can be chunked as follows:
2663  *
2664  * IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
2665  * f.lines.slice_before(/\AProp/).each { |lines| p lines }
2666  * }
2667  * #=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
2668  * # ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
2669  * # ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
2670  * # ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
2671  * # ...
2672  *
2673  * If the block needs to maintain state over multiple elements,
2674  * local variables can be used.
2675  * For example, three or more consecutive increasing numbers can be squashed
2676  * as follows:
2677  *
2678  * a = [0, 2, 3, 4, 6, 7, 9]
2679  * prev = a[0]
2680  * p a.slice_before { |e|
2681  * prev, prev2 = e, prev
2682  * prev2 + 1 != e
2683  * }.map { |es|
2684  * es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
2685  * }.join(",")
2686  * #=> "0,2-4,6,7,9"
2687  *
2688  * However local variables are not appropriate to maintain state
2689  * if the result enumerator is used twice or more.
2690  * In such a case, the last state of the 1st +each+ is used in the 2nd +each+.
2691  * The _initial_state_ argument can be used to avoid this problem.
2692  * If non-nil value is given as _initial_state_,
2693  * it is duplicated for each +each+ method invocation of the enumerator.
2694  * The duplicated object is passed to 2nd argument of the block for
2695  * +slice_before+ method.
2696  *
2697  * # Word wrapping. This assumes all characters have same width.
2698  * def wordwrap(words, maxwidth)
2699  * # if cols is a local variable, 2nd "each" may start with non-zero cols.
2700  * words.slice_before(cols: 0) { |w, h|
2701  * h[:cols] += 1 if h[:cols] != 0
2702  * h[:cols] += w.length
2703  * if maxwidth < h[:cols]
2704  * h[:cols] = w.length
2705  * true
2706  * else
2707  * false
2708  * end
2709  * }
2710  * end
2711  * text = (1..20).to_a.join(" ")
2712  * enum = wordwrap(text.split(/\s+/), 10)
2713  * puts "-"*10
2714  * enum.each { |ws| puts ws.join(" ") }
2715  * puts "-"*10
2716  * #=> ----------
2717  * # 1 2 3 4 5
2718  * # 6 7 8 9 10
2719  * # 11 12 13
2720  * # 14 15 16
2721  * # 17 18 19
2722  * # 20
2723  * # ----------
2724  *
2725  * mbox contains series of mails which start with Unix From line.
2726  * So each mail can be extracted by slice before Unix From line.
2727  *
2728  * # parse mbox
2729  * open("mbox") { |f|
2730  * f.slice_before { |line|
2731  * line.start_with? "From "
2732  * }.each { |mail|
2733  * unix_from = mail.shift
2734  * i = mail.index("\n")
2735  * header = mail[0...i]
2736  * body = mail[(i+1)..-1]
2737  * body.pop if body.last == "\n"
2738  * fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
2739  * p unix_from
2740  * pp fields
2741  * pp body
2742  * }
2743  * }
2744  *
2745  * # split mails in mbox (slice before Unix From line after an empty line)
2746  * open("mbox") { |f|
2747  * f.slice_before(emp: true) { |line, h|
2748  * prevemp = h[:emp]
2749  * h[:emp] = line == "\n"
2750  * prevemp && line.start_with?("From ")
2751  * }.each { |mail|
2752  * mail.pop if mail.last == "\n"
2753  * pp mail
2754  * }
2755  * }
2756  *
2757  */
2758 static VALUE
2760 {
2761  VALUE enumerator;
2762 
2763  if (rb_block_given_p()) {
2764  VALUE initial_state;
2765  rb_scan_args(argc, argv, "01", &initial_state);
2766  enumerator = rb_obj_alloc(rb_cEnumerator);
2767  rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
2768  rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
2769  }
2770  else {
2771  VALUE sep_pat;
2772  rb_scan_args(argc, argv, "1", &sep_pat);
2773  enumerator = rb_obj_alloc(rb_cEnumerator);
2774  rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
2775  }
2776  rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
2777  rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
2778  return enumerator;
2779 }
2780 
2781 /*
2782  * The <code>Enumerable</code> mixin provides collection classes with
2783  * several traversal and searching methods, and with the ability to
2784  * sort. The class must provide a method <code>each</code>, which
2785  * yields successive members of the collection. If
2786  * <code>Enumerable#max</code>, <code>#min</code>, or
2787  * <code>#sort</code> is used, the objects in the collection must also
2788  * implement a meaningful <code><=></code> operator, as these methods
2789  * rely on an ordering between members of the collection.
2790  */
2791 
2792 void
2794 {
2795 #undef rb_intern
2796 #define rb_intern(str) rb_intern_const(str)
2797 
2798  rb_mEnumerable = rb_define_module("Enumerable");
2799 
2801  rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
2803 
2809  rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
2810  rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
2817  rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
2834  rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
2835  rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
2836  rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
2837  rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
2838  rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
2840  rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
2843  rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
2845  rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
2848  rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
2849 
2850  id_next = rb_intern("next");
2851  id_call = rb_intern("call");
2852  id_size = rb_intern("size");
2853  id_div = rb_intern("div");
2854 }
VALUE data
Definition: tcltklib.c:3360
#define id_lshift
Definition: enum.c:30
#define RB_TYPE_P(obj, type)
RARRAY_PTR(q->result)[0]
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:451
#define rb_check_arity
static VALUE enum_any(VALUE obj)
Definition: enum.c:1087
UChar * pat
Definition: regerror.c:392
static VALUE enum_all(VALUE obj)
Definition: enum.c:1053
#define FALSE
Definition: nkf.h:174
VALUE alone
Definition: enum.c:2378
#define id_each
Definition: enum.c:27
#define OBJ_INFECT(x, s)
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
#define ENUM_WANT_SVALUE()
Definition: enum.c:40
VALUE state
Definition: enum.c:2367
static VALUE enum_each_with_index(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1726
static int sort_by_cmp(const void *ap, const void *bp, void *data)
Definition: enum.c:869
VALUE rb_ary_sort(VALUE ary)
Definition: array.c:2518
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:995
static VALUE enum_each_slice(VALUE obj, VALUE n)
Definition: enum.c:1869
Real * a
Definition: bigdecimal.c:1198
rb_yield(i)
VALUE rb_eTypeError
Definition: error.c:548
VALUE rb_obj_dup(VALUE)
Definition: object.c:406
rb_iter_break()
Definition: vm.c:1154
VALUE state
Definition: enum.c:2563
#define UNREACHABLE
Definition: ruby.h:42
VALUE sep_pred
Definition: enum.c:2561
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:900
static VALUE enum_each_cons(VALUE obj, VALUE n)
Definition: enum.c:1941
VALUE yielder
Definition: enum.c:2565
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:538
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
#define T_ARRAY
static VALUE enum_sort_by(VALUE obj)
Definition: enum.c:957
VALUE separator
Definition: enum.c:2379
static VALUE enum_member(VALUE obj, VALUE val)
Definition: enum.c:1690
VALUE rb_cEnumerator
Definition: enumerator.c:105
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
group
Definition: enum.c:723
return Qtrue
Definition: tcltklib.c:9618
VALUE vj
Definition: enum.c:1592
#define RETURN_ENUMERATOR(obj, argc, argv)
#define DEFINE_ENUMFUNCS(name)
Definition: enum.c:1008
rb_thread_check_ints()
Definition: thread.c:1143
static VALUE enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
Definition: enum.c:2759
#define rb_ary_new4
r
Definition: bigdecimal.c:1212
tmp
Definition: enum.c:447
VALUE max
Definition: enum.c:1562
VALUE max
Definition: enum.c:1315
int size
Definition: encoding.c:49
long argc
Definition: ripper.y:253
VALUE yielder
Definition: enum.c:2370
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17365
#define ID2SYM(x)
VALUE last
Definition: enum.c:1316
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2909
#define rb_ary_new2
#define LONG2NUM(x)
static VALUE enum_to_h(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:543
VALUE rb_f_send(int argc, VALUE *argv, VALUE recv)
Definition: vm_eval.c:914
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
i
Definition: enum.c:446
VALUE ary
Definition: enum.c:674
Definition: ripper.y:240
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ripper.y:1521
void Init_Enumerable(void)
Definition: enum.c:2793
memo yielder
Definition: enum.c:2435
VALUE prev_value
Definition: enum.c:2368
VALUE hash
Definition: tkutil.c:267
static VALUE enum_max(VALUE obj)
Definition: enum.c:1297
static VALUE enum_max_by(VALUE obj)
Definition: enum.c:1547
#define STATIC_ASSERT(name, expr)
long n
Definition: enum.c:837
static ID id_size
Definition: enum.c:25
VALUE rb_block_proc(void)
Definition: proc.c:620
BDIGIT m
Definition: bigdecimal.c:5209
return Qfalse
Definition: tcltklib.c:6790
static VALUE enum_take(VALUE obj, VALUE n)
Definition: enum.c:2147
static VALUE enum_chunk(int argc, VALUE *argv, VALUE enumerable)
Definition: enum.c:2542
int rb_block_given_p(void)
Definition: eval.c:712
#define RARRAY_LEN(a)
#define Qnil
Definition: enum.c:67
#define val
Definition: tcltklib.c:1935
VALUE rb_eRuntimeError
Definition: error.c:547
static VALUE enum_sort(VALUE obj)
Definition: enum.c:828
static VALUE enum_each_entry(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1812
#define RARRAY_AREF(a, i)
VALUE rb_ary_new(void)
Definition: array.c:499
static VALUE enum_inject(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:636
unsigned long ID
Definition: ripper.y:89
static VALUE enum_grep(VALUE obj, VALUE pat)
Definition: enum.c:89
static VALUE enum_find_all(VALUE obj)
Definition: enum.c:341
static VALUE enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
Definition: enum.c:2297
static VALUE VALUE obj
Definition: tcltklib.c:3150
#define INT2FIX(i)
#define SORT_BY_BUFSIZE
Definition: enum.c:833
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:794
VALUE value
Definition: ripper.y:246
#define offsetof(p_type, field)
Definition: addrinfo.h:186
static void minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
Definition: enum.c:1322
static double one(void)
Definition: isinf.c:52
key_value_pair
Definition: enum.c:518
static VALUE enum_first(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:795
#define LONG_MAX
Definition: ruby.h:191
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
memo sep_pat
Definition: enum.c:2606
static void minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
Definition: enum.c:1568
#define DBL2NUM(dbl)
long cnt
Definition: ripper.y:262
int len
Definition: enumerator.c:1332
#define numberof(array)
Definition: etc.c:602
VALUE arg
Definition: enum.c:2427
static int reject_i(VALUE key, VALUE value, VALUE result)
Definition: hash.c:1136
VALUE * argv
Definition: tcltklib.c:1969
static VALUE enum_cycle(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:2336
#define RTEST(v)
const int id
Definition: nkf.c:209
#define TRUE
Definition: nkf.h:175
VALUE rb_mEnumerable
Definition: enum.c:20
rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg)
VALUE categorize
Definition: enum.c:2366
#define rb_node_newnode(type, a1, a2, a3)
Definition: ripper.c:424
VALUE v
Definition: enum.c:845
#define CONST_ID(var, str)
static VALUE enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
Definition: enum.c:1906
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
VALUE sep_pat
Definition: enum.c:2562
NODE * memo
Definition: enum.c:1174
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:620
static void minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
Definition: enum.c:1374
VALUE min_bv
Definition: enum.c:1559
#define RBASIC_SET_CLASS_RAW(obj, cls)
union RNode::@114 u3
VALUE rb_eStopIteration
Definition: enumerator.c:111
static VALUE enum_collect(VALUE obj)
Definition: enum.c:429
#define id_cmp
Definition: enum.c:29
int argc
Definition: tcltklib.c:1968
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
VALUE vi
Definition: enum.c:1592
static VALUE enum_min(VALUE obj)
Definition: enum.c:1226
rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1))
static VALUE enum_none(VALUE obj)
Definition: enum.c:1163
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:741
static VALUE enum_size(VALUE self, VALUE args, VALUE eobj)
Definition: enum.c:313
VALUE values
Definition: enum.c:719
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
#define INFINITY
Definition: missing.h:141
#define ENUMFUNC(name)
Definition: enum.c:1006
static VALUE enum_one(VALUE obj)
Definition: enum.c:1127
#define NEW_MEMO_FOR(type, value)
Real * b
Definition: bigdecimal.c:1198
static VALUE enum_drop_while(VALUE obj)
Definition: enum.c:2274
return ptr
Definition: tcltklib.c:789
enumerable
Definition: enum.c:2430
#define enum_yield
Definition: enum.c:44
VALUE max_bv
Definition: enum.c:1560
#define NEW_MEMO(a, b, c)
VALUE last_bv
Definition: enum.c:1563
VALUE prev_elts
Definition: enum.c:2564
static ID id_call
Definition: enum.c:24
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1626
VALUE ary
Definition: enum.c:835
static VALUE enum_reject(VALUE obj)
Definition: enum.c:382
static VALUE enum_each_with_object(VALUE obj, VALUE memo)
Definition: enum.c:1976
VALUE cmp
Definition: enum.c:1246
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
static ID id_div
Definition: enum.c:23
#define RARRAY_PTR_USE(ary, ptr_name, expr)
#define NUM2LONG(x)
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Definition: enum.c:33
#define SYMBOL_P(x)
static VALUE enum_partition(VALUE obj)
Definition: enum.c:703
#define Qundef
static VALUE enum_to_a(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:502
#define mul(x, y)
Definition: date_strftime.c:25
static VALUE enum_minmax_by(VALUE obj)
Definition: enum.c:1644
VALUE name
Definition: enum.c:572
#define MEMO_FOR(type, value)
static VALUE enum_reverse_each(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1757
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:632
VALUE min
Definition: enum.c:1561
args[0]
Definition: enum.c:585
long state
Definition: ripper.y:259
static VALUE enum_count(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:151
#define LONG2FIX(i)
#define RBASIC(obj)
VALUE header_p
Definition: enum.c:2572
klass
Definition: tcltklib.c:3496
#define UINT2NUM(x)
#define INT2NUM(x)
static VALUE enum_drop(VALUE obj, VALUE n)
Definition: enum.c:2225
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1651
static VALUE enum_find(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:212
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1899
VALUE rb_cArray
Definition: array.c:27
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3553
static VALUE enum_zip(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:2088
static ID id_next
Definition: enum.c:22
static VALUE enum_min_by(VALUE obj)
Definition: enum.c:1501
register C_block * p
Definition: crypt.c:309
rb_ivar_set(yielder, id_memo, LONG2NUM(++count))
union RNode::@113 u2
data n
Definition: enum.c:860
#define rb_ary_new3
VALUE rb_hash_new(void)
Definition: hash.c:307
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1804
const char * rb_id2name(ID id)
Definition: ripper.c:17271
static VALUE enum_flat_map(VALUE obj)
Definition: enum.c:476
static VALUE enum_take_while(VALUE obj)
Definition: enum.c:2189
VALUE prev_elts
Definition: enum.c:2369
#define RBASIC_CLEAR_CLASS(obj)
static VALUE enum_find_index(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:278
static VALUE enum_minmax(VALUE obj)
Definition: enum.c:1441
BDIGIT e
Definition: bigdecimal.c:5209
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:706
unsigned long VALUE
Definition: ripper.y:88
void rb_warning(const char *fmt,...)
Definition: error.c:236
static VALUE call_stop(VALUE *v)
Definition: enum.c:2023
#define NODE_DOT2
#define RARRAY_ASET(a, i, v)
VALUE rb_define_module(const char *name)
Definition: class.c:727
#define rb_intern(str)
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
return rb_yield_values(2, rb_enum_values_pack(argc, argv), INT2NUM(n))
VALUE j
Definition: enum.c:1347
static VALUE enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
Definition: enum.c:1839
union RNode::@112 u1
static VALUE enum_group_by(VALUE obj)
Definition: enum.c:751
#define RNODE(obj)
volatile VALUE result
Definition: enum.c:1989
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
VALUE buf
Definition: enum.c:836
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:410
VALUE min
Definition: enum.c:1314
void rb_warn(const char *fmt,...)
Definition: error.c:223
#define SYM2ID(x)
#define bp()
Definition: vm_debug.h:25
VALUE rb_eArgError
Definition: error.c:549
VALUE last
Definition: enum.c:1564
static VALUE call_next(VALUE *v)
Definition: enum.c:2017
#define id_eqq
Definition: enum.c:28