14#include "internal/compar.h"
15#include "internal/enum.h"
16#include "internal/hash.h"
17#include "internal/imemo.h"
18#include "internal/numeric.h"
19#include "internal/object.h"
20#include "internal/proc.h"
21#include "internal/rational.h"
22#include "internal/re.h"
24#include "ruby_assert.h"
31static ID id__separator;
32static ID id_chunk_categorize;
33static ID id_chunk_enumerable;
34static ID id_sliceafter_enum;
35static ID id_sliceafter_pat;
36static ID id_sliceafter_pred;
37static ID id_slicebefore_enumerable;
38static ID id_slicebefore_sep_pat;
39static ID id_slicebefore_sep_pred;
40static ID id_slicewhen_enum;
41static ID id_slicewhen_inverted;
42static ID id_slicewhen_pred;
48#define id_lshift idLTLT
55 if (argc == 0)
return Qnil;
56 if (argc == 1)
return argv[0];
60#define ENUM_WANT_SVALUE() do { \
61 i = rb_enum_values_pack(argc, argv); \
65enum_yield(
int argc, VALUE ary)
68 return rb_yield_force_blockarg(ary);
75enum_yield_array(VALUE ary)
80 return rb_yield_force_blockarg(ary);
89 struct MEMO *memo = MEMO_CAST(args);
101 struct MEMO *memo = MEMO_CAST(args);
102 VALUE converted_element, match;
107 match =
NIL_P(converted_element) ?
Qfalse : rb_reg_match_p(memo->v1, i, 0);
108 if (match == memo->u3.value) {
117 struct MEMO *memo = MEMO_CAST(args);
127enum_grep0(VALUE obj, VALUE pat, VALUE test)
130 struct MEMO *memo = MEMO_NEW(pat, ary, test);
131 rb_block_call_func_t fn;
173enum_grep(VALUE obj, VALUE pat)
175 return enum_grep0(obj, pat,
Qtrue);
205enum_grep_v(VALUE obj, VALUE pat)
207 return enum_grep0(obj, pat,
Qfalse);
210#define COUNT_BIGNUM IMEMO_FL_USER0
211#define MEMO_V3_SET(m, v) RB_OBJ_WRITE((m), &(m)->u3.value, (v))
214imemo_count_up(
struct MEMO *memo)
216 if (memo->flags & COUNT_BIGNUM) {
217 MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
219 else if (++memo->u3.cnt == 0) {
221 unsigned long buf[2] = {0, 1};
223 memo->flags |= COUNT_BIGNUM;
228imemo_count_value(
struct MEMO *memo)
230 if (memo->flags & COUNT_BIGNUM) {
231 return memo->u3.value;
241 struct MEMO *memo = MEMO_CAST(memop);
245 if (rb_equal(i, memo->v1)) {
246 imemo_count_up(memo);
254 struct MEMO *memo = MEMO_CAST(memop);
257 imemo_count_up(memo);
265 struct MEMO *memo = MEMO_CAST(memop);
267 imemo_count_up(memo);
298enum_count(
int argc, VALUE *argv, VALUE obj)
315 rb_warn(
"given block not used");
320 memo = MEMO_NEW(item, 0, 0);
322 return imemo_count_value(memo);
330 if (
RTEST(enum_yield(argc, i))) {
331 struct MEMO *memo = MEMO_CAST(memop);
332 MEMO_V1_SET(memo, i);
361enum_find(
int argc, VALUE *argv, VALUE obj)
368 memo = MEMO_NEW(
Qundef, 0, 0);
373 if (!
NIL_P(if_none)) {
382 struct MEMO *memo = MEMO_CAST(memop);
386 if (rb_equal(i, memo->v2)) {
387 MEMO_V1_SET(memo, imemo_count_value(memo));
390 imemo_count_up(memo);
397 struct MEMO *memo = MEMO_CAST(memop);
400 MEMO_V1_SET(memo, imemo_count_value(memo));
403 imemo_count_up(memo);
432enum_find_index(
int argc, VALUE *argv, VALUE obj)
435 VALUE condition_value =
Qnil;
440 func = find_index_iter_i;
445 rb_warn(
"given block not used");
450 memo = MEMO_NEW(
Qnil, condition_value, 0);
460 if (
RTEST(enum_yield(argc, i))) {
467enum_size(VALUE
self, VALUE args, VALUE eobj)
469 return rb_check_funcall_default(
self, id_size, 0, 0,
Qnil);
473limit_by_enum_size(VALUE obj,
long n)
479 return ((
unsigned long)n > limit) ? (long)limit : n;
483enum_size_over_p(VALUE obj,
long n)
487 return ((
unsigned long)n >
FIX2ULONG(size));
509enum_find_all(VALUE obj)
550enum_filter_map(VALUE obj)
568 if (!
RTEST(enum_yield(argc, i))) {
593enum_reject(VALUE obj)
638enum_collect(VALUE obj)
641 int min_argc, max_argc;
646 min_argc = rb_block_min_max_arity(&max_argc);
647 rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
689enum_flat_map(VALUE obj)
712enum_to_a(
int argc, VALUE *argv, VALUE obj)
722enum_hashify_into(VALUE obj,
int argc,
const VALUE *argv,
rb_block_call_func *iter, VALUE hash)
731 return enum_hashify_into(obj, argc, argv, iter,
rb_hash_new());
738 return rb_hash_set_pair(hash, i);
769enum_to_h(
int argc, VALUE *argv, VALUE obj)
772 return enum_hashify(obj, argc, argv, iter);
778 struct MEMO *memo = MEMO_CAST(p);
783 MEMO_V1_SET(memo, i);
794 struct MEMO *memo = MEMO_CAST(p);
800 MEMO_V1_SET(memo, i);
802 else if (
SYMBOL_P(name = memo->u3.value)) {
803 const ID mid =
SYM2ID(name);
810 MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
816ary_inject_op(VALUE ary, VALUE init, VALUE op)
851 else if (RB_BIGNUM_TYPE_P(e))
1007enum_inject(
int argc, VALUE *argv, VALUE obj)
1023 op =
id ?
ID2SYM(
id) : init;
1037 if (iter == inject_op_i &&
1041 return ary_inject_op(obj, init, op);
1044 memo = MEMO_NEW(init,
Qnil, op);
1053 struct MEMO *memo = MEMO_CAST(arys);
1057 if (
RTEST(enum_yield(argc, i))) {
1096enum_partition(VALUE obj)
1103 rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
1116 group = enum_yield(argc, i);
1151enum_group_by(VALUE obj)
1155 return enum_hashify(obj, 0, 0, group_by_i);
1159tally_up(st_data_t *group, st_data_t *value, st_data_t arg,
int existing)
1161 VALUE tally = (
VALUE)*value;
1162 VALUE hash = (
VALUE)arg;
1167 tally +=
INT2FIX(1) & ~FIXNUM_FLAG;
1174 *value = (st_data_t)tally;
1180rb_enum_tally_up(VALUE hash, VALUE group)
1182 rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash);
1190 rb_enum_tally_up(hash, i);
1223enum_tally(
int argc, VALUE *argv, VALUE obj)
1234 return enum_hashify_into(obj, 0, 0, tally_i, hash);
1241 struct MEMO *memo = MEMO_CAST(params);
1244 MEMO_V1_SET(memo, i);
1250static VALUE enum_take(VALUE obj, VALUE n);
1278enum_first(
int argc, VALUE *argv, VALUE obj)
1283 return enum_take(obj, argv[0]);
1286 memo = MEMO_NEW(
Qnil, 0, 0);
1330#define SORT_BY_BUFSIZE 16
1341 VALUE ary = data->ary;
1346 v = enum_yield(argc, i);
1348 if (
RBASIC(ary)->klass) {
1349 rb_raise(rb_eRuntimeError,
"sort_by reentered");
1351 if (
RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
1352 rb_raise(rb_eRuntimeError,
"sort_by reentered");
1358 if (data->n == SORT_BY_BUFSIZE) {
1366sort_by_cmp(
const void *ap,
const void *bp,
void *data)
1371 VALUE ary = (
VALUE)data;
1373 if (
RBASIC(ary)->klass) {
1374 rb_raise(rb_eRuntimeError,
"sort_by reentered");
1380 return OPTIMIZED_CMP(a, b, cmp_opt);
1466enum_sort_by(VALUE obj)
1481 RBASIC_CLEAR_CLASS(ary);
1484 memo = MEMO_NEW(0, 0, 0);
1499 sort_by_cmp, (
void *)ary));
1501 if (
RBASIC(ary)->klass) {
1502 rb_raise(rb_eRuntimeError,
"sort_by reentered");
1513#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
1515#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
1517#define DEFINE_ENUMFUNCS(name) \
1518static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
1521name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1523 return enum_##name##_func(rb_enum_values_pack(argc, argv), MEMO_CAST(memo)); \
1527name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1529 return enum_##name##_func(rb_yield_values2(argc, argv), MEMO_CAST(memo)); \
1533name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1535 ENUM_WANT_SVALUE(); \
1536 return enum_##name##_func(rb_funcallv(MEMO_CAST(memo)->v2, id_eqq, 1, &i), MEMO_CAST(memo)); \
1540enum_##name##_func(VALUE result, struct MEMO *memo)
1542#define WARN_UNUSED_BLOCK(argc) do { \
1543 if ((argc) > 0 && rb_block_given_p()) { \
1544 rb_warn("given block not used"); \
1548DEFINE_ENUMFUNCS(all)
1550 if (!
RTEST(result)) {
1551 MEMO_V1_SET(memo,
Qfalse);
1601enum_all(
int argc, VALUE *argv, VALUE obj)
1603 struct MEMO *memo = MEMO_ENUM_NEW(
Qtrue);
1604 WARN_UNUSED_BLOCK(argc);
1605 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1609DEFINE_ENUMFUNCS(any)
1611 if (
RTEST(result)) {
1612 MEMO_V1_SET(memo,
Qtrue);
1661enum_any(
int argc, VALUE *argv, VALUE obj)
1664 WARN_UNUSED_BLOCK(argc);
1665 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1669DEFINE_ENUMFUNCS(one)
1671 if (
RTEST(result)) {
1672 if (memo->v1 ==
Qundef) {
1673 MEMO_V1_SET(memo,
Qtrue);
1675 else if (memo->v1 ==
Qtrue) {
1676 MEMO_V1_SET(memo,
Qfalse);
1689 int (*cmpfunc)(
const void *,
const void *,
void *);
1695cmpint_reenter_check(
struct nmin_data *data, VALUE val)
1697 if (
RBASIC(data->buf)->klass) {
1698 rb_raise(rb_eRuntimeError,
"%s%s reentered",
1699 data->rev ?
"max" :
"min",
1700 data->by ?
"_by" :
"");
1706nmin_cmp(
const void *ap,
const void *bp,
void *_data)
1710 VALUE a = *(
const VALUE *)ap, b = *(
const VALUE *)bp;
1711#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
1712 return OPTIMIZED_CMP(a, b, cmp_opt);
1717nmin_block_cmp(
const void *ap,
const void *bp,
void *_data)
1720 VALUE a = *(
const VALUE *)ap, b = *(
const VALUE *)bp;
1722 cmpint_reenter_check(data, cmp);
1739 if (data->curlen <= data->n)
1744 eltsize = data->by ? 2 : 1;
1745 numelts = data->curlen;
1750#define GETPTR(i) (beg+(i)*eltsize)
1752#define SWAP(i, j) do { \
1754 memcpy(tmp, GETPTR(i), sizeof(VALUE)*eltsize); \
1755 memcpy(GETPTR(i), GETPTR(j), sizeof(VALUE)*eltsize); \
1756 memcpy(GETPTR(j), tmp, sizeof(VALUE)*eltsize); \
1760 long pivot_index = left + (right-left)/2;
1761 long num_pivots = 1;
1763 SWAP(pivot_index, right);
1764 pivot_index = right;
1768 while (i <= right-num_pivots) {
1769 int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
1773 SWAP(i, right-num_pivots);
1778 SWAP(i, store_index);
1784 for (i = right; right-num_pivots < i; i--) {
1791 if (store_index <= n && n <= store_index+num_pivots)
1794 if (n < store_index) {
1795 right = store_index-1;
1798 left = store_index+num_pivots;
1804 data->limit =
RARRAY_AREF(data->buf, store_index*eltsize);
1805 data->curlen = data->n;
1818 cmpv = enum_yield(argc, i);
1822 if (data->limit !=
Qundef) {
1823 int c = data->cmpfunc(&cmpv, &data->limit, data);
1836 if (data->curlen == data->bufmax) {
1844rb_nmin_run(VALUE obj, VALUE num,
int by,
int rev,
int ary)
1851 rb_raise(rb_eArgError,
"negative size (%ld)", data.n);
1854 if (LONG_MAX/4/(by ? 2 : 1) < data.n)
1855 rb_raise(rb_eArgError,
"too big size");
1856 data.bufmax = data.n * 4;
1860 data.cmpfunc = by ? nmin_cmp :
1870 nmin_i(obj, (VALUE)&data, 1, args,
Qundef);
1884 data.cmpfunc, (
void *)&data);
1894 data.cmpfunc, (
void *)&data);
1949enum_one(
int argc, VALUE *argv, VALUE obj)
1954 WARN_UNUSED_BLOCK(argc);
1955 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1961DEFINE_ENUMFUNCS(none)
1963 if (
RTEST(result)) {
1964 MEMO_V1_SET(memo,
Qfalse);
2011enum_none(
int argc, VALUE *argv, VALUE obj)
2013 struct MEMO *memo = MEMO_ENUM_NEW(
Qtrue);
2015 WARN_UNUSED_BLOCK(argc);
2016 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
2028 struct min_t *memo = MEMO_FOR(
struct min_t, args);
2032 if (memo->min ==
Qundef) {
2036 if (OPTIMIZED_CMP(i, memo->min, memo->cmp_opt) < 0) {
2047 struct min_t *memo = MEMO_FOR(
struct min_t, args);
2051 if (memo->min ==
Qundef) {
2122enum_min(
int argc, VALUE *argv, VALUE obj)
2125 struct min_t *m = NEW_CMP_OPT_MEMO(
struct min_t, memo);
2130 return rb_nmin_run(obj, num, 0, 0, 0);
2133 m->cmp_opt.opt_methods = 0;
2134 m->cmp_opt.opt_inited = 0;
2154 struct max_t *memo = MEMO_FOR(
struct max_t, args);
2158 if (memo->max ==
Qundef) {
2162 if (OPTIMIZED_CMP(i, memo->max, memo->cmp_opt) > 0) {
2172 struct max_t *memo = MEMO_FOR(
struct max_t, args);
2177 if (memo->max ==
Qundef) {
2247enum_max(
int argc, VALUE *argv, VALUE obj)
2250 struct max_t *m = NEW_CMP_OPT_MEMO(
struct max_t, memo);
2255 return rb_nmin_run(obj, num, 0, 1, 0);
2258 m->cmp_opt.opt_methods = 0;
2259 m->cmp_opt.opt_inited = 0;
2279minmax_i_update(VALUE i, VALUE j,
struct minmax_t *memo)
2283 if (memo->min ==
Qundef) {
2288 n = OPTIMIZED_CMP(i, memo->min, memo->cmp_opt);
2292 n = OPTIMIZED_CMP(j, memo->max, memo->cmp_opt);
2308 if (memo->last ==
Qundef) {
2315 n = OPTIMIZED_CMP(j, i, memo->cmp_opt);
2325 minmax_i_update(i, j, memo);
2331minmax_ii_update(VALUE i, VALUE j,
struct minmax_t *memo)
2335 if (memo->min ==
Qundef) {
2360 if (memo->last ==
Qundef) {
2377 minmax_ii_update(i, j, memo);
2414enum_minmax(VALUE obj)
2421 m->cmp_opt.opt_methods = 0;
2422 m->cmp_opt.opt_inited = 0;
2426 minmax_ii_update(m->last, m->last, m);
2431 minmax_i_update(m->last, m->last, m);
2443 struct MEMO *memo = MEMO_CAST(args);
2448 v = enum_yield(argc, i);
2449 if (memo->v1 ==
Qundef) {
2450 MEMO_V1_SET(memo, v);
2451 MEMO_V2_SET(memo, i);
2453 else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) < 0) {
2454 MEMO_V1_SET(memo, v);
2455 MEMO_V2_SET(memo, i);
2497enum_min_by(
int argc, VALUE *argv, VALUE obj)
2506 if (argc && !
NIL_P(num = argv[0]))
2507 return rb_nmin_run(obj, num, 1, 0, 0);
2518 struct MEMO *memo = MEMO_CAST(args);
2523 v = enum_yield(argc, i);
2524 if (memo->v1 ==
Qundef) {
2525 MEMO_V1_SET(memo, v);
2526 MEMO_V2_SET(memo, i);
2528 else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) > 0) {
2529 MEMO_V1_SET(memo, v);
2530 MEMO_V2_SET(memo, i);
2572enum_max_by(
int argc, VALUE *argv, VALUE obj)
2581 if (argc && !
NIL_P(num = argv[0]))
2582 return rb_nmin_run(obj, num, 1, 1, 0);
2599minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2,
struct minmax_by_t *memo)
2603 if (memo->min_bv ==
Qundef) {
2610 if (OPTIMIZED_CMP(v1, memo->min_bv, cmp_opt) < 0) {
2614 if (OPTIMIZED_CMP(v2, memo->max_bv, cmp_opt) > 0) {
2631 vi = enum_yield(argc, i);
2633 if (memo->last_bv ==
Qundef) {
2642 n = OPTIMIZED_CMP(vj, vi, cmp_opt);
2657 minmax_by_i_update(vi, vj, i, j, memo);
2686enum_minmax_by(VALUE obj)
2700 if (m->last_bv !=
Qundef)
2701 minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
2709 struct MEMO *memo = MEMO_CAST(args);
2712 MEMO_V2_SET(memo,
Qtrue);
2738enum_member(VALUE obj, VALUE val)
2740 struct MEMO *memo = MEMO_NEW(val,
Qfalse, 0);
2749 struct MEMO *m = MEMO_CAST(memo);
2750 VALUE n = imemo_count_value(m);
2784enum_each_with_index(
int argc, VALUE *argv, VALUE obj)
2790 memo = MEMO_NEW(0, 0, 0);
2791 rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
2823enum_reverse_each(
int argc, VALUE *argv, VALUE obj)
2830 ary = enum_to_a(argc, argv, obj);
2850 enum_yield(argc, i);
2893enum_each_entry(
int argc, VALUE *argv, VALUE obj)
2901add_int(VALUE x,
long n)
2909div_int(VALUE x,
long n)
2916#define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) < 0)
2921 struct MEMO *memo = MEMO_CAST(m);
2922 VALUE ary = memo->v1;
2924 long size = memo->u3.cnt;
2944enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
2950 if (slice_size <= 0)
rb_raise(rb_eArgError,
"invalid slice size");
2952 size = enum_size(obj, 0, 0);
2958 n = add_int(size, slice_size-1);
2959 return div_int(n, slice_size);
2983enum_each_slice(VALUE obj, VALUE n)
2990 if (size <= 0)
rb_raise(rb_eArgError,
"invalid slice size");
2992 size = limit_by_enum_size(obj, size);
2994 arity = rb_block_arity();
2995 memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
2996 rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
3006 struct MEMO *memo = MEMO_CAST(args);
3007 VALUE ary = memo->v1;
3009 long size = memo->u3.cnt;
3026enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
3032 if (cons_size <= 0)
rb_raise(rb_eArgError,
"invalid size");
3034 size = enum_size(obj, 0, 0);
3037 n = add_int(size, 1 - cons_size);
3038 return (OPTIMIZED_CMP(n, zero, cmp_opt) == -1) ? zero : n;
3062enum_each_cons(VALUE obj, VALUE n)
3068 if (size <= 0)
rb_raise(rb_eArgError,
"invalid size");
3070 arity = rb_block_arity();
3071 if (enum_size_over_p(obj, size))
return obj;
3072 memo = MEMO_NEW(
rb_ary_new2(size), dont_recycle_block_arg(arity), size);
3073 rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
3101enum_each_with_object(VALUE obj, VALUE memo)
3105 rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
3113 struct MEMO *memo = (
struct MEMO *)memoval;
3114 VALUE result = memo->v1;
3115 VALUE args = memo->v2;
3116 long n = memo->u3.cnt++;
3132 if (
NIL_P(result)) {
3133 enum_yield_array(tmp);
3147 VALUE *v = (VALUE *)w;
3152call_stop(VALUE w, VALUE
_)
3154 VALUE *v = (VALUE *)w;
3161 struct MEMO *memo = (
struct MEMO *)memoval;
3162 VALUE result = memo->v1;
3163 VALUE args = memo->v2;
3185 if (
NIL_P(result)) {
3186 enum_yield_array(tmp);
3265enum_zip(
int argc, VALUE *argv, VALUE obj)
3270 VALUE result =
Qnil;
3275 for (i=0; i<argc; i++) {
3284 static const VALUE sym_each = STATIC_ID2SYM(id_each);
3286 for (i=0; i<argc; i++) {
3288 rb_raise(rb_eTypeError,
"wrong argument type %"PRIsVALUE
" (must respond to :each)",
3289 rb_obj_class(argv[i]));
3291 argv[i] =
rb_funcallv(argv[i], conv, 1, &sym_each);
3299 memo = MEMO_NEW(result, args, 0);
3300 rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
3308 struct MEMO *memo = MEMO_CAST(args);
3330enum_take(VALUE obj, VALUE n)
3337 rb_raise(rb_eArgError,
"attempt to take negative size");
3342 memo = MEMO_NEW(result, 0, len);
3376enum_take_while(VALUE obj)
3389 struct MEMO *memo = MEMO_CAST(args);
3390 if (memo->u3.cnt == 0) {
3419enum_drop(VALUE obj, VALUE n)
3426 rb_raise(rb_eArgError,
"attempt to drop negative size");
3430 memo = MEMO_NEW(result, 0, len);
3439 struct MEMO *memo = MEMO_CAST(args);
3442 if (!memo->u3.state && !
RTEST(enum_yield(argc, i))) {
3443 memo->u3.state = TRUE;
3445 if (memo->u3.state) {
3471enum_drop_while(VALUE obj)
3478 memo = MEMO_NEW(result, 0, FALSE);
3479 rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
3489 enum_yield(argc, i);
3494enum_cycle_size(VALUE
self, VALUE args, VALUE eobj)
3505 size = enum_size(
self, args, 0);
3506 if (
NIL_P(size) || FIXNUM_ZERO_P(size))
return size;
3509 if (mul <= 0)
return INT2FIX(0);
3542enum_cycle(
int argc, VALUE *argv, VALUE obj)
3551 if (!argc ||
NIL_P(nv = argv[0])) {
3556 if (n <= 0)
return Qnil;
3559 RBASIC_CLEAR_CLASS(ary);
3562 if (len == 0)
return Qnil;
3563 while (n < 0 || 0 < --n) {
3564 for (i=0; i<len; i++) {
3583 VALUE alone =
ID2SYM(id__alone);
3584 VALUE separator =
ID2SYM(id__separator);
3588 v =
rb_funcallv(argp->categorize, id_call, 1, &i);
3591 if (!
NIL_P(argp->prev_value)) {
3594 argp->prev_value = argp->prev_elts =
Qnil;
3599 else if (
NIL_P(v) || v == separator) {
3600 if (!
NIL_P(argp->prev_value)) {
3603 argp->prev_value = argp->prev_elts =
Qnil;
3607 rb_raise(rb_eRuntimeError,
"symbols beginning with an underscore are reserved");
3610 if (
NIL_P(argp->prev_value)) {
3611 argp->prev_value = v;
3615 if (rb_equal(argp->prev_value, v)) {
3621 argp->prev_value = v;
3638 memo->prev_value =
Qnil;
3639 memo->prev_elts =
Qnil;
3644 if (!
NIL_P(memo->prev_elts)) {
3756enum_chunk(VALUE enumerable)
3785 if (!
NIL_P(argp->sep_pat))
3786 header_p =
rb_funcallv(argp->sep_pat, id_eqq, 1, &i);
3788 header_p =
rb_funcallv(argp->sep_pred, id_call, 1, &i);
3789 if (
RTEST(header_p)) {
3790 if (!
NIL_P(argp->prev_elts))
3791 rb_funcallv(argp->yielder, id_lshift, 1, &argp->prev_elts);
3795 if (
NIL_P(argp->prev_elts))
3814 memo->prev_elts =
Qnil;
3817 rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
3819 if (!
NIL_P(memo->prev_elts))
3820 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3985enum_slice_before(
int argc, VALUE *argv, VALUE enumerable)
3991 rb_error_arity(argc, 0, 0);
4017#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct sliceafter_arg, _memo)))
4024 if (
NIL_P(memo->prev_elts)) {
4031 if (
NIL_P(memo->pred)) {
4041 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4043 memo->prev_elts =
Qnil;
4060 memo->prev_elts =
Qnil;
4063 rb_block_call(enumerable, id_each, 0, 0, sliceafter_ii, arg);
4065 if (!
NIL_P(memo->prev_elts))
4066 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4122enum_slice_after(
int argc, VALUE *argv, VALUE enumerable)
4129 rb_raise(rb_eArgError,
"both pattern and block are given");
4156#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct slicewhen_arg, _memo)))
4163 if (memo->prev_elt ==
Qundef) {
4170 args[0] = memo->prev_elt;
4179 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4205 memo->prev_elts =
Qnil;
4209 rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg);
4211 if (!
NIL_P(memo->prev_elts))
4212 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4237enum_slice_when(VALUE enumerable)
4278enum_chunk_while(VALUE enumerable)
4306 memo->v = rb_fix_plus(
LONG2FIX(memo->n), memo->v);
4309 switch (
TYPE(memo->r)) {
4310 case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v);
break;
4340 memo->r = rb_rational_plus(memo->r, i);
4366 memo->float_value = 0;
4367 sum_iter_some_value(i, memo);
4376 else if (! isfinite(x)) {
4377 if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
4385 else if (isinf(f)) {
4392 if (fabs(f) >= fabs(x)) {
4407 assert(memo != NULL);
4408 if (memo->block_given) {
4412 if (memo->float_value) {
4413 sum_iter_Kahan_Babuska(i, memo);
4415 else switch (
TYPE(memo->v)) {
4416 default: sum_iter_some_value(i, memo);
return;
4417 case T_FLOAT: sum_iter_Kahan_Babuska(i, memo);
return;
4422 case T_FIXNUM: sum_iter_fixnum(i, memo);
return;
4423 case T_BIGNUM: sum_iter_bignum(i, memo);
return;
4424 case T_RATIONAL: sum_iter_rational(i, memo);
return;
4426 sum_iter_normalize_memo(memo);
4429 memo->float_value = 1;
4430 sum_iter_Kahan_Babuska(i, memo);
4433 sum_iter_normalize_memo(memo);
4434 sum_iter_some_value(i, memo);
4449hash_sum_i(VALUE key, VALUE value, VALUE arg)
4459 assert(memo != NULL);
4465int_range_sum(VALUE beg, VALUE end,
int excl, VALUE init)
4474 if (rb_int_ge(end, beg)) {
4476 a = rb_int_plus(rb_int_minus(end, beg),
LONG2FIX(1));
4477 a = rb_int_mul(a, rb_int_plus(end, beg));
4479 return rb_int_plus(init, a);
4517enum_sum(
int argc, VALUE* argv, VALUE obj)
4538 if (!memo.block_given && !memo.float_value &&
4539 (
FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
4540 (
FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
4541 return int_range_sum(beg, end, excl, memo.v);
4547 hash_sum(obj, &memo);
4549 rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
4551 if (memo.float_value) {
4552 return DBL2NUM(memo.f + memo.c);
4556 memo.v = rb_fix_plus(
LONG2FIX(memo.n), memo.v);
4558 memo.v = rb_rational_plus(memo.r, memo.v);
4568 rb_hash_add_new_element(hash, i, i);
4610 ret = rb_hash_values(hash);
4638enum_compact(VALUE obj)
4803Init_Enumerable(
void)
4875 id_slicebefore_enumerable =
rb_intern_const(
"slicebefore_enumerable");
VALUE rb_define_module(const char *name)
Defines a top-level module.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define TYPE(_)
Old name of rb_type.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
#define T_HASH
Old name of RUBY_T_HASH.
#define NUM2DBL
Old name of rb_num2dbl.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define T_UNDEF
Old name of RUBY_T_UNDEF.
#define Qtrue
Old name of RUBY_Qtrue.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define T_REGEXP
Old name of RUBY_T_REGEXP.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
void rb_iter_break(void)
Breaks from a block.
VALUE rb_eStopIteration
StopIteration exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid)
Converts an object into another type.
VALUE rb_cArray
Array class.
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_cEnumerator
Enumerator class.
VALUE rb_cInteger
Module class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it only takes public methods into account.
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_tmp_new(long capa)
Allocates a "temporary" array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
VALUE rb_big_minus(VALUE x, VALUE y)
Performs subtraction of the passed two objects.
VALUE rb_big_plus(VALUE x, VALUE y)
Performs addition of the passed two objects.
VALUE rb_big_unpack(unsigned long *buf, long num_longs)
Constructs a (possibly very big) bignum from a series of integers.
double rb_big2dbl(VALUE x)
Converts a bignum into C's double.
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Canonicalises the passed val, which is the return value of a <=> b, into C's {-1, 0,...
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Basically identical to rb_ary_new_form_values(), except it returns something different when argc < 2.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
#define rb_check_frozen
Just another name of rb_check_frozen.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_hash_foreach(VALUE hash, int(*func)(VALUE key, VALUE val, VALUE arg), VALUE arg)
Iterates over a hash.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
VALUE rb_hash_clear(VALUE hash)
Swipes everything out of the passed hash table.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2)
Identical to rb_funcallv(), except it additionally passes a function as a block.
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define RARRAY_LEN
Just another name of rb_array_len.
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
#define RARRAY_AREF(a, i)
#define RBASIC(obj)
Convenient casting macro.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.