diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-09-14 20:25:10 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-09-16 09:34:35 +0200 |
commit | 15431d4fd8de67a03af4ee9cc8e774e1750e9da2 (patch) | |
tree | f5386db24f3901e86d3aaae10042d4f9181a6b32 /lib/fstream/compress/zstd.c | |
parent | 76b06f71078e2eea7def3d1c15cdb103dec785ed (diff) |
Add zstd stream compressor implementation to libfstream
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/fstream/compress/zstd.c')
-rw-r--r-- | lib/fstream/compress/zstd.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/lib/fstream/compress/zstd.c b/lib/fstream/compress/zstd.c new file mode 100644 index 0000000..f4f7f86 --- /dev/null +++ b/lib/fstream/compress/zstd.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * zstd.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +#include <zstd.h> + +typedef struct { + ostream_comp_t base; + + ZSTD_CStream *strm; +} ostream_zstd_t; + +static int flush_inbuf(ostream_comp_t *base, bool finish) +{ + ostream_zstd_t *zstd = (ostream_zstd_t *)base; + ZSTD_EndDirective op; + ZSTD_outBuffer out; + ZSTD_inBuffer in; + size_t ret; + + op = finish ? ZSTD_e_end : ZSTD_e_continue; + + do { + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + + in.src = base->inbuf; + in.size = base->inbuf_used; + + out.dst = base->outbuf; + out.size = BUFSZ; + + ret = ZSTD_compressStream2(zstd->strm, &out, &in, op); + + if (ZSTD_isError(ret)) { + fprintf(stderr, "%s: error in zstd compressor.\n", + base->wrapped->get_filename(base->wrapped)); + return -1; + } + + if (base->wrapped->append(base->wrapped, base->outbuf, + out.pos)) { + return -1; + } + + if (in.pos < in.size) { + base->inbuf_used = in.size - in.pos; + + memmove(base->inbuf, base->inbuf + in.pos, + base->inbuf_used); + } else { + base->inbuf_used = 0; + } + } while (finish && ret != 0); + + return 0; +} + +static void cleanup(ostream_comp_t *base) +{ + ostream_zstd_t *zstd = (ostream_zstd_t *)base; + + ZSTD_freeCStream(zstd->strm); +} + +ostream_comp_t *ostream_zstd_create(const char *filename) +{ + ostream_zstd_t *zstd = calloc(1, sizeof(*zstd)); + ostream_comp_t *base = (ostream_comp_t *)zstd; + + if (zstd == NULL) { + fprintf(stderr, "%s: creating zstd wrapper: %s.\n", + filename, strerror(errno)); + return NULL; + } + + zstd->strm = ZSTD_createCStream(); + if (zstd->strm == NULL) { + fprintf(stderr, "%s: error creating zstd decoder.\n", + filename); + free(zstd); + return NULL; + } + + base->flush_inbuf = flush_inbuf; + base->cleanup = cleanup; + return base; +} |