summaryrefslogtreecommitdiff
path: root/enum.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-01-08 09:50:01 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-01-08 09:50:01 +0000
commit929faf7906a2f2ca7dbf5eda5670e666edddfa88 (patch)
tree86ca0193cb62d7791cfa6301c06204f3b723ac7e /enum.c
parent1309c103322fe0662365decea9fcb9e58d026c4a (diff)
* enum.c (enum_zip): honor length of the receiver, not the
shortest length. [ruby-core:14738] * enum.c (enum_zip): returns array not enumerator for no block form. [ruby-core:14738] * enumerator.c (next_ii): do not ignore multiple values yielded. * array.c (rb_ary_zip): faster version without creating generators. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14952 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r--enum.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/enum.c b/enum.c
index df3f103cab..faa688e11f 100644
--- a/enum.c
+++ b/enum.c
@@ -1347,6 +1347,18 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
static VALUE
+call_next(VALUE *v)
+{
+ return v[0] = rb_funcall(v[1], id_next, 0, 0);
+}
+
+static VALUE
+call_stop(VALUE *v)
+{
+ return v[0] = Qundef;
+}
+
+static VALUE
zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
{
volatile VALUE result = memo->u1.value;
@@ -1357,8 +1369,20 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
for (i=0; i<RARRAY_LEN(args); i++) {
- VALUE v = rb_funcall(RARRAY_PTR(args)[i], id_next, 0, 0);
- rb_ary_push(tmp, v);
+ if (NIL_P(RARRAY_PTR(args)[i])) {
+ rb_ary_push(tmp, Qnil);
+ }
+ else {
+ VALUE v[2];
+
+ v[1] = RARRAY_PTR(args)[i];
+ rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
+ if (v[0] == Qundef) {
+ RARRAY_PTR(args)[i] = Qnil;
+ v[0] = Qnil;
+ }
+ rb_ary_push(tmp, v[0]);
+ }
}
if (NIL_P(result)) {
rb_yield(tmp);
@@ -1369,12 +1393,6 @@ zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
return Qnil;
}
-static VALUE
-zip_b(NODE *memo)
-{
- return rb_block_call(memo->u3.value, id_each, 0, 0, zip_i, (VALUE)memo);
-}
-
/*
* call-seq:
* enum.zip(arg, ...) => enumerator
@@ -1401,16 +1419,19 @@ static VALUE
enum_zip(int argc, VALUE *argv, VALUE obj)
{
int i;
- VALUE result;
+ ID conv;
NODE *memo;
+ VALUE result = Qnil;
+ conv = rb_intern("to_enum");
for (i=0; i<argc; i++) {
- argv[i] = rb_funcall(argv[i], rb_intern("to_enum"), 1, ID2SYM(id_each));
+ argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
}
- RETURN_ENUMERATOR(obj, argc, argv);
- result = rb_block_given_p() ? Qnil : rb_ary_new();
- memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), obj);
- rb_rescue2(zip_b, (VALUE)memo, 0, 0, rb_eStopIteration, (VALUE)0);
+ if (!rb_block_given_p()) {
+ result = rb_ary_new();
+ }
+ memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
+ rb_block_call(obj, id_each, 0, 0, zip_i, (VALUE)memo);
return result;
}