enum.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   enum.c -
00004 
00005   $Author: yugui $
00006   created at: Fri Oct  1 15:15:19 JST 1993
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009 
00010 **********************************************************************/
00011 
00012 #include "ruby/ruby.h"
00013 #include "ruby/util.h"
00014 #include "node.h"
00015 
00016 VALUE rb_mEnumerable;
00017 static ID id_each, id_eqq, id_cmp, id_next, id_size;
00018 
00019 static VALUE
00020 enum_values_pack(int argc, VALUE *argv)
00021 {
00022     if (argc == 0) return Qnil;
00023     if (argc == 1) return argv[0];
00024     return rb_ary_new4(argc, argv);
00025 }
00026 
00027 #define ENUM_WANT_SVALUE() do { \
00028     i = enum_values_pack(argc, argv); \
00029 } while (0)
00030 
00031 #define enum_yield rb_yield_values2
00032 
00033 static VALUE
00034 grep_i(VALUE i, VALUE args, int argc, VALUE *argv)
00035 {
00036     VALUE *arg = (VALUE *)args;
00037     ENUM_WANT_SVALUE();
00038 
00039     if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
00040         rb_ary_push(arg[1], i);
00041     }
00042     return Qnil;
00043 }
00044 
00045 static VALUE
00046 grep_iter_i(VALUE i, VALUE args, int argc, VALUE *argv)
00047 {
00048     VALUE *arg = (VALUE *)args;
00049     ENUM_WANT_SVALUE();
00050 
00051     if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
00052         rb_ary_push(arg[1], rb_yield(i));
00053     }
00054     return Qnil;
00055 }
00056 
00057 /*
00058  *  call-seq:
00059  *     enum.grep(pattern)                   -> array
00060  *     enum.grep(pattern) {| obj | block }  -> array
00061  *
00062  *  Returns an array of every element in <i>enum</i> for which
00063  *  <code>Pattern === element</code>. If the optional <em>block</em> is
00064  *  supplied, each matching element is passed to it, and the block's
00065  *  result is stored in the output array.
00066  *
00067  *     (1..100).grep 38..44   #=> [38, 39, 40, 41, 42, 43, 44]
00068  *     c = IO.constants
00069  *     c.grep(/SEEK/)         #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
00070  *     res = c.grep(/SEEK/) {|v| IO.const_get(v) }
00071  *     res                    #=> [0, 1, 2]
00072  *
00073  */
00074 
00075 static VALUE
00076 enum_grep(VALUE obj, VALUE pat)
00077 {
00078     VALUE ary = rb_ary_new();
00079     VALUE arg[2];
00080 
00081     arg[0] = pat;
00082     arg[1] = ary;
00083 
00084     rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
00085 
00086     return ary;
00087 }
00088 
00089 static VALUE
00090 count_i(VALUE i, VALUE memop, int argc, VALUE *argv)
00091 {
00092     VALUE *memo = (VALUE*)memop;
00093 
00094     ENUM_WANT_SVALUE();
00095 
00096     if (rb_equal(i, memo[1])) {
00097         memo[0]++;
00098     }
00099     return Qnil;
00100 }
00101 
00102 static VALUE
00103 count_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
00104 {
00105     VALUE *memo = (VALUE*)memop;
00106 
00107     if (RTEST(enum_yield(argc, argv))) {
00108         memo[0]++;
00109     }
00110     return Qnil;
00111 }
00112 
00113 static VALUE
00114 count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
00115 {
00116     VALUE *memo = (VALUE*)memop;
00117 
00118     memo[0]++;
00119     return Qnil;
00120 }
00121 
00122 /*
00123  *  call-seq:
00124  *     enum.count                   -> int
00125  *     enum.count(item)             -> int
00126  *     enum.count {| obj | block }  -> int
00127  *
00128  *  Returns the number of items in <i>enum</i>, where #size is called
00129  *  if it responds to it, otherwise the items are counted through
00130  *  enumeration.  If an argument is given, counts the number of items
00131  *  in <i>enum</i>, for which equals to <i>item</i>.  If a block is
00132  *  given, counts the number of elements yielding a true value.
00133  *
00134  *     ary = [1, 2, 4, 2]
00135  *     ary.count             #=> 4
00136  *     ary.count(2)          #=> 2
00137  *     ary.count{|x|x%2==0}  #=> 3
00138  *
00139  */
00140 
00141 static VALUE
00142 enum_count(int argc, VALUE *argv, VALUE obj)
00143 {
00144     VALUE memo[2];      /* [count, condition value] */
00145     rb_block_call_func *func;
00146 
00147     if (argc == 0) {
00148         if (rb_block_given_p()) {
00149             func = count_iter_i;
00150         }
00151         else {
00152             func = count_all_i;
00153         }
00154     }
00155     else {
00156         rb_scan_args(argc, argv, "1", &memo[1]);
00157         if (rb_block_given_p()) {
00158             rb_warn("given block not used");
00159         }
00160         func = count_i;
00161     }
00162 
00163     memo[0] = 0;
00164     rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo);
00165     return INT2NUM(memo[0]);
00166 }
00167 
00168 static VALUE
00169 find_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
00170 {
00171     ENUM_WANT_SVALUE();
00172 
00173     if (RTEST(rb_yield(i))) {
00174         *memo = i;
00175         rb_iter_break();
00176     }
00177     return Qnil;
00178 }
00179 
00180 /*
00181  *  call-seq:
00182  *     enum.detect(ifnone = nil) {| obj | block }  -> obj or nil
00183  *     enum.find(ifnone = nil)   {| obj | block }  -> obj or nil
00184  *     enum.detect(ifnone = nil)                   -> an_enumerator
00185  *     enum.find(ifnone = nil)                     -> an_enumerator
00186  *
00187  *  Passes each entry in <i>enum</i> to <em>block</em>. Returns the
00188  *  first for which <em>block</em> is not false.  If no
00189  *  object matches, calls <i>ifnone</i> and returns its result when it
00190  *  is specified, or returns <code>nil</code> otherwise.
00191  *
00192  *  If no block is given, an enumerator is returned instead.
00193  *
00194  *     (1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
00195  *     (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 }   #=> 35
00196  *
00197  */
00198 
00199 static VALUE
00200 enum_find(int argc, VALUE *argv, VALUE obj)
00201 {
00202     VALUE memo = Qundef;
00203     VALUE if_none;
00204 
00205     rb_scan_args(argc, argv, "01", &if_none);
00206     RETURN_ENUMERATOR(obj, argc, argv);
00207     rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)&memo);
00208     if (memo != Qundef) {
00209         return memo;
00210     }
00211     if (!NIL_P(if_none)) {
00212         return rb_funcall(if_none, rb_intern("call"), 0, 0);
00213     }
00214     return Qnil;
00215 }
00216 
00217 static VALUE
00218 find_index_i(VALUE i, VALUE memop, int argc, VALUE *argv)
00219 {
00220     VALUE *memo = (VALUE*)memop;
00221 
00222     ENUM_WANT_SVALUE();
00223 
00224     if (rb_equal(i, memo[2])) {
00225         memo[0] = UINT2NUM(memo[1]);
00226         rb_iter_break();
00227     }
00228     memo[1]++;
00229     return Qnil;
00230 }
00231 
00232 static VALUE
00233 find_index_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
00234 {
00235     VALUE *memo = (VALUE*)memop;
00236 
00237     if (RTEST(enum_yield(argc, argv))) {
00238         memo[0] = UINT2NUM(memo[1]);
00239         rb_iter_break();
00240     }
00241     memo[1]++;
00242     return Qnil;
00243 }
00244 
00245 /*
00246  *  call-seq:
00247  *     enum.find_index(value)            -> int or nil
00248  *     enum.find_index {| obj | block }  -> int or nil
00249  *     enum.find_index                   -> an_enumerator
00250  *
00251  *  Compares each entry in <i>enum</i> with <em>value</em> or passes
00252  *  to <em>block</em>.  Returns the index for the first for which the
00253  *  evaluated value is non-false.  If no object matches, returns
00254  *  <code>nil</code>
00255  *
00256  *  If neither block nor argument is given, an enumerator is returned instead.
00257  *
00258  *     (1..10).find_index  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
00259  *     (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 }   #=> 34
00260  *     (1..100).find_index(50)                                #=> 49
00261  *
00262  */
00263 
00264 static VALUE
00265 enum_find_index(int argc, VALUE *argv, VALUE obj)
00266 {
00267     VALUE memo[3];      /* [return value, current index, condition value] */
00268     rb_block_call_func *func;
00269 
00270     if (argc == 0) {
00271         RETURN_ENUMERATOR(obj, 0, 0);
00272         func = find_index_iter_i;
00273     }
00274     else {
00275         rb_scan_args(argc, argv, "1", &memo[2]);
00276         if (rb_block_given_p()) {
00277             rb_warn("given block not used");
00278         }
00279         func = find_index_i;
00280     }
00281 
00282     memo[0] = Qnil;
00283     memo[1] = 0;
00284     rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
00285     return memo[0];
00286 }
00287 
00288 static VALUE
00289 find_all_i(VALUE i, VALUE ary, int argc, VALUE *argv)
00290 {
00291     ENUM_WANT_SVALUE();
00292 
00293     if (RTEST(rb_yield(i))) {
00294         rb_ary_push(ary, i);
00295     }
00296     return Qnil;
00297 }
00298 
00299 /*
00300  *  call-seq:
00301  *     enum.find_all {| obj | block }  -> array
00302  *     enum.select   {| obj | block }  -> array
00303  *     enum.find_all                   -> an_enumerator
00304  *     enum.select                     -> an_enumerator
00305  *
00306  *  Returns an array containing all elements of <i>enum</i> for which
00307  *  <em>block</em> is not <code>false</code> (see also
00308  *  <code>Enumerable#reject</code>).
00309  *
00310  *  If no block is given, an enumerator is returned instead.
00311  *
00312  *
00313  *     (1..10).find_all {|i|  i % 3 == 0 }   #=> [3, 6, 9]
00314  *
00315  */
00316 
00317 static VALUE
00318 enum_find_all(VALUE obj)
00319 {
00320     VALUE ary;
00321 
00322     RETURN_ENUMERATOR(obj, 0, 0);
00323 
00324     ary = rb_ary_new();
00325     rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
00326 
00327     return ary;
00328 }
00329 
00330 static VALUE
00331 reject_i(VALUE i, VALUE ary, int argc, VALUE *argv)
00332 {
00333     ENUM_WANT_SVALUE();
00334 
00335     if (!RTEST(rb_yield(i))) {
00336         rb_ary_push(ary, i);
00337     }
00338     return Qnil;
00339 }
00340 
00341 /*
00342  *  call-seq:
00343  *     enum.reject {| obj | block }  -> array
00344  *     enum.reject                   -> an_enumerator
00345  *
00346  *  Returns an array for all elements of <i>enum</i> for which
00347  *  <em>block</em> is false (see also <code>Enumerable#find_all</code>).
00348  *
00349  *  If no block is given, an enumerator is returned instead.
00350  *
00351  *     (1..10).reject {|i|  i % 3 == 0 }   #=> [1, 2, 4, 5, 7, 8, 10]
00352  *
00353  */
00354 
00355 static VALUE
00356 enum_reject(VALUE obj)
00357 {
00358     VALUE ary;
00359 
00360     RETURN_ENUMERATOR(obj, 0, 0);
00361 
00362     ary = rb_ary_new();
00363     rb_block_call(obj, id_each, 0, 0, reject_i, ary);
00364 
00365     return ary;
00366 }
00367 
00368 static VALUE
00369 collect_i(VALUE i, VALUE ary, int argc, VALUE *argv)
00370 {
00371     rb_ary_push(ary, enum_yield(argc, argv));
00372 
00373     return Qnil;
00374 }
00375 
00376 static VALUE
00377 collect_all(VALUE i, VALUE ary, int argc, VALUE *argv)
00378 {
00379     rb_thread_check_ints();
00380     rb_ary_push(ary, enum_values_pack(argc, argv));
00381 
00382     return Qnil;
00383 }
00384 
00385 /*
00386  *  call-seq:
00387  *     enum.collect {| obj | block }  -> array
00388  *     enum.map     {| obj | block }  -> array
00389  *     enum.collect                   -> an_enumerator
00390  *     enum.map                       -> an_enumerator
00391  *
00392  *  Returns a new array with the results of running <em>block</em> once
00393  *  for every element in <i>enum</i>.
00394  *
00395  *  If no block is given, an enumerator is returned instead.
00396  *
00397  *     (1..4).collect {|i| i*i }   #=> [1, 4, 9, 16]
00398  *     (1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]
00399  *
00400  */
00401 
00402 static VALUE
00403 enum_collect(VALUE obj)
00404 {
00405     VALUE ary;
00406 
00407     RETURN_ENUMERATOR(obj, 0, 0);
00408 
00409     ary = rb_ary_new();
00410     rb_block_call(obj, id_each, 0, 0, collect_i, ary);
00411 
00412     return ary;
00413 }
00414 
00415 static VALUE
00416 flat_map_i(VALUE i, VALUE ary, int argc, VALUE *argv)
00417 {
00418     VALUE tmp;
00419 
00420     i = enum_yield(argc, argv);
00421     tmp = rb_check_array_type(i);
00422 
00423     if (NIL_P(tmp)) {
00424         rb_ary_push(ary, i);
00425     }
00426     else {
00427         rb_ary_concat(ary, tmp);
00428     }
00429     return Qnil;
00430 }
00431 
00432 /*
00433  *  call-seq:
00434  *     enum.flat_map       {| obj | block }  -> array
00435  *     enum.collect_concat {| obj | block }  -> array
00436  *     enum.flat_map                         -> an_enumerator
00437  *     enum.collect_concat                   -> an_enumerator
00438  *
00439  *  Returns a new array with the concatenated results of running
00440  *  <em>block</em> once for every element in <i>enum</i>.
00441  *
00442  *  If no block is given, an enumerator is returned instead.
00443  *
00444  *     [[1,2],[3,4]].flat_map {|i| i }   #=> [1, 2, 3, 4]
00445  *
00446  */
00447 
00448 static VALUE
00449 enum_flat_map(VALUE obj)
00450 {
00451     VALUE ary;
00452 
00453     RETURN_ENUMERATOR(obj, 0, 0);
00454 
00455     ary = rb_ary_new();
00456     rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
00457 
00458     return ary;
00459 }
00460 
00461 /*
00462  *  call-seq:
00463  *     enum.to_a      ->    array
00464  *     enum.entries   ->    array
00465  *
00466  *  Returns an array containing the items in <i>enum</i>.
00467  *
00468  *     (1..7).to_a                       #=> [1, 2, 3, 4, 5, 6, 7]
00469  *     { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]
00470  */
00471 static VALUE
00472 enum_to_a(int argc, VALUE *argv, VALUE obj)
00473 {
00474     VALUE ary = rb_ary_new();
00475 
00476     rb_block_call(obj, id_each, argc, argv, collect_all, ary);
00477     OBJ_INFECT(ary, obj);
00478 
00479     return ary;
00480 }
00481 
00482 static VALUE
00483 inject_i(VALUE i, VALUE p, int argc, VALUE *argv)
00484 {
00485     VALUE *memo = (VALUE *)p;
00486 
00487     ENUM_WANT_SVALUE();
00488 
00489     if (memo[0] == Qundef) {
00490         memo[0] = i;
00491     }
00492     else {
00493         memo[0] = rb_yield_values(2, memo[0], i);
00494     }
00495     return Qnil;
00496 }
00497 
00498 static VALUE
00499 inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
00500 {
00501     VALUE *memo = (VALUE *)p;
00502 
00503     ENUM_WANT_SVALUE();
00504 
00505     if (memo[0] == Qundef) {
00506         memo[0] = i;
00507     }
00508     else {
00509         memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
00510     }
00511     return Qnil;
00512 }
00513 
00514 /*
00515  *  call-seq:
00516  *     enum.inject(initial, sym) -> obj
00517  *     enum.inject(sym)          -> obj
00518  *     enum.inject(initial) {| memo, obj | block }  -> obj
00519  *     enum.inject          {| memo, obj | block }  -> obj
00520  *
00521  *     enum.reduce(initial, sym) -> obj
00522  *     enum.reduce(sym)          -> obj
00523  *     enum.reduce(initial) {| memo, obj | block }  -> obj
00524  *     enum.reduce          {| memo, obj | block }  -> obj
00525  *
00526  *  Combines all elements of <i>enum</i> by applying a binary
00527  *  operation, specified by a block or a symbol that names a
00528  *  method or operator.
00529  *
00530  *  If you specify a block, then for each element in <i>enum</i>
00531  *  the block is passed an accumulator value (<i>memo</i>) and the element.
00532  *  If you specify a symbol instead, then each element in the collection
00533  *  will be passed to the named method of <i>memo</i>.
00534  *  In either case, the result becomes the new value for <i>memo</i>.
00535  *  At the end of the iteration, the final value of <i>memo</i> is the
00536  *  return value fo the method.
00537  *
00538  *  If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
00539  *  then uses the first element of collection is used as the initial value
00540  *  of <i>memo</i>.
00541  *
00542  *  Examples:
00543  *
00544  *     # Sum some numbers
00545  *     (5..10).reduce(:+)                            #=> 45
00546  *     # Same using a block and inject
00547  *     (5..10).inject {|sum, n| sum + n }            #=> 45
00548  *     # Multiply some numbers
00549  *     (5..10).reduce(1, :*)                         #=> 151200
00550  *     # Same using a block
00551  *     (5..10).inject(1) {|product, n| product * n } #=> 151200
00552  *     # find the longest word
00553  *     longest = %w{ cat sheep bear }.inject do |memo,word|
00554  *        memo.length > word.length ? memo : word
00555  *     end
00556  *     longest                                       #=> "sheep"
00557  *
00558  */
00559 static VALUE
00560 enum_inject(int argc, VALUE *argv, VALUE obj)
00561 {
00562     VALUE memo[2];
00563     VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;
00564 
00565     switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
00566       case 0:
00567         memo[0] = Qundef;
00568         break;
00569       case 1:
00570         if (rb_block_given_p()) {
00571             break;
00572         }
00573         memo[1] = (VALUE)rb_to_id(memo[0]);
00574         memo[0] = Qundef;
00575         iter = inject_op_i;
00576         break;
00577       case 2:
00578         if (rb_block_given_p()) {
00579             rb_warning("given block not used");
00580         }
00581         memo[1] = (VALUE)rb_to_id(memo[1]);
00582         iter = inject_op_i;
00583         break;
00584     }
00585     rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
00586     if (memo[0] == Qundef) return Qnil;
00587     return memo[0];
00588 }
00589 
00590 static VALUE
00591 partition_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
00592 {
00593     ENUM_WANT_SVALUE();
00594 
00595     if (RTEST(rb_yield(i))) {
00596         rb_ary_push(ary[0], i);
00597     }
00598     else {
00599         rb_ary_push(ary[1], i);
00600     }
00601     return Qnil;
00602 }
00603 
00604 /*
00605  *  call-seq:
00606  *     enum.partition {| obj | block }  -> [ true_array, false_array ]
00607  *     enum.partition                   -> an_enumerator
00608  *
00609  *  Returns two arrays, the first containing the elements of
00610  *  <i>enum</i> for which the block evaluates to true, the second
00611  *  containing the rest.
00612  *
00613  *  If no block is given, an enumerator is returned instead.
00614  *
00615  *     (1..6).partition {|i| (i&1).zero?}   #=> [[2, 4, 6], [1, 3, 5]]
00616  *
00617  */
00618 
00619 static VALUE
00620 enum_partition(VALUE obj)
00621 {
00622     VALUE ary[2];
00623 
00624     RETURN_ENUMERATOR(obj, 0, 0);
00625 
00626     ary[0] = rb_ary_new();
00627     ary[1] = rb_ary_new();
00628     rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)ary);
00629 
00630     return rb_assoc_new(ary[0], ary[1]);
00631 }
00632 
00633 static VALUE
00634 group_by_i(VALUE i, VALUE hash, int argc, VALUE *argv)
00635 {
00636     VALUE group;
00637     VALUE values;
00638 
00639     ENUM_WANT_SVALUE();
00640 
00641     group = rb_yield(i);
00642     values = rb_hash_aref(hash, group);
00643     if (NIL_P(values)) {
00644         values = rb_ary_new3(1, i);
00645         rb_hash_aset(hash, group, values);
00646     }
00647     else {
00648         rb_ary_push(values, i);
00649     }
00650     return Qnil;
00651 }
00652 
00653 /*
00654  *  call-seq:
00655  *     enum.group_by {| obj | block }  -> a_hash
00656  *     enum.group_by                   -> an_enumerator
00657  *
00658  *  Returns a hash, which keys are evaluated result from the
00659  *  block, and values are arrays of elements in <i>enum</i>
00660  *  corresponding to the key.
00661  *
00662  *  If no block is given, an enumerator is returned instead.
00663  *
00664  *     (1..6).group_by {|i| i%3}   #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
00665  *
00666  */
00667 
00668 static VALUE
00669 enum_group_by(VALUE obj)
00670 {
00671     VALUE hash;
00672 
00673     RETURN_ENUMERATOR(obj, 0, 0);
00674 
00675     hash = rb_hash_new();
00676     rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
00677     OBJ_INFECT(hash, obj);
00678 
00679     return hash;
00680 }
00681 
00682 static VALUE
00683 first_i(VALUE i, VALUE *params, int argc, VALUE *argv)
00684 {
00685     ENUM_WANT_SVALUE();
00686 
00687     if (NIL_P(params[1])) {
00688         params[1] = i;
00689         rb_iter_break();
00690     }
00691     else {
00692         long n = params[0];
00693 
00694         rb_ary_push(params[1], i);
00695         n--;
00696         if (n <= 0) {
00697             rb_iter_break();
00698         }
00699         params[0] = n;
00700     }
00701     return Qnil;
00702 }
00703 
00704 /*
00705  *  call-seq:
00706  *     enum.first       ->  obj or nil
00707  *     enum.first(n)    ->  an_array
00708  *
00709  *  Returns the first element, or the first +n+ elements, of the enumerable.
00710  *  If the enumerable is empty, the first form returns <code>nil</code>, and the
00711  *  second form returns an empty array.
00712  *
00713  */
00714 
00715 static VALUE
00716 enum_first(int argc, VALUE *argv, VALUE obj)
00717 {
00718     VALUE n, params[2];
00719 
00720     if (argc == 0) {
00721         params[0] = params[1] = Qnil;
00722     }
00723     else {
00724         long len;
00725 
00726         rb_scan_args(argc, argv, "01", &n);
00727         len = NUM2LONG(n);
00728         if (len == 0) return rb_ary_new2(0);
00729         if (len < 0) {
00730             rb_raise(rb_eArgError, "negative length");
00731         }
00732         params[0] = len;
00733         params[1] = rb_ary_new2(len);
00734     }
00735     rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)params);
00736 
00737     return params[1];
00738 }
00739 
00740 
00741 /*
00742  *  call-seq:
00743  *     enum.sort                     -> array
00744  *     enum.sort {| a, b | block }   -> array
00745  *
00746  *  Returns an array containing the items in <i>enum</i> sorted,
00747  *  either according to their own <code><=></code> method, or by using
00748  *  the results of the supplied block. The block should return -1, 0, or
00749  *  +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
00750  *  Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
00751  *  built-in Schwartzian Transform, useful when key computation or
00752  *  comparison is expensive.
00753  *
00754  *     %w(rhea kea flea).sort         #=> ["flea", "kea", "rhea"]
00755  *     (1..10).sort {|a,b| b <=> a}   #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
00756  */
00757 
00758 static VALUE
00759 enum_sort(VALUE obj)
00760 {
00761     return rb_ary_sort(enum_to_a(0, 0, obj));
00762 }
00763 
00764 static VALUE
00765 sort_by_i(VALUE i, VALUE ary, int argc, VALUE *argv)
00766 {
00767     NODE *memo;
00768 
00769     ENUM_WANT_SVALUE();
00770 
00771     if (RBASIC(ary)->klass) {
00772         rb_raise(rb_eRuntimeError, "sort_by reentered");
00773     }
00774     /* use NODE_DOT2 as memo(v, v, -) */
00775     memo = rb_node_newnode(NODE_DOT2, rb_yield(i), i, 0);
00776     rb_ary_push(ary, (VALUE)memo);
00777     return Qnil;
00778 }
00779 
00780 static int
00781 sort_by_cmp(const void *ap, const void *bp, void *data)
00782 {
00783     VALUE a = (*(NODE *const *)ap)->u1.value;
00784     VALUE b = (*(NODE *const *)bp)->u1.value;
00785     VALUE ary = (VALUE)data;
00786 
00787     if (RBASIC(ary)->klass) {
00788         rb_raise(rb_eRuntimeError, "sort_by reentered");
00789     }
00790     return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
00791 }
00792 
00793 /*
00794  *  call-seq:
00795  *     enum.sort_by {| obj | block }    -> array
00796  *     enum.sort_by                     -> an_enumerator
00797  *
00798  *  Sorts <i>enum</i> using a set of keys generated by mapping the
00799  *  values in <i>enum</i> through the given block.
00800  *
00801  *  If no block is given, an enumerator is returned instead.
00802  *
00803  *     %w{ apple pear fig }.sort_by {|word| word.length}
00804  *                   #=> ["fig", "pear", "apple"]
00805  *
00806  *  The current implementation of <code>sort_by</code> generates an
00807  *  array of tuples containing the original collection element and the
00808  *  mapped value. This makes <code>sort_by</code> fairly expensive when
00809  *  the keysets are simple
00810  *
00811  *     require 'benchmark'
00812  *
00813  *     a = (1..100000).map {rand(100000)}
00814  *
00815  *     Benchmark.bm(10) do |b|
00816  *       b.report("Sort")    { a.sort }
00817  *       b.report("Sort by") { a.sort_by {|a| a} }
00818  *     end
00819  *
00820  *  <em>produces:</em>
00821  *
00822  *     user     system      total        real
00823  *     Sort        0.180000   0.000000   0.180000 (  0.175469)
00824  *     Sort by     1.980000   0.040000   2.020000 (  2.013586)
00825  *
00826  *  However, consider the case where comparing the keys is a non-trivial
00827  *  operation. The following code sorts some files on modification time
00828  *  using the basic <code>sort</code> method.
00829  *
00830  *     files = Dir["*"]
00831  *     sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
00832  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
00833  *
00834  *  This sort is inefficient: it generates two new <code>File</code>
00835  *  objects during every comparison. A slightly better technique is to
00836  *  use the <code>Kernel#test</code> method to generate the modification
00837  *  times directly.
00838  *
00839  *     files = Dir["*"]
00840  *     sorted = files.sort { |a,b|
00841  *       test(?M, a) <=> test(?M, b)
00842  *     }
00843  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
00844  *
00845  *  This still generates many unnecessary <code>Time</code> objects. A
00846  *  more efficient technique is to cache the sort keys (modification
00847  *  times in this case) before the sort. Perl users often call this
00848  *  approach a Schwartzian Transform, after Randal Schwartz. We
00849  *  construct a temporary array, where each element is an array
00850  *  containing our sort key along with the filename. We sort this array,
00851  *  and then extract the filename from the result.
00852  *
00853  *     sorted = Dir["*"].collect { |f|
00854  *        [test(?M, f), f]
00855  *     }.sort.collect { |f| f[1] }
00856  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
00857  *
00858  *  This is exactly what <code>sort_by</code> does internally.
00859  *
00860  *     sorted = Dir["*"].sort_by {|f| test(?M, f)}
00861  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
00862  */
00863 
00864 static VALUE
00865 enum_sort_by(VALUE obj)
00866 {
00867     VALUE ary;
00868     long i;
00869 
00870     RETURN_ENUMERATOR(obj, 0, 0);
00871 
00872     if (TYPE(obj) == T_ARRAY) {
00873         ary  = rb_ary_new2(RARRAY_LEN(obj));
00874     }
00875     else {
00876         ary = rb_ary_new();
00877     }
00878     RBASIC(ary)->klass = 0;
00879     rb_block_call(obj, id_each, 0, 0, sort_by_i, ary);
00880     if (RARRAY_LEN(ary) > 1) {
00881         ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE),
00882                    sort_by_cmp, (void *)ary);
00883     }
00884     if (RBASIC(ary)->klass) {
00885         rb_raise(rb_eRuntimeError, "sort_by reentered");
00886     }
00887     for (i=0; i<RARRAY_LEN(ary); i++) {
00888         RARRAY_PTR(ary)[i] = RNODE(RARRAY_PTR(ary)[i])->u2.value;
00889     }
00890     RBASIC(ary)->klass = rb_cArray;
00891     OBJ_INFECT(ary, obj);
00892 
00893     return ary;
00894 }
00895 
00896 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
00897 
00898 #define DEFINE_ENUMFUNCS(name) \
00899 static VALUE enum_##name##_func(VALUE result, VALUE *memo); \
00900 \
00901 static VALUE \
00902 name##_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
00903 { \
00904     return enum_##name##_func(enum_values_pack(argc, argv), memo); \
00905 } \
00906 \
00907 static VALUE \
00908 name##_iter_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
00909 { \
00910     return enum_##name##_func(enum_yield(argc, argv), memo); \
00911 } \
00912 \
00913 static VALUE \
00914 enum_##name##_func(VALUE result, VALUE *memo)
00915 
00916 DEFINE_ENUMFUNCS(all)
00917 {
00918     if (!RTEST(result)) {
00919         *memo = Qfalse;
00920         rb_iter_break();
00921     }
00922     return Qnil;
00923 }
00924 
00925 /*
00926  *  call-seq:
00927  *     enum.all? [{|obj| block } ]   -> true or false
00928  *
00929  *  Passes each element of the collection to the given block. The method
00930  *  returns <code>true</code> if the block never returns
00931  *  <code>false</code> or <code>nil</code>. If the block is not given,
00932  *  Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
00933  *  <code>all?</code> will return <code>true</code> only if none of the
00934  *  collection members are <code>false</code> or <code>nil</code>.)
00935  *
00936  *     %w{ant bear cat}.all? {|word| word.length >= 3}   #=> true
00937  *     %w{ant bear cat}.all? {|word| word.length >= 4}   #=> false
00938  *     [ nil, true, 99 ].all?                            #=> false
00939  *
00940  */
00941 
00942 static VALUE
00943 enum_all(VALUE obj)
00944 {
00945     VALUE result = Qtrue;
00946 
00947     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)&result);
00948     return result;
00949 }
00950 
00951 DEFINE_ENUMFUNCS(any)
00952 {
00953     if (RTEST(result)) {
00954         *memo = Qtrue;
00955         rb_iter_break();
00956     }
00957     return Qnil;
00958 }
00959 
00960 /*
00961  *  call-seq:
00962  *     enum.any? [{|obj| block } ]   -> true or false
00963  *
00964  *  Passes each element of the collection to the given block. The method
00965  *  returns <code>true</code> if the block ever returns a value other
00966  *  than <code>false</code> or <code>nil</code>. If the block is not
00967  *  given, Ruby adds an implicit block of <code>{|obj| obj}</code> (that
00968  *  is <code>any?</code> will return <code>true</code> if at least one
00969  *  of the collection members is not <code>false</code> or
00970  *  <code>nil</code>.
00971  *
00972  *     %w{ant bear cat}.any? {|word| word.length >= 3}   #=> true
00973  *     %w{ant bear cat}.any? {|word| word.length >= 4}   #=> true
00974  *     [ nil, true, 99 ].any?                            #=> true
00975  *
00976  */
00977 
00978 static VALUE
00979 enum_any(VALUE obj)
00980 {
00981     VALUE result = Qfalse;
00982 
00983     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)&result);
00984     return result;
00985 }
00986 
00987 DEFINE_ENUMFUNCS(one)
00988 {
00989     if (RTEST(result)) {
00990         if (*memo == Qundef) {
00991             *memo = Qtrue;
00992         }
00993         else if (*memo == Qtrue) {
00994             *memo = Qfalse;
00995             rb_iter_break();
00996         }
00997     }
00998     return Qnil;
00999 }
01000 
01001 /*
01002  *  call-seq:
01003  *     enum.one? [{|obj| block }]   -> true or false
01004  *
01005  *  Passes each element of the collection to the given block. The method
01006  *  returns <code>true</code> if the block returns <code>true</code>
01007  *  exactly once. If the block is not given, <code>one?</code> will return
01008  *  <code>true</code> only if exactly one of the collection members is
01009  *  true.
01010  *
01011  *     %w{ant bear cat}.one? {|word| word.length == 4}   #=> true
01012  *     %w{ant bear cat}.one? {|word| word.length > 4}    #=> false
01013  *     %w{ant bear cat}.one? {|word| word.length < 4}    #=> false
01014  *     [ nil, true, 99 ].one?                            #=> false
01015  *     [ nil, true, false ].one?                         #=> true
01016  *
01017  */
01018 
01019 static VALUE
01020 enum_one(VALUE obj)
01021 {
01022     VALUE result = Qundef;
01023 
01024     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)&result);
01025     if (result == Qundef) return Qfalse;
01026     return result;
01027 }
01028 
01029 DEFINE_ENUMFUNCS(none)
01030 {
01031     if (RTEST(result)) {
01032         *memo = Qfalse;
01033         rb_iter_break();
01034     }
01035     return Qnil;
01036 }
01037 
01038 /*
01039  *  call-seq:
01040  *     enum.none? [{|obj| block }]   -> true or false
01041  *
01042  *  Passes each element of the collection to the given block. The method
01043  *  returns <code>true</code> if the block never returns <code>true</code>
01044  *  for all elements. If the block is not given, <code>none?</code> will return
01045  *  <code>true</code> only if none of the collection members is true.
01046  *
01047  *     %w{ant bear cat}.none? {|word| word.length == 5}  #=> true
01048  *     %w{ant bear cat}.none? {|word| word.length >= 4}  #=> false
01049  *     [].none?                                          #=> true
01050  *     [nil].none?                                       #=> true
01051  *     [nil,false].none?                                 #=> true
01052  */
01053 static VALUE
01054 enum_none(VALUE obj)
01055 {
01056     VALUE result = Qtrue;
01057 
01058     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)&result);
01059     return result;
01060 }
01061 
01062 static VALUE
01063 min_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01064 {
01065     VALUE cmp;
01066 
01067     ENUM_WANT_SVALUE();
01068 
01069     if (*memo == Qundef) {
01070         *memo = i;
01071     }
01072     else {
01073         cmp = rb_funcall(i, id_cmp, 1, *memo);
01074         if (rb_cmpint(cmp, i, *memo) < 0) {
01075             *memo = i;
01076         }
01077     }
01078     return Qnil;
01079 }
01080 
01081 static VALUE
01082 min_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
01083 {
01084     VALUE cmp;
01085 
01086     ENUM_WANT_SVALUE();
01087 
01088     if (*memo == Qundef) {
01089         *memo = i;
01090     }
01091     else {
01092         cmp = rb_yield_values(2, i, *memo);
01093         if (rb_cmpint(cmp, i, *memo) < 0) {
01094             *memo = i;
01095         }
01096     }
01097     return Qnil;
01098 }
01099 
01100 
01101 /*
01102  *  call-seq:
01103  *     enum.min                    -> obj
01104  *     enum.min {| a,b | block }   -> obj
01105  *
01106  *  Returns the object in <i>enum</i> with the minimum value. The
01107  *  first form assumes all objects implement <code>Comparable</code>;
01108  *  the second uses the block to return <em>a <=> b</em>.
01109  *
01110  *     a = %w(albatross dog horse)
01111  *     a.min                                  #=> "albatross"
01112  *     a.min {|a,b| a.length <=> b.length }   #=> "dog"
01113  */
01114 
01115 static VALUE
01116 enum_min(VALUE obj)
01117 {
01118     VALUE result = Qundef;
01119 
01120     if (rb_block_given_p()) {
01121         rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)&result);
01122     }
01123     else {
01124         rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)&result);
01125     }
01126     if (result == Qundef) return Qnil;
01127     return result;
01128 }
01129 
01130 static VALUE
01131 max_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01132 {
01133     VALUE cmp;
01134 
01135     ENUM_WANT_SVALUE();
01136 
01137     if (*memo == Qundef) {
01138         *memo = i;
01139     }
01140     else {
01141         cmp = rb_funcall(i, id_cmp, 1, *memo);
01142         if (rb_cmpint(cmp, i, *memo) > 0) {
01143             *memo = i;
01144         }
01145     }
01146     return Qnil;
01147 }
01148 
01149 static VALUE
01150 max_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
01151 {
01152     VALUE cmp;
01153 
01154     ENUM_WANT_SVALUE();
01155 
01156     if (*memo == Qundef) {
01157         *memo = i;
01158     }
01159     else {
01160         cmp = rb_yield_values(2, i, *memo);
01161         if (rb_cmpint(cmp, i, *memo) > 0) {
01162             *memo = i;
01163         }
01164     }
01165     return Qnil;
01166 }
01167 
01168 /*
01169  *  call-seq:
01170  *     enum.max                   -> obj
01171  *     enum.max {|a,b| block }    -> obj
01172  *
01173  *  Returns the object in _enum_ with the maximum value. The
01174  *  first form assumes all objects implement <code>Comparable</code>;
01175  *  the second uses the block to return <em>a <=> b</em>.
01176  *
01177  *     a = %w(albatross dog horse)
01178  *     a.max                                  #=> "horse"
01179  *     a.max {|a,b| a.length <=> b.length }   #=> "albatross"
01180  */
01181 
01182 static VALUE
01183 enum_max(VALUE obj)
01184 {
01185     VALUE result = Qundef;
01186 
01187     if (rb_block_given_p()) {
01188         rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)&result);
01189     }
01190     else {
01191         rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)&result);
01192     }
01193     if (result == Qundef) return Qnil;
01194     return result;
01195 }
01196 
01197 struct minmax_t {
01198     VALUE min;
01199     VALUE max;
01200     VALUE last;
01201 };
01202 
01203 static void
01204 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
01205 {
01206     int n;
01207 
01208     if (memo->min == Qundef) {
01209         memo->min = i;
01210         memo->max = j;
01211     }
01212     else {
01213         n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo->min), i, memo->min);
01214         if (n < 0) {
01215             memo->min = i;
01216         }
01217         n = rb_cmpint(rb_funcall(j, id_cmp, 1, memo->max), j, memo->max);
01218         if (n > 0) {
01219             memo->max = j;
01220         }
01221     }
01222 }
01223 
01224 static VALUE
01225 minmax_i(VALUE i, VALUE _memo, int argc, VALUE *argv)
01226 {
01227     struct minmax_t *memo = (struct minmax_t *)_memo;
01228     int n;
01229     VALUE j;
01230 
01231     ENUM_WANT_SVALUE();
01232 
01233     if (memo->last == Qundef) {
01234         memo->last = i;
01235         return Qnil;
01236     }
01237     j = memo->last;
01238     memo->last = Qundef;
01239 
01240     n = rb_cmpint(rb_funcall(j, id_cmp, 1, i), j, i);
01241     if (n == 0)
01242         i = j;
01243     else if (n < 0) {
01244         VALUE tmp;
01245         tmp = i;
01246         i = j;
01247         j = tmp;
01248     }
01249 
01250     minmax_i_update(i, j, memo);
01251 
01252     return Qnil;
01253 }
01254 
01255 static void
01256 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
01257 {
01258     int n;
01259 
01260     if (memo->min == Qundef) {
01261         memo->min = i;
01262         memo->max = j;
01263     }
01264     else {
01265         n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
01266         if (n < 0) {
01267             memo->min = i;
01268         }
01269         n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
01270         if (n > 0) {
01271             memo->max = j;
01272         }
01273     }
01274 }
01275 
01276 static VALUE
01277 minmax_ii(VALUE i, VALUE _memo, int argc, VALUE *argv)
01278 {
01279     struct minmax_t *memo = (struct minmax_t *)_memo;
01280     int n;
01281     VALUE j;
01282 
01283     ENUM_WANT_SVALUE();
01284 
01285     if (memo->last == Qundef) {
01286         memo->last = i;
01287         return Qnil;
01288     }
01289     j = memo->last;
01290     memo->last = Qundef;
01291 
01292     n = rb_cmpint(rb_yield_values(2, j, i), j, i);
01293     if (n == 0)
01294         i = j;
01295     else if (n < 0) {
01296         VALUE tmp;
01297         tmp = i;
01298         i = j;
01299         j = tmp;
01300     }
01301 
01302     minmax_ii_update(i, j, memo);
01303 
01304     return Qnil;
01305 }
01306 
01307 /*
01308  *  call-seq:
01309  *     enum.minmax                   -> [min,max]
01310  *     enum.minmax {|a,b| block }    -> [min,max]
01311  *
01312  *  Returns two elements array which contains the minimum and the
01313  *  maximum value in the enumerable.  The first form assumes all
01314  *  objects implement <code>Comparable</code>; the second uses the
01315  *  block to return <em>a <=> b</em>.
01316  *
01317  *     a = %w(albatross dog horse)
01318  *     a.minmax                                  #=> ["albatross", "horse"]
01319  *     a.minmax {|a,b| a.length <=> b.length }   #=> ["dog", "albatross"]
01320  */
01321 
01322 static VALUE
01323 enum_minmax(VALUE obj)
01324 {
01325     struct minmax_t memo;
01326     VALUE ary = rb_ary_new3(2, Qnil, Qnil);
01327 
01328     memo.min = Qundef;
01329     memo.last = Qundef;
01330     if (rb_block_given_p()) {
01331         rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)&memo);
01332         if (memo.last != Qundef)
01333             minmax_ii_update(memo.last, memo.last, &memo);
01334     }
01335     else {
01336         rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)&memo);
01337         if (memo.last != Qundef)
01338             minmax_i_update(memo.last, memo.last, &memo);
01339     }
01340     if (memo.min != Qundef) {
01341         rb_ary_store(ary, 0, memo.min);
01342         rb_ary_store(ary, 1, memo.max);
01343     }
01344     return ary;
01345 }
01346 
01347 static VALUE
01348 min_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01349 {
01350     VALUE v;
01351 
01352     ENUM_WANT_SVALUE();
01353 
01354     v = rb_yield(i);
01355     if (memo[0] == Qundef) {
01356         memo[0] = v;
01357         memo[1] = i;
01358     }
01359     else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
01360         memo[0] = v;
01361         memo[1] = i;
01362     }
01363     return Qnil;
01364 }
01365 
01366 /*
01367  *  call-seq:
01368  *     enum.min_by {|obj| block }   -> obj
01369  *     enum.min_by                  -> an_enumerator
01370  *
01371  *  Returns the object in <i>enum</i> that gives the minimum
01372  *  value from the given block.
01373  *
01374  *  If no block is given, an enumerator is returned instead.
01375  *
01376  *     a = %w(albatross dog horse)
01377  *     a.min_by {|x| x.length }   #=> "dog"
01378  */
01379 
01380 static VALUE
01381 enum_min_by(VALUE obj)
01382 {
01383     VALUE memo[2];
01384 
01385     RETURN_ENUMERATOR(obj, 0, 0);
01386 
01387     memo[0] = Qundef;
01388     memo[1] = Qnil;
01389     rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
01390     return memo[1];
01391 }
01392 
01393 static VALUE
01394 max_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01395 {
01396     VALUE v;
01397 
01398     ENUM_WANT_SVALUE();
01399 
01400     v = rb_yield(i);
01401     if (memo[0] == Qundef) {
01402         memo[0] = v;
01403         memo[1] = i;
01404     }
01405     else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) > 0) {
01406         memo[0] = v;
01407         memo[1] = i;
01408     }
01409     return Qnil;
01410 }
01411 
01412 /*
01413  *  call-seq:
01414  *     enum.max_by {|obj| block }   -> obj
01415  *     enum.max_by                  -> an_enumerator
01416  *
01417  *  Returns the object in <i>enum</i> that gives the maximum
01418  *  value from the given block.
01419  *
01420  *  If no block is given, an enumerator is returned instead.
01421  *
01422  *     a = %w(albatross dog horse)
01423  *     a.max_by {|x| x.length }   #=> "albatross"
01424  */
01425 
01426 static VALUE
01427 enum_max_by(VALUE obj)
01428 {
01429     VALUE memo[2];
01430 
01431     RETURN_ENUMERATOR(obj, 0, 0);
01432 
01433     memo[0] = Qundef;
01434     memo[1] = Qnil;
01435     rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
01436     return memo[1];
01437 }
01438 
01439 struct minmax_by_t {
01440     VALUE min_bv;
01441     VALUE max_bv;
01442     VALUE min;
01443     VALUE max;
01444     VALUE last_bv;
01445     VALUE last;
01446 };
01447 
01448 static void
01449 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
01450 {
01451     if (memo->min_bv == Qundef) {
01452         memo->min_bv = v1;
01453         memo->max_bv = v2;
01454         memo->min = i1;
01455         memo->max = i2;
01456     }
01457     else {
01458         if (rb_cmpint(rb_funcall(v1, id_cmp, 1, memo->min_bv), v1, memo->min_bv) < 0) {
01459             memo->min_bv = v1;
01460             memo->min = i1;
01461         }
01462         if (rb_cmpint(rb_funcall(v2, id_cmp, 1, memo->max_bv), v2, memo->max_bv) > 0) {
01463             memo->max_bv = v2;
01464             memo->max = i2;
01465         }
01466     }
01467 }
01468 
01469 static VALUE
01470 minmax_by_i(VALUE i, VALUE _memo, int argc, VALUE *argv)
01471 {
01472     struct minmax_by_t *memo = (struct minmax_by_t *)_memo;
01473     VALUE vi, vj, j;
01474     int n;
01475 
01476     ENUM_WANT_SVALUE();
01477 
01478     vi = rb_yield(i);
01479 
01480     if (memo->last_bv == Qundef) {
01481         memo->last_bv = vi;
01482         memo->last = i;
01483         return Qnil;
01484     }
01485     vj = memo->last_bv;
01486     j = memo->last;
01487     memo->last_bv = Qundef;
01488 
01489     n = rb_cmpint(rb_funcall(vj, id_cmp, 1, vi), vj, vi);
01490     if (n == 0) {
01491         i = j;
01492         vi = vj;
01493     }
01494     else if (n < 0) {
01495         VALUE tmp;
01496         tmp = i;
01497         i = j;
01498         j = tmp;
01499         tmp = vi;
01500         vi = vj;
01501         vj = tmp;
01502     }
01503 
01504     minmax_by_i_update(vi, vj, i, j, memo);
01505 
01506     return Qnil;
01507 }
01508 
01509 /*
01510  *  call-seq:
01511  *     enum.minmax_by {|obj| block }   -> [min, max]
01512  *     enum.minmax_by                  -> an_enumerator
01513  *
01514  *  Returns two elements array array containing the objects in
01515  *  <i>enum</i> that gives the minimum and maximum values respectively
01516  *  from the given block.
01517  *
01518  *  If no block is given, an enumerator is returned instead.
01519  *
01520  *     a = %w(albatross dog horse)
01521  *     a.minmax_by {|x| x.length }   #=> ["dog", "albatross"]
01522  */
01523 
01524 static VALUE
01525 enum_minmax_by(VALUE obj)
01526 {
01527     struct minmax_by_t memo;
01528 
01529     RETURN_ENUMERATOR(obj, 0, 0);
01530 
01531     memo.min_bv = Qundef;
01532     memo.max_bv = Qundef;
01533     memo.min = Qnil;
01534     memo.max = Qnil;
01535     memo.last_bv = Qundef;
01536     memo.last = Qundef;
01537     rb_block_call(obj, id_each, 0, 0, minmax_by_i, (VALUE)&memo);
01538     if (memo.last_bv != Qundef)
01539         minmax_by_i_update(memo.last_bv, memo.last_bv, memo.last, memo.last, &memo);
01540     return rb_assoc_new(memo.min, memo.max);
01541 }
01542 
01543 static VALUE
01544 member_i(VALUE iter, VALUE *memo, int argc, VALUE *argv)
01545 {
01546     if (rb_equal(enum_values_pack(argc, argv), memo[0])) {
01547         memo[1] = Qtrue;
01548         rb_iter_break();
01549     }
01550     return Qnil;
01551 }
01552 
01553 /*
01554  *  call-seq:
01555  *     enum.include?(obj)     -> true or false
01556  *     enum.member?(obj)      -> true or false
01557  *
01558  *  Returns <code>true</code> if any member of <i>enum</i> equals
01559  *  <i>obj</i>. Equality is tested using <code>==</code>.
01560  *
01561  *     IO.constants.include? :SEEK_SET          #=> true
01562  *     IO.constants.include? :SEEK_NO_FURTHER   #=> false
01563  *
01564  */
01565 
01566 static VALUE
01567 enum_member(VALUE obj, VALUE val)
01568 {
01569     VALUE memo[2];
01570 
01571     memo[0] = val;
01572     memo[1] = Qfalse;
01573     rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
01574     return memo[1];
01575 }
01576 
01577 static VALUE
01578 each_with_index_i(VALUE i, VALUE memo, int argc, VALUE *argv)
01579 {
01580     long n = (*(VALUE *)memo)++;
01581 
01582     return rb_yield_values(2, enum_values_pack(argc, argv), INT2NUM(n));
01583 }
01584 
01585 /*
01586  *  call-seq:
01587  *     enum.each_with_index(*args) {|obj, i| block }   ->  enum
01588  *     enum.each_with_index(*args)                     ->  an_enumerator
01589  *
01590  *  Calls <em>block</em> with two arguments, the item and its index,
01591  *  for each item in <i>enum</i>.  Given arguments are passed through
01592  *  to #each().
01593  *
01594  *  If no block is given, an enumerator is returned instead.
01595  *
01596  *     hash = Hash.new
01597  *     %w(cat dog wombat).each_with_index {|item, index|
01598  *       hash[item] = index
01599  *     }
01600  *     hash   #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
01601  *
01602  */
01603 
01604 static VALUE
01605 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
01606 {
01607     long memo;
01608 
01609     RETURN_ENUMERATOR(obj, argc, argv);
01610 
01611     memo = 0;
01612     rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)&memo);
01613     return obj;
01614 }
01615 
01616 
01617 /*
01618  *  call-seq:
01619  *     enum.reverse_each(*args) {|item| block }   ->  enum
01620  *     enum.reverse_each(*args)                   ->  an_enumerator
01621  *
01622  *  Builds a temporary array and traverses that array in reverse order.
01623  *
01624  *  If no block is given, an enumerator is returned instead.
01625  *
01626  */
01627 
01628 static VALUE
01629 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
01630 {
01631     VALUE ary;
01632     long i;
01633 
01634     RETURN_ENUMERATOR(obj, argc, argv);
01635 
01636     ary = enum_to_a(argc, argv, obj);
01637 
01638     for (i = RARRAY_LEN(ary); --i >= 0; ) {
01639         rb_yield(RARRAY_PTR(ary)[i]);
01640     }
01641 
01642     return obj;
01643 }
01644 
01645 
01646 static VALUE
01647 each_val_i(VALUE i, VALUE p, int argc, VALUE *argv)
01648 {
01649     ENUM_WANT_SVALUE();
01650     rb_yield(i);
01651     return Qnil;
01652 }
01653 
01654 /*
01655  *  call-seq:
01656  *     enum.each_entry {|obj| block}  -> enum
01657  *     enum.each_entry                -> an_enumerator
01658  *
01659  *  Calls <i>block</i> once for each element in +self+, passing that
01660  *  element as a parameter, converting multiple values from yield to an
01661  *  array.
01662  *
01663  *  If no block is given, an enumerator is returned instead.
01664  *
01665  *     class Foo
01666  *       include Enumerable
01667  *       def each
01668  *         yield 1
01669  *         yield 1,2
01670  *       end
01671  *     end
01672  *     Foo.new.each_entry{|o| print o, " -- "}
01673  *
01674  *  produces:
01675  *
01676  *     1 -- [1, 2] --
01677  */
01678 
01679 static VALUE
01680 enum_each_entry(int argc, VALUE *argv, VALUE obj)
01681 {
01682     RETURN_ENUMERATOR(obj, argc, argv);
01683     rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
01684     return obj;
01685 }
01686 
01687 static VALUE
01688 each_slice_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01689 {
01690     VALUE ary = memo[0];
01691     VALUE v = Qnil;
01692     long size = (long)memo[1];
01693     ENUM_WANT_SVALUE();
01694 
01695     rb_ary_push(ary, i);
01696 
01697     if (RARRAY_LEN(ary) == size) {
01698         v = rb_yield(ary);
01699         memo[0] = rb_ary_new2(size);
01700     }
01701 
01702     return v;
01703 }
01704 
01705 /*
01706  *  call-seq:
01707  *    enum.each_slice(n) {...}  ->  nil
01708  *    enum.each_slice(n)        ->  an_enumerator
01709  *
01710  *  Iterates the given block for each slice of <n> elements.  If no
01711  *  block is given, returns an enumerator.
01712  *
01713  *  e.g.:
01714  *      (1..10).each_slice(3) {|a| p a}
01715  *      # outputs below
01716  *      [1, 2, 3]
01717  *      [4, 5, 6]
01718  *      [7, 8, 9]
01719  *      [10]
01720  *
01721  */
01722 static VALUE
01723 enum_each_slice(VALUE obj, VALUE n)
01724 {
01725     long size = NUM2LONG(n);
01726     VALUE args[2], ary;
01727 
01728     if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
01729     RETURN_ENUMERATOR(obj, 1, &n);
01730     args[0] = rb_ary_new2(size);
01731     args[1] = (VALUE)size;
01732 
01733     rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)args);
01734 
01735     ary = args[0];
01736     if (RARRAY_LEN(ary) > 0) rb_yield(ary);
01737 
01738     return Qnil;
01739 }
01740 
01741 static VALUE
01742 each_cons_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
01743 {
01744     VALUE ary = memo[0];
01745     VALUE v = Qnil;
01746     long size = (long)memo[1];
01747     ENUM_WANT_SVALUE();
01748 
01749     if (RARRAY_LEN(ary) == size) {
01750         rb_ary_shift(ary);
01751     }
01752     rb_ary_push(ary, i);
01753     if (RARRAY_LEN(ary) == size) {
01754         v = rb_yield(rb_ary_dup(ary));
01755     }
01756     return v;
01757 }
01758 
01759 /*
01760  *  call-seq:
01761  *    enum.each_cons(n) {...}   ->  nil
01762  *    enum.each_cons(n)         ->  an_enumerator
01763  *
01764  *  Iterates the given block for each array of consecutive <n>
01765  *  elements.  If no block is given, returns an enumerator.
01766  *
01767  *  e.g.:
01768  *      (1..10).each_cons(3) {|a| p a}
01769  *      # outputs below
01770  *      [1, 2, 3]
01771  *      [2, 3, 4]
01772  *      [3, 4, 5]
01773  *      [4, 5, 6]
01774  *      [5, 6, 7]
01775  *      [6, 7, 8]
01776  *      [7, 8, 9]
01777  *      [8, 9, 10]
01778  *
01779  */
01780 static VALUE
01781 enum_each_cons(VALUE obj, VALUE n)
01782 {
01783     long size = NUM2LONG(n);
01784     VALUE args[2];
01785 
01786     if (size <= 0) rb_raise(rb_eArgError, "invalid size");
01787     RETURN_ENUMERATOR(obj, 1, &n);
01788     args[0] = rb_ary_new2(size);
01789     args[1] = (VALUE)size;
01790 
01791     rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)args);
01792 
01793     return Qnil;
01794 }
01795 
01796 static VALUE
01797 each_with_object_i(VALUE i, VALUE memo, int argc, VALUE *argv)
01798 {
01799     ENUM_WANT_SVALUE();
01800     return rb_yield_values(2, i, memo);
01801 }
01802 
01803 /*
01804  *  call-seq:
01805  *    enum.each_with_object(obj) {|(*args), memo_obj| ... }  ->  obj
01806  *    enum.each_with_object(obj)                             ->  an_enumerator
01807  *
01808  *  Iterates the given block for each element with an arbitrary
01809  *  object given, and returns the initially given object.
01810  *
01811  *  If no block is given, returns an enumerator.
01812  *
01813  *  e.g.:
01814  *      evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
01815  *      #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
01816  *
01817  */
01818 static VALUE
01819 enum_each_with_object(VALUE obj, VALUE memo)
01820 {
01821     RETURN_ENUMERATOR(obj, 1, &memo);
01822 
01823     rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
01824 
01825     return memo;
01826 }
01827 
01828 static VALUE
01829 zip_ary(VALUE val, NODE *memo, int argc, VALUE *argv)
01830 {
01831     volatile VALUE result = memo->u1.value;
01832     volatile VALUE args = memo->u2.value;
01833     long n = memo->u3.cnt++;
01834     volatile VALUE tmp;
01835     int i;
01836 
01837     tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
01838     rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
01839     for (i=0; i<RARRAY_LEN(args); i++) {
01840         VALUE e = RARRAY_PTR(args)[i];
01841 
01842         if (RARRAY_LEN(e) <= n) {
01843             rb_ary_push(tmp, Qnil);
01844         }
01845         else {
01846             rb_ary_push(tmp, RARRAY_PTR(e)[n]);
01847         }
01848     }
01849     if (NIL_P(result)) {
01850         rb_yield(tmp);
01851     }
01852     else {
01853         rb_ary_push(result, tmp);
01854     }
01855     return Qnil;
01856 }
01857 
01858 static VALUE
01859 call_next(VALUE *v)
01860 {
01861     return v[0] = rb_funcall(v[1], id_next, 0, 0);
01862 }
01863 
01864 static VALUE
01865 call_stop(VALUE *v)
01866 {
01867     return v[0] = Qundef;
01868 }
01869 
01870 static VALUE
01871 zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
01872 {
01873     volatile VALUE result = memo->u1.value;
01874     volatile VALUE args = memo->u2.value;
01875     volatile VALUE tmp;
01876     int i;
01877 
01878     tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
01879     rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
01880     for (i=0; i<RARRAY_LEN(args); i++) {
01881         if (NIL_P(RARRAY_PTR(args)[i])) {
01882             rb_ary_push(tmp, Qnil);
01883         }
01884         else {
01885             VALUE v[2];
01886 
01887             v[1] = RARRAY_PTR(args)[i];
01888             rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
01889             if (v[0] == Qundef) {
01890                 RARRAY_PTR(args)[i] = Qnil;
01891                 v[0] = Qnil;
01892             }
01893             rb_ary_push(tmp, v[0]);
01894         }
01895     }
01896     if (NIL_P(result)) {
01897         rb_yield(tmp);
01898     }
01899     else {
01900         rb_ary_push(result, tmp);
01901     }
01902     return Qnil;
01903 }
01904 
01905 /*
01906  *  call-seq:
01907  *     enum.zip(arg, ...)                   -> an_array_of_array
01908  *     enum.zip(arg, ...) {|arr| block }    -> nil
01909  *
01910  *  Takes one element from <i>enum</i> and merges corresponding
01911  *  elements from each <i>args</i>.  This generates a sequence of
01912  *  <em>n</em>-element arrays, where <em>n</em> is one more than the
01913  *  count of arguments.  The length of the resulting sequence will be
01914  *  <code>enum#size</code>.  If the size of any argument is less than
01915  *  <code>enum#size</code>, <code>nil</code> values are supplied. If
01916  *  a block is given, it is invoked for each output array, otherwise
01917  *  an array of arrays is returned.
01918  *
01919  *     a = [ 4, 5, 6 ]
01920  *     b = [ 7, 8, 9 ]
01921  *
01922  *     [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
01923  *     [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
01924  *     a.zip([1,2],[8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
01925  *
01926  */
01927 
01928 static VALUE
01929 enum_zip(int argc, VALUE *argv, VALUE obj)
01930 {
01931     int i;
01932     ID conv;
01933     NODE *memo;
01934     VALUE result = Qnil;
01935     VALUE args = rb_ary_new4(argc, argv);
01936     int allary = TRUE;
01937 
01938     argv = RARRAY_PTR(args);
01939     for (i=0; i<argc; i++) {
01940         VALUE ary = rb_check_array_type(argv[i]);
01941         if (NIL_P(ary)) {
01942             allary = FALSE;
01943             break;
01944         }
01945         argv[i] = ary;
01946     }
01947     if (!allary) {
01948         CONST_ID(conv, "to_enum");
01949         for (i=0; i<argc; i++) {
01950             argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
01951         }
01952     }
01953     if (!rb_block_given_p()) {
01954         result = rb_ary_new();
01955     }
01956     /* use NODE_DOT2 as memo(v, v, -) */
01957     memo = rb_node_newnode(NODE_DOT2, result, args, 0);
01958     rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
01959 
01960     return result;
01961 }
01962 
01963 static VALUE
01964 take_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
01965 {
01966     rb_ary_push(arg[0], enum_values_pack(argc, argv));
01967     if (--arg[1] == 0) rb_iter_break();
01968     return Qnil;
01969 }
01970 
01971 /*
01972  *  call-seq:
01973  *     enum.take(n)               -> array
01974  *
01975  *  Returns first n elements from <i>enum</i>.
01976  *
01977  *     a = [1, 2, 3, 4, 5, 0]
01978  *     a.take(3)             #=> [1, 2, 3]
01979  *
01980  */
01981 
01982 static VALUE
01983 enum_take(VALUE obj, VALUE n)
01984 {
01985     VALUE args[2];
01986     long len = NUM2LONG(n);
01987 
01988     if (len < 0) {
01989         rb_raise(rb_eArgError, "attempt to take negative size");
01990     }
01991 
01992     if (len == 0) return rb_ary_new2(0);
01993     args[0] = rb_ary_new();
01994     args[1] = len;
01995     rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)args);
01996     return args[0];
01997 }
01998 
01999 
02000 static VALUE
02001 take_while_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
02002 {
02003     if (!RTEST(enum_yield(argc, argv))) rb_iter_break();
02004     rb_ary_push(*ary, enum_values_pack(argc, argv));
02005     return Qnil;
02006 }
02007 
02008 /*
02009  *  call-seq:
02010  *     enum.take_while {|arr| block }   -> array
02011  *     enum.take_while                  -> an_enumerator
02012  *
02013  *  Passes elements to the block until the block returns +nil+ or +false+,
02014  *  then stops iterating and returns an array of all prior elements.
02015  *
02016  *  If no block is given, an enumerator is returned instead.
02017  *
02018  *     a = [1, 2, 3, 4, 5, 0]
02019  *     a.take_while {|i| i < 3 }   #=> [1, 2]
02020  *
02021  */
02022 
02023 static VALUE
02024 enum_take_while(VALUE obj)
02025 {
02026     VALUE ary;
02027 
02028     RETURN_ENUMERATOR(obj, 0, 0);
02029     ary = rb_ary_new();
02030     rb_block_call(obj, id_each, 0, 0, take_while_i, (VALUE)&ary);
02031     return ary;
02032 }
02033 
02034 static VALUE
02035 drop_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
02036 {
02037     if (arg[1] == 0) {
02038         rb_ary_push(arg[0], enum_values_pack(argc, argv));
02039     }
02040     else {
02041         arg[1]--;
02042     }
02043     return Qnil;
02044 }
02045 
02046 /*
02047  *  call-seq:
02048  *     enum.drop(n)               -> array
02049  *
02050  *  Drops first n elements from <i>enum</i>, and returns rest elements
02051  *  in an array.
02052  *
02053  *     a = [1, 2, 3, 4, 5, 0]
02054  *     a.drop(3)             #=> [4, 5, 0]
02055  *
02056  */
02057 
02058 static VALUE
02059 enum_drop(VALUE obj, VALUE n)
02060 {
02061     VALUE args[2];
02062     long len = NUM2LONG(n);
02063 
02064     if (len < 0) {
02065         rb_raise(rb_eArgError, "attempt to drop negative size");
02066     }
02067 
02068     args[1] = len;
02069     args[0] = rb_ary_new();
02070     rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)args);
02071     return args[0];
02072 }
02073 
02074 
02075 static VALUE
02076 drop_while_i(VALUE i, VALUE *args, int argc, VALUE *argv)
02077 {
02078     ENUM_WANT_SVALUE();
02079 
02080     if (!args[1] && !RTEST(rb_yield(i))) {
02081         args[1] = Qtrue;
02082     }
02083     if (args[1]) {
02084         rb_ary_push(args[0], i);
02085     }
02086     return Qnil;
02087 }
02088 
02089 /*
02090  *  call-seq:
02091  *     enum.drop_while {|arr| block }   -> array
02092  *     enum.drop_while                  -> an_enumerator
02093  *
02094  *  Drops elements up to, but not including, the first element for
02095  *  which the block returns +nil+ or +false+ and returns an array
02096  *  containing the remaining elements.
02097  *
02098  *  If no block is given, an enumerator is returned instead.
02099  *
02100  *     a = [1, 2, 3, 4, 5, 0]
02101  *     a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
02102  *
02103  */
02104 
02105 static VALUE
02106 enum_drop_while(VALUE obj)
02107 {
02108     VALUE args[2];
02109 
02110     RETURN_ENUMERATOR(obj, 0, 0);
02111     args[0] = rb_ary_new();
02112     args[1] = Qfalse;
02113     rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)args);
02114     return args[0];
02115 }
02116 
02117 static VALUE
02118 cycle_i(VALUE i, VALUE ary, int argc, VALUE *argv)
02119 {
02120     ENUM_WANT_SVALUE();
02121 
02122     rb_ary_push(ary, i);
02123     rb_yield(i);
02124     return Qnil;
02125 }
02126 
02127 /*
02128  *  call-seq:
02129  *     enum.cycle(n=nil) {|obj| block }   ->  nil
02130  *     enum.cycle(n=nil)                  ->  an_enumerator
02131  *
02132  *  Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
02133  *  times or forever if none or +nil+ is given.  If a non-positive
02134  *  number is given or the collection is empty, does nothing.  Returns
02135  *  +nil+ if the loop has finished without getting interrupted.
02136  *
02137  *  Enumerable#cycle saves elements in an internal array so changes
02138  *  to <i>enum</i> after the first pass have no effect.
02139  *
02140  *  If no block is given, an enumerator is returned instead.
02141  *
02142  *     a = ["a", "b", "c"]
02143  *     a.cycle {|x| puts x }  # print, a, b, c, a, b, c,.. forever.
02144  *     a.cycle(2) {|x| puts x }  # print, a, b, c, a, b, c.
02145  *
02146  */
02147 
02148 static VALUE
02149 enum_cycle(int argc, VALUE *argv, VALUE obj)
02150 {
02151     VALUE ary;
02152     VALUE nv = Qnil;
02153     long n, i, len;
02154 
02155     rb_scan_args(argc, argv, "01", &nv);
02156 
02157     RETURN_ENUMERATOR(obj, argc, argv);
02158     if (NIL_P(nv)) {
02159         n = -1;
02160     }
02161     else {
02162         n = NUM2LONG(nv);
02163         if (n <= 0) return Qnil;
02164     }
02165     ary = rb_ary_new();
02166     RBASIC(ary)->klass = 0;
02167     rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
02168     len = RARRAY_LEN(ary);
02169     if (len == 0) return Qnil;
02170     while (n < 0 || 0 < --n) {
02171         for (i=0; i<len; i++) {
02172             rb_yield(RARRAY_PTR(ary)[i]);
02173         }
02174     }
02175     return Qnil;
02176 }
02177 
02178 struct chunk_arg {
02179     VALUE categorize;
02180     VALUE state;
02181     VALUE prev_value;
02182     VALUE prev_elts;
02183     VALUE yielder;
02184 };
02185 
02186 static VALUE
02187 chunk_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
02188 {
02189     struct chunk_arg *argp = (struct chunk_arg *)_argp;
02190     VALUE v;
02191     VALUE alone = ID2SYM(rb_intern("_alone"));
02192     VALUE separator = ID2SYM(rb_intern("_separator"));
02193 
02194     ENUM_WANT_SVALUE();
02195 
02196     if (NIL_P(argp->state))
02197         v = rb_funcall(argp->categorize, rb_intern("call"), 1, i);
02198     else
02199         v = rb_funcall(argp->categorize, rb_intern("call"), 2, i, argp->state);
02200 
02201     if (v == alone) {
02202         if (!NIL_P(argp->prev_value)) {
02203             rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02204             argp->prev_value = argp->prev_elts = Qnil;
02205         }
02206         rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(v, rb_ary_new3(1, i)));
02207     }
02208     else if (NIL_P(v) || v == separator) {
02209         if (!NIL_P(argp->prev_value)) {
02210             rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02211             argp->prev_value = argp->prev_elts = Qnil;
02212         }
02213     }
02214     else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
02215         rb_raise(rb_eRuntimeError, "symbol begins with an underscore is reserved");
02216     }
02217     else {
02218         if (NIL_P(argp->prev_value)) {
02219             argp->prev_value = v;
02220             argp->prev_elts = rb_ary_new3(1, i);
02221         }
02222         else {
02223             if (rb_equal(argp->prev_value, v)) {
02224                 rb_ary_push(argp->prev_elts, i);
02225             }
02226             else {
02227                 rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02228                 argp->prev_value = v;
02229                 argp->prev_elts = rb_ary_new3(1, i);
02230             }
02231         }
02232     }
02233     return Qnil;
02234 }
02235 
02236 static VALUE
02237 chunk_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
02238 {
02239     VALUE enumerable;
02240     struct chunk_arg arg;
02241 
02242     enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
02243     arg.categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
02244     arg.state = rb_ivar_get(enumerator, rb_intern("chunk_initial_state"));
02245     arg.prev_value = Qnil;
02246     arg.prev_elts = Qnil;
02247     arg.yielder = yielder;
02248 
02249     if (!NIL_P(arg.state))
02250         arg.state = rb_obj_dup(arg.state);
02251 
02252     rb_block_call(enumerable, id_each, 0, 0, chunk_ii, (VALUE)&arg);
02253     if (!NIL_P(arg.prev_elts))
02254         rb_funcall(arg.yielder, rb_intern("<<"), 1, rb_assoc_new(arg.prev_value, arg.prev_elts));
02255     return Qnil;
02256 }
02257 
02258 /*
02259  *  call-seq:
02260  *     enum.chunk {|elt| ... }                       -> an_enumerator
02261  *     enum.chunk(initial_state) {|elt, state| ... } -> an_enumerator
02262  *
02263  *  Creates an enumerator for each chunked elements.
02264  *  The consecutive elements which have same block value are chunked.
02265  *
02266  *  The result enumerator yields the block value and an array of chunked elements.
02267  *  So "each" method can be called as follows.
02268  *
02269  *    enum.chunk {|elt| key }.each {|key, ary| ... }
02270  *    enum.chunk(initial_state) {|elt, state| key }.each {|key, ary| ... }
02271  *
02272  *  For example, consecutive even numbers and odd numbers can be
02273  *  splitted as follows.
02274  *
02275  *    [3,1,4,1,5,9,2,6,5,3,5].chunk {|n|
02276  *      n.even?
02277  *    }.each {|even, ary|
02278  *      p [even, ary]
02279  *    }
02280  *    #=> [false, [3, 1]]
02281  *    #   [true, [4]]
02282  *    #   [false, [1, 5, 9]]
02283  *    #   [true, [2, 6]]
02284  *    #   [false, [5, 3, 5]]
02285  *
02286  *  This method is especially useful for sorted series of elements.
02287  *  The following example counts words for each initial letter.
02288  *
02289  *    open("/usr/share/dict/words", "r:iso-8859-1") {|f|
02290  *      f.chunk {|line| line.ord }.each {|ch, lines| p [ch.chr, lines.length] }
02291  *    }
02292  *    #=> ["\n", 1]
02293  *    #   ["A", 1327]
02294  *    #   ["B", 1372]
02295  *    #   ["C", 1507]
02296  *    #   ["D", 791]
02297  *    #   ...
02298  *
02299  *  The following key values has special meaning:
02300  *  - nil and :_separator specifies that the elements are dropped.
02301  *  - :_alone specifies that the element should be chunked as a singleton.
02302  *  Other symbols which begins an underscore are reserved.
02303  *
02304  *  nil and :_separator can be used to ignore some elements.
02305  *  For example, the sequence of hyphens in svn log can be eliminated as follows.
02306  *
02307  *    sep = "-"*72 + "\n"
02308  *    IO.popen("svn log README") {|f|
02309  *      f.chunk {|line|
02310  *        line != sep || nil
02311  *      }.each {|_, lines|
02312  *        pp lines
02313  *      }
02314  *    }
02315  *    #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
02316  *    #    "\n",
02317  *    #    "* README, README.ja: Update the portability section.\n",
02318  *    #    "\n"]
02319  *    #   ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
02320  *    #    "\n",
02321  *    #    "* README, README.ja: Add a note about default C flags.\n",
02322  *    #    "\n"]
02323  *    #   ...
02324  *
02325  *  paragraphs separated by empty lines can be parsed as follows.
02326  *
02327  *    File.foreach("README").chunk {|line|
02328  *      /\A\s*\z/ !~ line || nil
02329  *    }.each {|_, lines|
02330  *      pp lines
02331  *    }
02332  *
02333  *  :_alone can be used to pass through bunch of elements.
02334  *  For example, sort consecutive lines formed as Foo#bar and
02335  *  pass other lines, chunk can be used as follows.
02336  *
02337  *    pat = /\A[A-Z][A-Za-z0-9_]+\#/
02338  *    open(filename) {|f|
02339  *      f.chunk {|line| pat =~ line ? $& : :_alone }.each {|key, lines|
02340  *        if key != :_alone
02341  *          print lines.sort.join('')
02342  *        else
02343  *          print lines.join('')
02344  *        end
02345  *      }
02346  *    }
02347  *
02348  *  If the block needs to maintain state over multiple elements,
02349  *  _initial_state_ argument can be used.
02350  *  If non-nil value is given,
02351  *  it is duplicated for each "each" method invocation of the enumerator.
02352  *  The duplicated object is passed to 2nd argument of the block for "chunk" method.
02353  *
02354  */
02355 static VALUE
02356 enum_chunk(int argc, VALUE *argv, VALUE enumerable)
02357 {
02358     VALUE initial_state;
02359     VALUE enumerator;
02360 
02361     if(!rb_block_given_p())
02362         rb_raise(rb_eArgError, "no block given");
02363     rb_scan_args(argc, argv, "01", &initial_state);
02364 
02365     enumerator = rb_obj_alloc(rb_cEnumerator);
02366     rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
02367     rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
02368     rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
02369     rb_block_call(enumerator, rb_intern("initialize"), 0, 0, chunk_i, enumerator);
02370     return enumerator;
02371 }
02372 
02373 
02374 struct slicebefore_arg {
02375     VALUE sep_pred;
02376     VALUE sep_pat;
02377     VALUE state;
02378     VALUE prev_elts;
02379     VALUE yielder;
02380 };
02381 
02382 static VALUE
02383 slicebefore_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
02384 {
02385     struct slicebefore_arg *argp = (struct slicebefore_arg *)_argp;
02386     VALUE header_p;
02387 
02388     ENUM_WANT_SVALUE();
02389 
02390     if (!NIL_P(argp->sep_pat))
02391         header_p = rb_funcall(argp->sep_pat, id_eqq, 1, i);
02392     else if (NIL_P(argp->state))
02393         header_p = rb_funcall(argp->sep_pred, rb_intern("call"), 1, i);
02394     else
02395         header_p = rb_funcall(argp->sep_pred, rb_intern("call"), 2, i, argp->state);
02396     if (RTEST(header_p)) {
02397         if (!NIL_P(argp->prev_elts))
02398             rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
02399         argp->prev_elts = rb_ary_new3(1, i);
02400     }
02401     else {
02402         if (NIL_P(argp->prev_elts))
02403             argp->prev_elts = rb_ary_new3(1, i);
02404         else
02405             rb_ary_push(argp->prev_elts, i);
02406     }
02407 
02408     return Qnil;
02409 }
02410 
02411 static VALUE
02412 slicebefore_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
02413 {
02414     VALUE enumerable;
02415     struct slicebefore_arg arg;
02416 
02417     enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
02418     arg.sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
02419     arg.sep_pat = NIL_P(arg.sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
02420     arg.state = rb_ivar_get(enumerator, rb_intern("slicebefore_initial_state"));
02421     arg.prev_elts = Qnil;
02422     arg.yielder = yielder;
02423 
02424     if (!NIL_P(arg.state))
02425         arg.state = rb_obj_dup(arg.state);
02426 
02427     rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, (VALUE)&arg);
02428     if (!NIL_P(arg.prev_elts))
02429         rb_funcall(arg.yielder, rb_intern("<<"), 1, arg.prev_elts);
02430     return Qnil;
02431 }
02432 
02433 /*
02434  *  call-seq:
02435  *     enum.slice_before(pattern)                            -> an_enumerator
02436  *     enum.slice_before {|elt| bool }                       -> an_enumerator
02437  *     enum.slice_before(initial_state) {|elt, state| bool } -> an_enumerator
02438  *
02439  *  Creates an enumerator for each chunked elements.
02440  *  The beginnings of chunks are defined by _pattern_ and the block.
02441  *  If _pattern_ === _elt_ returns true or
02442  *  the block returns true for the element,
02443  *  the element is beginning of a chunk.
02444  *
02445  *  The === and block is called from the first element to the last element
02446  *  of _enum_.
02447  *  The result for the first element is ignored.
02448  *
02449  *  The result enumerator yields the chunked elements as an array for +each+
02450  *  method.
02451  *  +each+ method can be called as follows.
02452  *
02453  *    enum.slice_before(pattern).each {|ary| ... }
02454  *    enum.slice_before {|elt| bool }.each {|ary| ... }
02455  *    enum.slice_before(initial_state) {|elt, state| bool }.each {|ary| ... }
02456  *
02457  *  Other methods of Enumerator class and Enumerable module,
02458  *  such as map, etc., are also usable.
02459  *
02460  *  For example, iteration over ChangeLog entries can be implemented as
02461  *  follows.
02462  *
02463  *    # iterate over ChangeLog entries.
02464  *    open("ChangeLog") {|f|
02465  *      f.slice_before(/\A\S/).each {|e| pp e}
02466  *    }
02467  *
02468  *    # same as above.  block is used instead of pattern argument.
02469  *    open("ChangeLog") {|f|
02470  *      f.slice_before {|line| /\A\S/ === line }.each {|e| pp e}
02471  *    }
02472  *
02473  * "svn proplist -R" produces multiline output for each file.
02474  * They can be chunked as follows:
02475  *
02476  *    IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) {|f|
02477  *      f.lines.slice_before(/\AProp/).each {|lines| p lines }
02478  *    }
02479  *    #=> ["Properties on '.':\n", "  svn:ignore\n", "  svk:merge\n"]
02480  *    #   ["Properties on 'goruby.c':\n", "  svn:eol-style\n"]
02481  *    #   ["Properties on 'complex.c':\n", "  svn:mime-type\n", "  svn:eol-style\n"]
02482  *    #   ["Properties on 'regparse.c':\n", "  svn:eol-style\n"]
02483  *    #   ...
02484  *
02485  *  If the block needs to maintain state over multiple elements,
02486  *  local variables can be used.
02487  *  For example, three or more consecutive increasing numbers can be squashed
02488  *  as follows:
02489  *
02490  *    a = [0,2,3,4,6,7,9]
02491  *    prev = a[0]
02492  *    p a.slice_before {|e|
02493  *      prev, prev2 = e, prev
02494  *      prev2 + 1 != e
02495  *    }.map {|es|
02496  *      es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
02497  *    }.join(",")
02498  *    #=> "0,2-4,6,7,9"
02499  *
02500  *  However local variables are not appropriate to maintain state
02501  *  if the result enumerator is used twice or more.
02502  *  In such case, the last state of the 1st +each+ is used in 2nd +each+.
02503  *  _initial_state_ argument can be used to avoid this problem.
02504  *  If non-nil value is given as _initial_state_,
02505  *  it is duplicated for each "each" method invocation of the enumerator.
02506  *  The duplicated object is passed to 2nd argument of the block for
02507  *  +slice_before+ method.
02508  *
02509  *    # word wrapping.
02510  *    # this assumes all characters have same width.
02511  *    def wordwrap(words, maxwidth)
02512  *      # if cols is a local variable, 2nd "each" may start with non-zero cols.
02513  *      words.slice_before(cols: 0) {|w, h|
02514  *        h[:cols] += 1 if h[:cols] != 0
02515  *        h[:cols] += w.length
02516  *        if maxwidth < h[:cols]
02517  *          h[:cols] = w.length
02518  *          true
02519  *        else
02520  *          false
02521  *        end
02522  *      }
02523  *    end
02524  *    text = (1..20).to_a.join(" ")
02525  *    enum = wordwrap(text.split(/\s+/), 10)
02526  *    puts "-"*10
02527  *    enum.each {|ws| puts ws.join(" ") }
02528  *    puts "-"*10
02529  *    #=> ----------
02530  *    #   1 2 3 4 5
02531  *    #   6 7 8 9 10
02532  *    #   11 12 13
02533  *    #   14 15 16
02534  *    #   17 18 19
02535  *    #   20
02536  *    #   ----------
02537  *
02538  * mbox contains series of mails which start with Unix From line.
02539  * So each mail can be extracted by slice before Unix From line.
02540  *
02541  *    # parse mbox
02542  *    open("mbox") {|f|
02543  *      f.slice_before {|line|
02544  *        line.start_with? "From "
02545  *      }.each {|mail|
02546  *        unix_from = mail.shift
02547  *        i = mail.index("\n")
02548  *        header = mail[0...i]
02549  *        body = mail[(i+1)..-1]
02550  *        body.pop if body.last == "\n"
02551  *        fields = header.slice_before {|line| !" \t".include?(line[0]) }.to_a
02552  *        p unix_from
02553  *        pp fields
02554  *        pp body
02555  *      }
02556  *    }
02557  *
02558  *    # split mails in mbox (slice before Unix From line after an empty line)
02559  *    open("mbox") {|f|
02560  *      f.slice_before(emp: true) {|line,h|
02561  *        prevemp = h[:emp]
02562  *        h[:emp] = line == "\n"
02563  *        prevemp && line.start_with?("From ")
02564  *      }.each {|mail|
02565  *        mail.pop if mail.last == "\n"
02566  *        pp mail
02567  *      }
02568  *    }
02569  *
02570  */
02571 static VALUE
02572 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
02573 {
02574     VALUE enumerator;
02575 
02576     if (rb_block_given_p()) {
02577         VALUE initial_state;
02578         rb_scan_args(argc, argv, "01", &initial_state);
02579         enumerator = rb_obj_alloc(rb_cEnumerator);
02580         rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
02581         rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
02582     }
02583     else {
02584         VALUE sep_pat;
02585         rb_scan_args(argc, argv, "1", &sep_pat);
02586         enumerator = rb_obj_alloc(rb_cEnumerator);
02587         rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
02588     }
02589     rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
02590     rb_block_call(enumerator, rb_intern("initialize"), 0, 0, slicebefore_i, enumerator);
02591     return enumerator;
02592 }
02593 
02594 /*
02595  *  The <code>Enumerable</code> mixin provides collection classes with
02596  *  several traversal and searching methods, and with the ability to
02597  *  sort. The class must provide a method <code>each</code>, which
02598  *  yields successive members of the collection. If
02599  *  <code>Enumerable#max</code>, <code>#min</code>, or
02600  *  <code>#sort</code> is used, the objects in the collection must also
02601  *  implement a meaningful <code><=></code> operator, as these methods
02602  *  rely on an ordering between members of the collection.
02603  */
02604 
02605 void
02606 Init_Enumerable(void)
02607 {
02608 #undef rb_intern
02609 #define rb_intern(str) rb_intern_const(str)
02610 
02611     rb_mEnumerable = rb_define_module("Enumerable");
02612 
02613     rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
02614     rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
02615 
02616     rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
02617     rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
02618     rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
02619     rb_define_method(rb_mEnumerable, "count", enum_count, -1);
02620     rb_define_method(rb_mEnumerable, "find", enum_find, -1);
02621     rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
02622     rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
02623     rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
02624     rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
02625     rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
02626     rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
02627     rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
02628     rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
02629     rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
02630     rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
02631     rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
02632     rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
02633     rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
02634     rb_define_method(rb_mEnumerable, "first", enum_first, -1);
02635     rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
02636     rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
02637     rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
02638     rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
02639     rb_define_method(rb_mEnumerable, "min", enum_min, 0);
02640     rb_define_method(rb_mEnumerable, "max", enum_max, 0);
02641     rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
02642     rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
02643     rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
02644     rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
02645     rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
02646     rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
02647     rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
02648     rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
02649     rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
02650     rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
02651     rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
02652     rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
02653     rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
02654     rb_define_method(rb_mEnumerable, "take", enum_take, 1);
02655     rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
02656     rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
02657     rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
02658     rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
02659     rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
02660     rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
02661 
02662     id_eqq  = rb_intern("===");
02663     id_each = rb_intern("each");
02664     id_cmp  = rb_intern("<=>");
02665     id_next = rb_intern("next");
02666     id_size = rb_intern("size");
02667 }
02668 
02669 

Generated on Wed Aug 10 09:16:55 2011 for Ruby by  doxygen 1.4.7