about summary refs log tree commit homepage
path: root/ext/io_splice
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-05-24 23:27:14 -0700
committerEric Wong <normalperson@yhbt.net>2010-05-24 23:27:14 -0700
commitbde5844909cd61ecfa3393fba4e9884c083f2fa8 (patch)
treeaac869f82fe13e0f91ee110e9e6fe9849b86a308 /ext/io_splice
parentc405321e8df7ff71417cc0b6f7b0624e18970655 (diff)
downloadruby_io_splice-bde5844909cd61ecfa3393fba4e9884c083f2fa8.tar.gz
Diffstat (limited to 'ext/io_splice')
-rw-r--r--ext/io_splice/io_splice_ext.c48
1 files changed, 24 insertions, 24 deletions
diff --git a/ext/io_splice/io_splice_ext.c b/ext/io_splice/io_splice_ext.c
index 0679273..69c0288 100644
--- a/ext/io_splice/io_splice_ext.c
+++ b/ext/io_splice/io_splice_ext.c
@@ -223,6 +223,28 @@ static VALUE nogvl_vmsplice(void *ptr)
         return (VALUE)vmsplice(a->fd, a->iov, a->nr_segs, a->flags);
 }
 
+/* this can't be a function since we use alloca() */
+#define ARY2IOVEC(iov,iovcnt,expect,ary) \
+do { \
+        VALUE *cur; \
+        struct iovec *tmp; \
+        long n; \
+        Check_Type(ary, T_ARRAY); \
+        cur = RARRAY_PTR(ary); \
+        n = RARRAY_LEN(ary); \
+        if (n > IOV_MAX) \
+                rb_raise(rb_eArgError, "array is larger than IOV_MAX"); \
+        iov = tmp = alloca(sizeof(struct iovec) * n); \
+        expect = 0; \
+        iovcnt = n; \
+        for (; --n >= 0; tmp++, cur++) { \
+                Check_Type(*cur, T_STRING); \
+                tmp->iov_base = RSTRING_PTR(*cur); \
+                tmp->iov_len = RSTRING_LEN(*cur); \
+                expect += tmp->iov_len; \
+        } \
+} while (0)
+
 /*
  * call-seq:
  *   IO.vmsplice(fd, string_array, flags) => integer
@@ -239,32 +261,10 @@ static VALUE nogvl_vmsplice(void *ptr)
 static VALUE my_vmsplice(VALUE self, VALUE fd, VALUE data, VALUE flags)
 {
         long n;
+        ssize_t left;
         struct vmsplice_args a;
-        struct iovec *tmp;
-        VALUE *ary;
-
-        switch (TYPE(data)) {
-        case T_ARRAY:
-                ary = RARRAY_PTR(data);
-                a.nr_segs = RARRAY_LEN(data);
-
-                if (a.nr_segs > IOV_MAX)
-                        rb_raise(rb_eArgError, "array larger than IOV_MAX");
-
-                a.iov = tmp = alloca(sizeof(struct iovec) * a.nr_segs);
-
-                for (n = (long)a.nr_segs; --n >= 0; tmp++, ary++) {
-                        if (TYPE(*ary) != T_STRING)
-                                rb_raise(rb_eArgError,
-                                         "must be an array of strings");
-                        tmp->iov_base = RSTRING_PTR(*ary);
-                        tmp->iov_len = RSTRING_LEN(*ary);
-                }
-                break;
-        default:
-                rb_raise(rb_eArgError, "must be an array of strings");
-        }
 
+        ARY2IOVEC(a.iov, a.nr_segs, left, data);
         a.fd = NUM2INT(fd);
         a.flags = NUM2UINT(flags);