/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuCompression.cpp Date: 2021-6-17 Author: Reece ***/ #include #include "AuCompression.hpp" #include "zstd.h" namespace Aurora::Compression { AUKN_SYM bool Compress(const AuMemoryViewRead &source, AuByteBuffer &out, int iCompressionLevel /* -7 to 22 */) { if (!out.GetOrAllocateLinearWriteable(AuMax(source.length, 20u))) { SysPushErrorMemory(); return {}; } auto uRet = ::ZSTD_compress(out.writePtr, out.length, source.ptr, source.length, iCompressionLevel); if (::ZSTD_isError(uRet)) { return false; } out.writePtr += uRet; if (!out.flagCircular && out.flagExpandable) { if (!AuTryDownsize(out, out.writePtr - out.base)) { SysPushErrorMemory(); return false; } } return true; } AUKN_SYM bool Decompress(const AuMemoryViewRead &source, AuByteBuffer &out) { AuUInt32 dwRead = 0; while (dwRead != source.length) { auto pBlockPointer = reinterpret_cast(source.ptr) + dwRead; auto uDeflatedLength = ZSTD_findFrameCompressedSize(pBlockPointer, source.length - dwRead); auto uInflatedLength = ZSTD_getFrameContentSize(pBlockPointer, source.length - dwRead); if (uDeflatedLength == ZSTD_CONTENTSIZE_ERROR) { return false; } if (uInflatedLength == ZSTD_CONTENTSIZE_UNKNOWN) { return false; } if (::ZSTD_isError(uInflatedLength)) { return false; } if (!out.GetOrAllocateLinearWriteable(uInflatedLength)) { SysPushErrorMemory(); return false; } auto uRet = ::ZSTD_decompress(out.writePtr, uInflatedLength, source.ptr, source.length); if (::ZSTD_isError(uRet)) { return false; } out.writePtr += uRet; dwRead += AuUInt32(uDeflatedLength); } return true; } }