diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-03-14 21:41:53 +1100 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-03-14 21:41:53 +1100 |
commit | 662b83ff92cc2316fb962ff1608359f6d705a5f0 (patch) | |
tree | d0e7d15887ed14bd252e6e61888710c8bac2200a /source/core/StarZSTDCompression.cpp | |
parent | 8164e5ae6fa33c9ec2a14f107585a7cbe7fbf813 (diff) |
Initial commit of experimental zstd network compression
currently a bit buggy
Diffstat (limited to 'source/core/StarZSTDCompression.cpp')
-rw-r--r-- | source/core/StarZSTDCompression.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/source/core/StarZSTDCompression.cpp b/source/core/StarZSTDCompression.cpp new file mode 100644 index 0000000..733b182 --- /dev/null +++ b/source/core/StarZSTDCompression.cpp @@ -0,0 +1,84 @@ +#include "StarZSTDCompression.hpp" +#include <zstd.h> + +namespace Star { + +CompressionStream::CompressionStream() : m_cStream(ZSTD_createCStream()) { + ZSTD_CCtx_setParameter(m_cStream, ZSTD_c_enableLongDistanceMatching, 1); + ZSTD_CCtx_setParameter(m_cStream, ZSTD_c_windowLog, 24); + ZSTD_initCStream(m_cStream, 2); +} + +CompressionStream::~CompressionStream() { ZSTD_freeCStream(m_cStream); } + +ByteArray CompressionStream::compress(const char* in, size_t inLen) { + size_t const cInSize = ZSTD_CStreamInSize (); + size_t const cOutSize = ZSTD_CStreamOutSize(); + ByteArray output(cOutSize, 0); + size_t written = 0, read = 0; + while (read < inLen) { + ZSTD_inBuffer inBuffer = {in + read, min(cInSize, inLen - read), 0}; + ZSTD_outBuffer outBuffer = {output.ptr() + written, output.size() - written, 0}; + bool finished = false; + do { + size_t ret = ZSTD_compressStream2(m_cStream, &outBuffer, &inBuffer, ZSTD_e_flush); + if (ZSTD_isError(ret)) { + throw IOException(strf("ZSTD compression error {}", ZSTD_getErrorName(ret))); + break; + } + + if (outBuffer.pos == outBuffer.size) { + output.resize(output.size() * 2); + outBuffer.dst = output.ptr(); + outBuffer.size = output.size(); + continue; + } + + finished = ret == 0 && inBuffer.pos == inBuffer.size; + } while (!finished); + + read += inBuffer.pos; + written += outBuffer.pos; + } + output.resize(written); + return output; +} + +DecompressionStream::DecompressionStream() : m_dStream(ZSTD_createDStream()) { + ZSTD_DCtx_setParameter(m_dStream, ZSTD_d_windowLogMax, 25); + ZSTD_initDStream(m_dStream); +} + +DecompressionStream::~DecompressionStream() { ZSTD_freeDStream(m_dStream); } + +ByteArray DecompressionStream::decompress(const char* in, size_t inLen) { + size_t const dInSize = ZSTD_DStreamInSize (); + size_t const dOutSize = ZSTD_DStreamOutSize(); + ByteArray output(dOutSize, 0); + size_t written = 0, read = 0; + while (read < inLen) { + ZSTD_inBuffer inBuffer = {in + read, min(dInSize, inLen - read), 0}; + ZSTD_outBuffer outBuffer = {output.ptr() + written, output.size() - written, 0}; + do { + size_t ret = ZSTD_decompressStream(m_dStream, &outBuffer, &inBuffer); + if (ZSTD_isError(ret)) { + throw IOException(strf("ZSTD decompression error {}", ZSTD_getErrorName(ret))); + break; + } + + if (outBuffer.pos == outBuffer.size) { + output.resize(output.size() * 2); + outBuffer.dst = output.ptr(); + outBuffer.size = output.size(); + continue; + } + } while (inBuffer.pos < inBuffer.size); + + read += inBuffer.pos; + written += outBuffer.pos; + } + output.resize(written); + return output; +} + +}
\ No newline at end of file |