aboutsummaryrefslogtreecommitdiff
path: root/lib/trace-cmd/trace-compress-zstd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/trace-cmd/trace-compress-zstd.c')
-rw-r--r--lib/trace-cmd/trace-compress-zstd.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/trace-cmd/trace-compress-zstd.c b/lib/trace-cmd/trace-compress-zstd.c
new file mode 100644
index 00000000..10ae7a4c
--- /dev/null
+++ b/lib/trace-cmd/trace-compress-zstd.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Copyright (C) 2022, Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
+ *
+ */
+#include <stdlib.h>
+#include <zstd.h>
+#include <errno.h>
+
+#include "trace-cmd-private.h"
+
+#define __ZSTD_NAME "zstd"
+#define __ZSTD_WEIGTH 5
+
+struct zstd_context {
+ ZSTD_CCtx *ctx_c;
+ ZSTD_DCtx *ctx_d;
+};
+
+static int zstd_compress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes)
+{
+ struct zstd_context *context = ctx;
+ size_t ret;
+
+ if (!ctx)
+ return -1;
+
+ ret = ZSTD_compress2(context->ctx_c, out, out_bytes, in, in_bytes);
+ if (ZSTD_isError(ret))
+ return -1;
+
+ return ret;
+}
+
+static int zstd_decompress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes)
+{
+ struct zstd_context *context = ctx;
+ size_t ret;
+
+ if (!ctx)
+ return -1;
+
+ ret = ZSTD_decompressDCtx(context->ctx_d, out, out_bytes, in, in_bytes);
+ if (ZSTD_isError(ret)) {
+ errno = -EINVAL;
+ return -1;
+ }
+
+ return ret;
+}
+
+static unsigned int zstd_compress_bound(void *ctx, unsigned int in_bytes)
+{
+ return ZSTD_compressBound(in_bytes);
+}
+
+static bool zstd_is_supported(const char *name, const char *version)
+{
+ if (!name)
+ return false;
+ if (strcmp(name, __ZSTD_NAME))
+ return false;
+
+ return true;
+}
+
+static void *new_zstd_context(void)
+{
+ struct zstd_context *context;
+ size_t r;
+
+ context = calloc(1, sizeof(*context));
+ if (!context)
+ return NULL;
+
+ context->ctx_c = ZSTD_createCCtx();
+ context->ctx_d = ZSTD_createDCtx();
+ if (!context->ctx_c || !context->ctx_d)
+ goto err;
+
+ r = ZSTD_CCtx_setParameter(context->ctx_c, ZSTD_c_contentSizeFlag, 0);
+ if (ZSTD_isError(r))
+ goto err;
+
+ return context;
+err:
+ ZSTD_freeCCtx(context->ctx_c);
+ ZSTD_freeDCtx(context->ctx_d);
+ free(context);
+ return NULL;
+}
+static void free_zstd_context(void *ctx)
+{
+ struct zstd_context *context = ctx;
+
+ if (!ctx)
+ return;
+
+ ZSTD_freeCCtx(context->ctx_c);
+ ZSTD_freeDCtx(context->ctx_d);
+ free(context);
+}
+
+int tracecmd_zstd_init(void)
+{
+ struct tracecmd_compression_proto proto;
+
+ memset(&proto, 0, sizeof(proto));
+ proto.name = __ZSTD_NAME;
+ proto.version = ZSTD_versionString();
+ proto.weight = __ZSTD_WEIGTH;
+ proto.compress = zstd_compress;
+ proto.uncompress = zstd_decompress;
+ proto.is_supported = zstd_is_supported;
+ proto.compress_size = zstd_compress_bound;
+ proto.new_context = new_zstd_context;
+ proto.free_context = free_zstd_context;
+
+ return tracecmd_compress_proto_register(&proto);
+}