commit 19ad368f68164b99a2cfedb11747d7ca2d040ee0
Author:     Mattias Andrée <maand...@kth.se>
AuthorDate: Wed May 10 21:29:46 2017 +0200
Commit:     Mattias Andrée <maand...@kth.se>
CommitDate: Wed May 10 21:29:46 2017 +0200

    Cleaner code
    
    Signed-off-by: Mattias Andrée <maand...@kth.se>

diff --git a/man/blind-transpose.1 b/man/blind-transpose.1
index 73dbfd5..0323ec3 100644
--- a/man/blind-transpose.1
+++ b/man/blind-transpose.1
@@ -15,9 +15,6 @@ X and Y coordinates.
 requires enough free memory to load one full frames and
 one input column into memory. A frame requires 32 bytes
 per pixel it contains.
-.B blind-transpose
-has not been optimised for memory usage, but instead
-for code simplicity.
 .SH SEE ALSO
 .BR blind (7),
 .BR blind-flip (1),
diff --git a/src/blind-arithm.c b/src/blind-arithm.c
index 77e691f..1c2c11b 100644
--- a/src/blind-arithm.c
+++ b/src/blind-arithm.c
@@ -74,7 +74,7 @@ int
 main(int argc, char *argv[])
 {
        struct stream left, right;
-       process_func process = NULL;
+       process_func process;
 
        ARGBEGIN {
        case 'a':
diff --git a/src/blind-compress.c b/src/blind-compress.c
index 375055d..0da5194 100644
--- a/src/blind-compress.c
+++ b/src/blind-compress.c
@@ -17,7 +17,7 @@ compare(const char *restrict new, const char *restrict old, 
size_t n, size_t **c
                        (*cmp)[ptr - 1] += same + diff;
                } else {
                        if (ptr + 2 > *cmpsize)
-                               *cmp = erealloc(*cmp, (*cmpsize += 128) * 
sizeof(size_t));
+                               *cmp = erealloc2(*cmp, *cmpsize += 128, 
sizeof(size_t));
                        (*cmp)[ptr++] = same;
                        (*cmp)[ptr++] = diff;
                }
diff --git a/src/blind-concat.c b/src/blind-concat.c
index a323af8..f7d31e3 100644
--- a/src/blind-concat.c
+++ b/src/blind-concat.c
@@ -17,7 +17,7 @@ concat_to_stdout(int argc, char *argv[], const char *fname)
        size_t frames = 0;
        int i;
 
-       streams = emalloc((size_t)argc * sizeof(*streams));
+       streams = emalloc2((size_t)argc, sizeof(*streams));
 
        for (i = 0; i < argc; i++) {
                eopen_stream(streams + i, argv[i]);
@@ -33,10 +33,7 @@ concat_to_stdout(int argc, char *argv[], const char *fname)
        efflush(stdout, fname);
 
        for (i = 0; i < argc; i++) {
-               do {
-                       ewriteall(STDOUT_FILENO, streams[i].buf, 
streams[i].ptr, fname);
-                       streams[i].ptr = 0;
-               } while (eread_stream(streams + i, SIZE_MAX));
+               esend_stream(streams + i, STDOUT_FILENO, fname);
                close(streams[i].fd);
        }
 
@@ -50,7 +47,9 @@ concat_to_file(int argc, char *argv[], char *output_file)
        int first = 1;
        int fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666);
        char head[STREAM_HEAD_MAX];
-       ssize_t headlen, size = 0;
+       ssize_t headlen;
+       size_t size = 0;
+       off_t pos;
        char *data;
 
        for (; argc--; argv++) {
@@ -66,23 +65,23 @@ concat_to_file(int argc, char *argv[], char *output_file)
                        echeck_compat(&stream, &refstream);
                }
 
-               do {
-                       ewriteall(fd, stream.buf, stream.ptr, output_file);
-                       size += stream.ptr;
-                       stream.ptr = 0;
-               } while (eread_stream(&stream, SIZE_MAX));
+               esend_stream(&stream, fd, output_file);
                close(stream.fd);
        }
 
        SPRINTF_HEAD_ZN(head, stream.frames, stream.width, stream.height, 
stream.pixfmt, &headlen);
        ewriteall(fd, head, (size_t)headlen, output_file);
 
-       data = mmap(0, size + (size_t)headlen, PROT_READ | PROT_WRITE, 
MAP_SHARED, fd, 0);
+       if ((pos = elseek(fd, 0, SEEK_CUR, output_file)) > SIZE_MAX)
+               eprintf("%s\n", strerror(EFBIG));
+       size = pos;
+
+       data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if (data == MAP_FAILED)
                eprintf("mmap %s:", output_file);
-       memmove(data + headlen, data, size);
+       memmove(data + headlen, data, size - (size_t)headlen);
        memcpy(data, head, (size_t)headlen);
-       munmap(data, size + (size_t)headlen);
+       munmap(data, size);
 
        close(fd);
 }
@@ -108,9 +107,9 @@ concat_to_file_parallel(int argc, char *argv[], char 
*output_file, size_t jobs)
                jobs = (size_t)argc;
 
        fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666);
-       events  = emalloc(jobs * sizeof(*events));
-       streams = emalloc((size_t)argc * sizeof(*streams));
-       ptrs    = emalloc((size_t)argc * sizeof(*ptrs));
+       events  = emalloc2(jobs, sizeof(*events));
+       streams = emalloc2((size_t)argc, sizeof(*streams));
+       ptrs    = emalloc2((size_t)argc, sizeof(*ptrs));
 
        for (i = 0; i < argc; i++) {
                eopen_stream(streams + i, argv[i]);
diff --git a/src/blind-cut.c b/src/blind-cut.c
index 62ef98b..b21e83d 100644
--- a/src/blind-cut.c
+++ b/src/blind-cut.c
@@ -10,9 +10,7 @@ int
 main(int argc, char *argv[])
 {
        struct stream stream;
-       size_t start = 0, end = 0, ptr, max;
-       ssize_t r;
-       char buf[BUFSIZ];
+       size_t start = 0, end = 0;
        int to_end = 0;
 
        UNOFLAGS(argc != 3);
@@ -32,26 +30,16 @@ main(int argc, char *argv[])
                end = stream.frames;
        else if (end > stream.frames)
                eprintf("end point is after end of video\n");
-       stream.frames = end - start;
-       echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, NULL);
-       fprint_stream_head(stdout, &stream);
-       efflush(stdout, "<stdout>");
-
        if (start >= end)
                eprintf("%s\n", start > end ?
                        "start point is after end point" :
                        "refusing to create video with zero frames");
-       end   = end   * stream.frame_size + stream.headlen;
-       start = start * stream.frame_size + stream.headlen;
-
-       fadvise_sequential(stream.fd, start, end - start);
-       for (ptr = start; ptr < end; ptr += (size_t)r) {
-               max = end - ptr;
-               max = MIN(max, sizeof(buf));
-               if (!(r = epread(stream.fd, buf, max, ptr, stream.file)))
-                       eprintf("%s: file is shorter than expected\n", 
stream.file);
-               ewriteall(STDOUT_FILENO, buf, (size_t)r, "<stdout>");
-       }
+       stream.frames = end - start;
+       fprint_stream_head(stdout, &stream);
+       efflush(stdout, "<stdout>");
+
+       esend_frames(&stream, -1, start, NULL);
+       esend_frames(&stream, STDOUT_FILENO, start - end, "<stdout>");
 
        close(stream.fd);
        return 0;
diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c
index 3bbe1b9..8416279 100644
--- a/src/blind-dissolve.c
+++ b/src/blind-dissolve.c
@@ -31,7 +31,7 @@ main(int argc, char *argv[])
 {
        struct stream stream;
        int reverse = 0;
-       void (*process)(struct stream *stream, size_t n, size_t f) = NULL;
+       void (*process)(struct stream *stream, size_t n, size_t f);
 
        ARGBEGIN {
        case 'r':
diff --git a/src/blind-from-text.c b/src/blind-from-text.c
index a03adaf..d7c10ce 100644
--- a/src/blind-from-text.c
+++ b/src/blind-from-text.c
@@ -33,7 +33,7 @@ main(int argc, char *argv[])
        size_t size = 0;
        char *line = NULL;
        ssize_t len;
-       void (*process)(void) = NULL;
+       void (*process)(void);
 
        UNOFLAGS(argc);
 
diff --git a/src/blind-invert-luma.c b/src/blind-invert-luma.c
index cedfc2e..96001cb 100644
--- a/src/blind-invert-luma.c
+++ b/src/blind-invert-luma.c
@@ -58,7 +58,7 @@ main(int argc, char *argv[])
 {
        int invert = 0, whitepoint = 0;
        struct stream colour, mask;
-       void (*process)(struct stream *colour, struct stream *mask, size_t n) = 
NULL;
+       void (*process)(struct stream *colour, struct stream *mask, size_t n);
 
        ARGBEGIN {
        case 'i':
diff --git a/src/blind-next-frame.c b/src/blind-next-frame.c
index e6e7f4b..51e956a 100644
--- a/src/blind-next-frame.c
+++ b/src/blind-next-frame.c
@@ -10,15 +10,15 @@ int
 main(int argc, char *argv[])
 {
        struct stream stream;
-       size_t n, w, h = 0;
-       int i, anything = 0;
+       size_t n;
+       int i;
        char *p;
 
        stream.frames = 1;
 
        ARGBEGIN {
        case 'f':
-               stream.frames = etozu_flag('f', UARGF(), 1, SIZE_MAX);
+               stream.frames = entozu_flag(2, 'f', UARGF(), 1, SIZE_MAX);
                break;
        default:
                usage();
@@ -51,21 +51,10 @@ main(int argc, char *argv[])
        fprint_stream_head(stdout, &stream);
        enfflush(2, stdout, "<stdout>");
 
-       w = stream.width * stream.pixel_size;
-       for (; stream.frames; stream.frames--) {
-               for (h = stream.height; h; h--) {
-                       for (n = w; n; n -= stream.ptr, stream.ptr = 0) {
-                               if (!stream.ptr && !enread_stream(2, &stream, 
n))
-                                       goto done;
-                               anything = 1;
-                               enwriteall(2, STDOUT_FILENO, stream.buf, 
stream.ptr, "<stdout>");
-                       }
-               }
-       }
-done:
-
-       if (anything && stream.frames)
+       n = ensend_frames(2, &stream, STDOUT_FILENO, stream.frames, "<stdout>");
+       if (!n)
+               return 1;
+       else if (n < stream.frames)
                enprintf(2, "%s: is shorter than expected\n", stream.file);
-
-       return !anything;
+       return 0;
 }
diff --git a/src/blind-repeat.c b/src/blind-repeat.c
index 6e2b169..17164e7 100644
--- a/src/blind-repeat.c
+++ b/src/blind-repeat.c
@@ -6,96 +6,56 @@
 
 USAGE("(count | 'inf') file")
 
-static void
-repeat_regular_file(char *file, size_t count, int inf)
-{
-       struct stream stream;
-       char buf[BUFSIZ];
-       size_t ptr;
-       ssize_t r;
-
-       eopen_stream(&stream, file);
-       if (count > SIZE_MAX / stream.frames)
-               eprintf("%s: video is too long\n", stream.file);
-       stream.frames *= count;
-       fprint_stream_head(stdout, &stream);
-       efflush(stdout, "<stdout>");
+static size_t count = 0;
+static int inf;
+static struct stream stream;
 
+static int
+repeat_regular_file(void)
+{
        while (inf || count--) {
                fadvise_sequential(stream.fd, stream.headlen, 0);
-               for (ptr = stream.headlen;; ptr += (size_t)r) {
-                       if (!(r = epread(stream.fd, buf, sizeof(buf), ptr, 
stream.file)))
-                               break;
-                       if (writeall(STDOUT_FILENO, buf, (size_t)r)) {
-                               if (!inf || errno != EPIPE)
-                                       eprintf("write <stdout>:");
-                               return;
-                       }
-               }
+               elseek(stream.fd, stream.headlen, SEEK_SET, stream.file);
+               if (esend_stream(&stream, STDOUT_FILENO, NULL))
+                       return -1;
        }
-
-       close(stream.fd);
+       return 0;
 }
 
-static void
-repeat_stdin(size_t count, int inf)
+static int
+repeat_stdin(void)
 {
-       struct stream stream;
-       char *buf;
-       size_t ptr, size;
-       ssize_t r;
-
-       eopen_stream(&stream, NULL);
-       if (count > SIZE_MAX / stream.frames)
-               eprintf("%s: video is too long\n", stream.file);
-       stream.frames *= count;
-       fprint_stream_head(stdout, &stream);
-       efflush(stdout, "<stdout>");
-
-       ptr = stream.ptr;
-       size = MAX(ptr, BUFSIZ);
-       buf = emalloc(size);
-       memcpy(buf, stream.buf, ptr);
-
-       for (;;) {
-               if (ptr == size)
-                       buf = erealloc(buf, size <<= 1);
-               if (!(r = eread(STDIN_FILENO, buf + ptr, size - ptr, 
"<stdout>")))
-                       break;
-               ptr += (size_t)r;
-       }
-
-       while (inf || count--) {
-               if (writeall(STDOUT_FILENO, buf, ptr)) {
-                       if (!inf || errno != EPIPE)
-                               eprintf("write <stdout>:");
-                       return;
-               }
-       }
-
-       free(buf);
+       size_t ptr = stream.ptr;
+       size_t size = MAX(ptr, BUFSIZ);
+       char *buf = memcpy(emalloc(size), stream.buf, ptr);
+       egetfile(STDIN_FILENO, &buf, &ptr, &size, "<stdout>");
+       while (inf || count--)
+               if (writeall(STDOUT_FILENO, buf, ptr))
+                       return free(buf), -1;
+       return free(buf), 0;
 }
 
 int
 main(int argc, char *argv[])
 {
-       size_t count = 0;
-       int inf = 0;
-
        UNOFLAGS(argc != 2);
 
-       if (!strcmp(argv[0], "inf"))
-               inf = 1;
+       if ((inf = !strcmp(argv[0], "inf")))
+               einf_check_fd(STDOUT_FILENO, "<stdout>");
        else
                count = etozu_arg("the count", argv[0], 0, SIZE_MAX);
 
-       if (inf)
-               einf_check_fd(STDOUT_FILENO, "<stdout>");
+       eopen_stream(&stream, !strcmp(argv[1], "-") ? NULL : argv[1]);
+       if (count > SIZE_MAX / stream.frames)
+               eprintf("%s: video is too long\n", stream.file);
+       stream.frames *= count;
+       fprint_stream_head(stdout, &stream);
+       efflush(stdout, "<stdout>");
 
-       if (!strcmp(argv[1], "-"))
-               repeat_stdin(count, inf);
-       else
-               repeat_regular_file(argv[1], count, inf);
+       if (!strcmp(argv[1], "-") ? repeat_stdin() : repeat_regular_file())
+               if (!inf || errno != EPIPE)
+                       eprintf("write <stdout>:");
 
+       close(stream.fd);
        return 0;
 }
diff --git a/src/blind-set-alpha.c b/src/blind-set-alpha.c
index 72222f6..d09bdbe 100644
--- a/src/blind-set-alpha.c
+++ b/src/blind-set-alpha.c
@@ -27,7 +27,7 @@ main(int argc, char *argv[])
 {
        int invert = 0;
        struct stream colour, alpha;
-       void (*process)(struct stream *colour, struct stream *alpha, size_t n) 
= NULL;
+       void (*process)(struct stream *colour, struct stream *alpha, size_t n);
 
        ARGBEGIN {
        case 'i':
diff --git a/src/blind-set-saturation.c b/src/blind-set-saturation.c
index 626fc37..5705ede 100644
--- a/src/blind-set-saturation.c
+++ b/src/blind-set-saturation.c
@@ -54,7 +54,7 @@ main(int argc, char *argv[])
 {
        struct stream colour, satur;
        int whitepoint = 0;
-       void (*process)(struct stream *colour, struct stream *satur, size_t n) 
= NULL;
+       void (*process)(struct stream *colour, struct stream *satur, size_t n);
 
        ARGBEGIN {
        case 'w':
diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c
index d367a37..6b510ac 100644
--- a/src/blind-single-colour.c
+++ b/src/blind-single-colour.c
@@ -39,7 +39,7 @@ main(int argc, char *argv[])
 {
        char *arg;
        const char *pixfmt = "xyza";
-       void (*process)(void) = NULL;
+       void (*process)(void);
 
        ARGBEGIN {
        case 'f':
diff --git a/src/blind-skip-pattern.c b/src/blind-skip-pattern.c
index e8eee0b..1d3e25d 100644
--- a/src/blind-skip-pattern.c
+++ b/src/blind-skip-pattern.c
@@ -6,35 +6,11 @@
 
 USAGE("(skipped-frames | +included-frames) ...")
 
-static int
-process_frame(struct stream *stream, int include)
-{
-       size_t h, n, m;
-       int anything = 0;
-
-       for (h = stream->height; h; h--) {
-               for (n = stream->row_size; n; n -= m, anything = 1) {
-                       if (!stream->ptr && !eread_stream(stream, n))
-                               goto done;
-                       m = MIN(stream->ptr, n);
-                       if (include)
-                               ewriteall(STDOUT_FILENO, stream->buf, m, 
"<stdout>");
-                       memmove(stream->buf, stream->buf + m, stream->ptr -= m);
-               }
-       }
-done:
-
-       if (anything && h)
-               eprintf("%s: is shorter than expected\n", stream->file);
-
-       return anything;
-}
-
 int
 main(int argc, char *argv[])
 {
        struct stream stream;
-       int i, include;
+       int i, include, outfd;
        size_t f, n, total = 0;
        char *includes;
        size_t *ns;
@@ -68,13 +44,11 @@ main(int argc, char *argv[])
        efflush(stdout, "<stdout>");
 
        for (i = 0;; i = (i + 1) % argc) {
-               include = (int)includes[i];
-               for (n = ns[i]; n--;)
-                       if (!process_frame(&stream, include))
-                               goto done;
+               outfd = includes[i] ? STDOUT_FILENO : -1;
+               if (!esend_frames(&stream, outfd, ns[i], "<stdout>"))
+                       break;
        }
 
-done:
        free(includes);
        free(ns);
        return 0;
diff --git a/src/blind-split.c b/src/blind-split.c
index f6949f6..2014e52 100644
--- a/src/blind-split.c
+++ b/src/blind-split.c
@@ -11,7 +11,7 @@ int
 main(int argc, char *argv[])
 {
        struct stream stream;
-       size_t *ends, i, parts, ptr, end, n;
+       size_t *ends, i, parts, n;
        char *to_end;
        FILE *fp;
        int fd, unknown_length = 0;
@@ -28,54 +28,37 @@ main(int argc, char *argv[])
                usage();
 
        eopen_stream(&stream, NULL);
-       echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, NULL);
+       echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
 
        parts = (size_t)argc / 2;
        ends = alloca(parts * sizeof(*ends));
        to_end = alloca(parts);
 
        for (i = 0; i < parts; i++) {
-               to_end[i] = 0;
-               if (!strcmp(argv[i * 2 + 1], "end")) {
+               if ((to_end[i] = !strcmp(argv[i * 2 + 1], "end")))
                        ends[i] = unknown_length ? SIZE_MAX : stream.frames;
-                       to_end[i] = 1;
-               } else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i)) {
+               else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i))
                        eprintf("the end point must be an integer in [0, 
%zu]\n", SIZE_MAX);
-               }
+
                if (i && ends[i] <= ends[i - 1])
                        eprintf("the end points must be in strictly ascending 
order\n");
                if (!unknown_length && ends[i] > stream.frames)
                        eprintf("frame %zu is beyond the end of the video\n", 
ends[i]);
        }
 
-       ptr = 0;
        for (i = 0; i < parts; i++) {
                fd = eopen(argv[i * 2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
-               fp = fdopen(fd, "wb");
-               if (!fp)
+               if (!(fp = fdopen(fd, "wb")))
                        eprintf("fdopen %s:", argv[i * 2]);
 
-               stream.frames = ends[i] - (i ? ends[i - 1] : 0);
+               n = ends[i] - (i ? ends[i - 1] : 0);
+               stream.frames = (to_end[i] && unknown_length) ? 0 : n;
                fprint_stream_head(fp, &stream);
                efflush(fp, argv[i * 2]);
 
-               for (end = to_end[i] ? SIZE_MAX : ends[i] * stream.frame_size; 
ptr < end; ptr += n) {
-                       n = end - ptr;
-                       if (stream.ptr) {
-                               n = MIN(stream.ptr, n);
-                               ewriteall(fd, stream.buf, n, argv[i * 2]);
-                               memmove(stream.buf, stream.buf + n, stream.ptr 
-= n);
-                       } else if ((n = eread_stream(&stream, n))) {
-                               ewriteall(fd, stream.buf, n, argv[i * 2]);
-                               stream.ptr = 0;
-                       } else if (ptr % stream.frame_size) {
-                               eprintf("%s: incomplete frame\n", stream.file);
-                       } else if (!unknown_length || !to_end[i]) {
+               if (esend_frames(&stream, fd, n, argv[i * 2]) != n)
+                       if (!unknown_length || !to_end[i])
                                eprintf("%s: file is shorter than expected\n", 
stream.file);
-                       } else {
-                               break;
-                       }
-               }
 
                if (fclose(fp))
                        eprintf("%s:", argv[i * 2]);
diff --git a/src/blind-stack.c b/src/blind-stack.c
index 4591154..0eab3ec 100644
--- a/src/blind-stack.c
+++ b/src/blind-stack.c
@@ -46,7 +46,7 @@ main(int argc, char *argv[])
        struct stream *streams;
        size_t n_streams, i, frames = 0, tmp;
        int blend = 0;
-       void (*process)(struct stream *streams, size_t n_streams, size_t n) = 
NULL;
+       void (*process)(struct stream *streams, size_t n_streams, size_t n);
 
        ARGBEGIN {
        case 'b':
diff --git a/src/blind-to-text.c b/src/blind-to-text.c
index ed95f08..b8e6d8f 100644
--- a/src/blind-to-text.c
+++ b/src/blind-to-text.c
@@ -24,7 +24,7 @@ int
 main(int argc, char *argv[])
 {
        struct stream stream;
-       void (*process)(struct stream *stream, size_t n) = NULL;
+       void (*process)(struct stream *stream, size_t n);
 
        UNOFLAGS(argc);
 
diff --git a/src/blind-to-video.c b/src/blind-to-video.c
index 5d25789..e33fafc 100644
--- a/src/blind-to-video.c
+++ b/src/blind-to-video.c
@@ -72,7 +72,7 @@ main(int argc, char *argv[])
        size_t n = 0;
        int status, pipe_rw[2];
        pid_t pid;
-       void (*process)(struct stream *stream, size_t n) = NULL;
+       void (*process)(struct stream *stream, size_t n);
 
        ARGBEGIN {
        case 'd':
diff --git a/src/stream.c b/src/stream.c
index 259b967..274ed25 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -276,6 +276,48 @@ enread_segment(int status, struct stream *stream, void 
*buf, size_t n)
 }
 
 
+size_t
+ensend_frames(int status, struct stream *stream, int outfd, size_t frames, 
const char *outfname)
+{
+       size_t h, w, p;
+       size_t ret = 0;
+
+       for (ret = 0; ret < frames; ret++) {
+               for (p = stream->pixel_size; p; p--) {
+                       for (h = stream->height; h; h--) {
+                               for (w = stream->width; w; w -= stream->ptr, 
stream->ptr = 0) {
+                                       if (!stream->ptr && 
!enread_stream(status, stream, w))
+                                               goto done;
+                                       if (outfd >= 0)
+                                               enwriteall(status, outfd, 
stream->buf, stream->ptr, outfname);
+                               }
+                       }
+               }
+       }
+
+       return ret;
+done:
+       if (p != stream->pixel_size || h != stream->height || w != 
stream->width)
+               enprintf(status, "%s: incomplete frame", stream->file);
+       return ret;
+}
+
+
+int
+ensend_stream(int status, struct stream *stream, int outfd, const char 
*outfname)
+{
+       do {
+               if (writeall(outfd, stream->buf, stream->ptr)) {
+                       if (outfname)
+                               eprintf("write %s:", outfname);
+                       return -1;
+               }
+               stream->ptr = 0;
+       } while (enread_stream(status, stream, SIZE_MAX));
+       return 0;
+}
+
+
 void
 nprocess_stream(int status, struct stream *stream, void (*process)(struct 
stream *stream, size_t n))
 {
diff --git a/src/stream.h b/src/stream.h
index e419c89..3e239d4 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -32,6 +32,8 @@
 #define eread_segment(...)            enread_segment(1, __VA_ARGS__)
 #define eread_frame(...)              enread_frame(1, __VA_ARGS__)
 #define eread_row(...)                enread_row(1, __VA_ARGS__)
+#define esend_frames(...)             ensend_frames(1, __VA_ARGS__)
+#define esend_stream(...)             ensend_stream(1, __VA_ARGS__)
 
 #define process_stream(...)                 nprocess_stream(1, __VA_ARGS__)
 #define process_each_frame_segmented(...)   nprocess_each_frame_segmented(1, 
__VA_ARGS__)
@@ -76,6 +78,8 @@ void encheck_dimensions(int status, const struct stream 
*stream, enum dimension
 void encheck_compat(int status, const struct stream *a, const struct stream 
*b);
 const char *get_pixel_format(const char *specified, const char *current);
 int enread_segment(int status, struct stream *stream, void *buf, size_t n);
+size_t ensend_frames(int status, struct stream *stream, int outfd, size_t 
frames, const char *outfname);
+int ensend_stream(int status, struct stream *stream, int outfd, const char 
*outfname);
 
 void nprocess_stream(int status, struct stream *stream, void (*process)(struct 
stream *stream, size_t n));
 
diff --git a/src/util.c b/src/util.c
index f6150f2..c1943d7 100644
--- a/src/util.c
+++ b/src/util.c
@@ -166,6 +166,34 @@ writezeroes(int fd, void *buf, size_t bufsize, size_t n)
        return 0;
 }
 
+int
+getfile(int fd, void *buffer, size_t *restrict ptr, size_t *restrict size)
+{
+       char *restrict *restrict buf = buffer;
+       void *new;
+       size_t r;
+
+       for (;;) {
+               if (*ptr == *size) {
+                       if (!(new = realloc(*buf, *size << 1))) {
+                               errno = ENOMEM;
+                               return -1;
+                       }
+                       *buf = new;
+                       *size <<= 1;
+               }
+               r = read(fd, *buf + *ptr, *size - *ptr);
+               if (r <= 0) {
+                       if (r)
+                               return -1;
+                       break;
+               }
+               *ptr += (size_t)r;
+       }
+
+       return 0;
+}
+
 
 static inline pid_t
 enfork(int status)
@@ -193,7 +221,7 @@ enfork_jobs(int status, size_t *start, size_t *end, size_t 
jobs, pid_t **pids)
                return 1;
        }
        *end = n / jobs + s;
-       *pids = enmalloc(status, jobs * sizeof(**pids));
+       *pids = enmalloc2(status, jobs, sizeof(**pids));
        for (j = 1; j < jobs; j++) {
                pid = enfork(status);
                if (!pid) {
diff --git a/src/util.h b/src/util.h
index ce5f647..24fc2c4 100644
--- a/src/util.h
+++ b/src/util.h
@@ -6,7 +6,7 @@
 #define MAX(A, B)         ((A) > (B) ? (A) : (B))
 #define CLIP(A, B, C)     ((B) < (A) ? (A) : (B) > (C) ? (C) : (B))
 #define STRLEN(STR)       (sizeof(STR) - 1)
-#define INTSTRLEN(TYPE)   ((sizeof(TYPE) == 1 ? 3 : (5 * sizeof(TYPE) / 2)) + 
(TYPE)-1 < 0)
+#define INTSTRLEN(TYPE)   ((sizeof(TYPE) == 1 ? 3 : (5 * sizeof(TYPE) / 2)) + 
((TYPE)-1 < 0))
 
 #define USAGE(SYNOPSIS)\
        static void usage(void)\
diff --git a/src/util/emalloc.h b/src/util/emalloc.h
index 81816be..f4a7f12 100644
--- a/src/util/emalloc.h
+++ b/src/util/emalloc.h
@@ -1,9 +1,15 @@
 /* See LICENSE file for copyright and license details. */
 #include <stdlib.h>
+#include <stdint.h>
 
-#define emalloc(...) enmalloc(1, __VA_ARGS__)
-#define ecalloc(...) encalloc(1, __VA_ARGS__)
-#define erealloc(...) enrealloc(1, __VA_ARGS__)
+#define emalloc(...)   enmalloc(1, __VA_ARGS__)
+#define emalloc2(...)  enmalloc2(1, __VA_ARGS__)
+#define ecalloc(...)   encalloc(1, __VA_ARGS__)
+#define erealloc(...)  enrealloc(1, __VA_ARGS__)
+#define erealloc2(...) enrealloc2(1, __VA_ARGS__)
+
+#define malloc2(n, m)     malloc(n * m);
+#define realloc3(p, n, m) realloc(p, n * m);
 
 static inline void *
 enmalloc(int status, size_t n)
@@ -15,6 +21,15 @@ enmalloc(int status, size_t n)
 }
 
 static inline void *
+enmalloc2(int status, size_t n, size_t m)
+{
+       void *ptr;
+       if (n > SIZE_MAX / m || !(ptr = malloc(n * m)))
+               enprintf(status, "malloc: out of memory\n");
+       return ptr;
+}
+
+static inline void *
 encalloc(int status, size_t n, size_t m)
 {
        void *ptr = calloc(n, m);
@@ -31,3 +46,11 @@ enrealloc(int status, void *ptr, size_t n)
                enprintf(status, "realloc: out of memory\n");
        return ptr;
 }
+
+static inline void *
+enrealloc2(int status, void *ptr, size_t n, size_t m)
+{
+       if (n > SIZE_MAX / m || !(ptr = realloc(ptr, n * m)))
+               enprintf(status, "realloc: out of memory\n");
+       return ptr;
+}
diff --git a/src/util/io.h b/src/util/io.h
index 8c646cb..44c0a92 100644
--- a/src/util/io.h
+++ b/src/util/io.h
@@ -1,5 +1,6 @@
 /* See LICENSE file for copyright and license details. */
 #include <fcntl.h>
+#include <errno.h>
 
 #if defined(POSIX_FADV_SEQUENTIAL)
 # define fadvise_sequential(...)  posix_fadvise(__VA_ARGS__, 
POSIX_FADV_SEQUENTIAL)
@@ -17,6 +18,7 @@
 #define ereadall(...)      enreadall(1, __VA_ARGS__)
 #define epwriteall(...)    enpwriteall(1, __VA_ARGS__)
 #define ewritezeroes(...)  enwritezeroes(1, __VA_ARGS__)
+#define egetfile(...)      engetfile(1, __VA_ARGS__)
 
 int writeall(int fd, void *buf, size_t n);
 
@@ -55,3 +57,17 @@ enwritezeroes(int status, int fd, void *buf, size_t bufsize, 
size_t n, const cha
        if (writezeroes(fd, buf, bufsize, n))
                enprintf(status, "write %s:", fname);
 }
+
+int getfile(int fd, void *bufp, size_t *restrict ptrp, size_t *restrict sizep);
+
+static inline void
+engetfile(int status, int fd, void *bufp, size_t *restrict ptrp,
+         size_t *restrict sizep, const char *fname)
+{
+       if (getfile(fd, bufp, ptrp, sizep)) {
+               if (errno == ENOMEM)
+                       enprintf(status, "realloc:");
+               else
+                       enprintf(status, "read %s:", fname);
+       }
+}

Reply via email to