From cdccc69c62579b0c13b35fad0728079652b8f3c9 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 31 Jan 2023 11:21:30 +0100 Subject: Move library source into src sub-directory Signed-off-by: David Oberhollenzer --- lib/xfrm/src/zstd.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 lib/xfrm/src/zstd.c (limited to 'lib/xfrm/src/zstd.c') diff --git a/lib/xfrm/src/zstd.c b/lib/xfrm/src/zstd.c new file mode 100644 index 0000000..70666c1 --- /dev/null +++ b/lib/xfrm/src/zstd.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * zstd.c + * + * Copyright (C) 2021 David Oberhollenzer + */ +#include +#include +#include +#include + +#include "xfrm/stream.h" +#include "xfrm/compress.h" + +typedef struct { + xfrm_stream_t base; + + ZSTD_CStream *cstrm; + ZSTD_DStream *dstrm; + bool compress; +} xfrm_zstd_t; + +static const ZSTD_EndDirective zstd_action[] = { + [XFRM_STREAM_FLUSH_NONE] = ZSTD_e_continue, + [XFRM_STREAM_FLUSH_SYNC] = ZSTD_e_flush, + [XFRM_STREAM_FLUSH_FULL] = ZSTD_e_end, +}; + +static int process_data(xfrm_stream_t *stream, const void *in, + sqfs_u32 in_size, void *out, sqfs_u32 out_size, + sqfs_u32 *in_read, sqfs_u32 *out_written, + int flush_mode) +{ + xfrm_zstd_t *zstd = (xfrm_zstd_t *)stream; + ZSTD_outBuffer out_desc; + ZSTD_inBuffer in_desc; + size_t ret; + + if (flush_mode < 0 || flush_mode >= XFRM_STREAM_FLUSH_COUNT) + flush_mode = XFRM_STREAM_FLUSH_NONE; + + while (in_size > 0 && out_size > 0) { + memset(&in_desc, 0, sizeof(in_desc)); + in_desc.src = in; + in_desc.size = in_size; + + memset(&out_desc, 0, sizeof(out_desc)); + out_desc.dst = out; + out_desc.size = out_size; + + if (zstd->compress) { + ret = ZSTD_compressStream2(zstd->cstrm, &out_desc, + &in_desc, + zstd_action[flush_mode]); + } else { + ret = ZSTD_decompressStream(zstd->dstrm, &out_desc, + &in_desc); + } + + if (ZSTD_isError(ret)) + return XFRM_STREAM_ERROR; + + in = (const char *)in + in_desc.pos; + in_size -= in_desc.pos; + *in_read += in_desc.pos; + + out = (char *)out + out_desc.pos; + out_size -= out_desc.pos; + *out_written += out_desc.pos; + } + + if (flush_mode != XFRM_STREAM_FLUSH_NONE) { + if (in_size == 0) + return XFRM_STREAM_END; + } + + if (in_size > 0 && out_size == 0) + return XFRM_STREAM_BUFFER_FULL; + + return XFRM_STREAM_OK; +} + +static void destroy(sqfs_object_t *obj) +{ + xfrm_zstd_t *zstd = (xfrm_zstd_t *)obj; + + if (zstd->compress) { + ZSTD_freeCStream(zstd->cstrm); + } else { + ZSTD_freeDStream(zstd->dstrm); + } + + free(zstd); +} + +static xfrm_stream_t *stream_create(const compressor_config_t *cfg, + bool compress) +{ + xfrm_zstd_t *zstd = calloc(1, sizeof(*zstd)); + xfrm_stream_t *strm = (xfrm_stream_t *)zstd; + (void)cfg; + + if (zstd == NULL) { + perror("creating zstd stream compressor"); + return NULL; + } + + if (compress) { + zstd->cstrm = ZSTD_createCStream(); + if (zstd->cstrm == NULL) + goto fail_strm; + } else { + zstd->dstrm = ZSTD_createDStream(); + if (zstd->dstrm == NULL) + goto fail_strm; + } + + zstd->compress = compress; + strm->process_data = process_data; + sqfs_object_init(zstd, destroy, NULL); + return strm; +fail_strm: + fputs("error initializing zstd stream.\n", stderr); + free(zstd); + return NULL; +} + +xfrm_stream_t *compressor_stream_zstd_create(const compressor_config_t *cfg) +{ + return stream_create(cfg, true); +} + +xfrm_stream_t *decompressor_stream_zstd_create(void) +{ + return stream_create(NULL, false); +} -- cgit v1.2.3