diff --git a/addon/compress.h b/addon/compress.h new file mode 100644 index 0000000..a5548a1 --- /dev/null +++ b/addon/compress.h @@ -0,0 +1,25 @@ + +#include + +#include + +#include "zstd.h" + +using namespace Napi; + +CompressionResult compress(const std::vector data, size_t compression_level) { + size_t output_buffer_size = ZSTD_compressBound(data.size()); + std::vector output(output_buffer_size); + + size_t result_code = + ZSTD_compress(output.data(), output.size(), data.data(), data.size(), compression_level); + + if (ZSTD_isError(result_code)) { + std::string error(ZSTD_getErrorName(result_code)); + return CompressionResult::Error(error); + } + + output.resize(result_code); + + return CompressionResult::Ok(output); +} diff --git a/addon/decompress.h b/addon/decompress.h new file mode 100644 index 0000000..c61718c --- /dev/null +++ b/addon/decompress.h @@ -0,0 +1,34 @@ +#include + +#include + +#include "zstd.h" + +using namespace Napi; + +CompressionResult decompress(const std::vector& compressed) { + std::vector decompressed; + + using DCTX_Deleter = void (*)(ZSTD_DCtx*); + + std::unique_ptr decompression_context(ZSTD_createDCtx(), + (DCTX_Deleter)ZSTD_freeDCtx); + + ZSTD_inBuffer input = {compressed.data(), compressed.size(), 0}; + + while (input.pos < input.size) { + std::vector chunk(ZSTD_DStreamOutSize()); + ZSTD_outBuffer output = {chunk.data(), chunk.size(), 0}; + size_t const ret = ZSTD_decompressStream(decompression_context.get(), &output, &input); + if (ZSTD_isError(ret)) { + std::string error(ZSTD_getErrorName(ret)); + return CompressionResult::Error(error); + } + + for (size_t i = 0; i < output.pos; ++i) { + decompressed.push_back(chunk[i]); + } + } + + return CompressionResult::Ok(decompressed); +}