blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit f757761b310a899dc8ece7ad7845ed0a22ff752b
parent 2debbbe6e70b66357fa510850b57c47406a87249
Author: Mattias Andrée <maandree@kth.se>
Date:   Thu, 26 Jan 2017 07:26:42 +0100

Add blind-compress and blind-decompress

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
Asrc/blind-compress.c | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-decompress.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/src/blind-compress.c b/src/blind-compress.c @@ -0,0 +1,69 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include <string.h> +#include <unistd.h> + +USAGE("") + +static size_t +compare(const char *restrict new, const char *restrict old, size_t n, size_t **cmp, size_t *cmpsize) +{ + size_t i, start1, start2, ptr, same, diff; + for (ptr = i = 0; i < n;) { + for (start1 = i; i < n && old[i] == new[i]; i++); + for (start2 = i; i < n && old[i] != new[i]; i++); + same = start2 - start1; + diff = i - start2; + if (ptr && same < 2 * sizeof(size_t) && same + diff <= SIZE_MAX - (*cmp)[ptr - 1]) { + (*cmp)[ptr - 1] += same + diff; + } else { + if (ptr + 2 > *cmpsize) + *cmp = erealloc(*cmp, (*cmpsize += 128) * sizeof(size_t)); + (*cmp)[ptr++] = same; + (*cmp)[ptr++] = diff; + } + } + return ptr; +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf[2]; + size_t n, parts, part, off; + int i; + size_t *cmp = NULL; + size_t cmpsize = 0; + + ENOFLAGS(argc); + + stream.file = "<stdin>"; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, "<stdin>"); + n = stream.width * stream.height * stream.pixel_size; + buf[0] = emalloc(n); + buf[1] = ecalloc(1, n); + + memcpy(buf[0], stream.buf, stream.ptr); + for (i = 0; eread_frame(&stream, buf[i], n); i ^= 1) { + parts = compare(buf[i], buf[i ^ 1], n, &cmp, &cmpsize); + for (off = part = 0; part < parts; part += 2) { + off += cmp[part]; + ewriteall(STDOUT_FILENO, cmp + part, 2 * sizeof(size_t), "<stdout>"); + ewriteall(STDOUT_FILENO, buf[i] + off, cmp[part + 1], "<stdout>"); + off += cmp[part + 1]; + } + } + + free(cmp); + free(buf[0]); + free(buf[1]); + return 0; +} diff --git a/src/blind-decompress.c b/src/blind-decompress.c @@ -0,0 +1,64 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include <string.h> +#include <unistd.h> + +USAGE("") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf; + size_t n, m, fptr, sptr, same = 0, diff = 0; + + ENOFLAGS(argc); + + stream.file = "<stdin>"; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, "<stdin>"); + n = stream.width * stream.height * stream.pixel_size; + buf = ecalloc(1, n); + + fptr = 0; + do { + sptr = 0; + again: + while (same) { + m = same < n - fptr ? same : n - fptr; + ewriteall(STDOUT_FILENO, buf + fptr, m, "<stdout>"); + fptr = (fptr + m) % n; + same -= m; + } + + while (diff && sptr < stream.ptr) { + m = diff < n - fptr ? diff : n - fptr; + m = m < stream.ptr - sptr ? m : stream.ptr - sptr; + memcpy(buf + fptr, stream.buf + sptr, m); + ewriteall(STDOUT_FILENO, buf + fptr, m, "<stdout>"); + fptr = (fptr + m) % n; + diff -= m; + sptr += m; + } + + if (diff || sptr + 2 * sizeof(size_t) > stream.ptr) { + memmove(stream.buf, stream.buf + sptr, stream.ptr -= sptr); + } else { + same = ((size_t *)(stream.buf + sptr))[0]; + diff = ((size_t *)(stream.buf + sptr))[1]; + sptr += 2 * sizeof(size_t); + goto again; + } + } while (eread_stream(&stream, SIZE_MAX)); + + free(buf); + if (same || diff) + eprintf("<stdin>: corrupt input\n"); + return 0; +}