diff --git a/headers/private/package/hpkg/PackageFileHeapAccessorBase.h b/headers/private/package/hpkg/PackageFileHeapAccessorBase.h index 62817e2e01..904778c8f2 100644 --- a/headers/private/package/hpkg/PackageFileHeapAccessorBase.h +++ b/headers/private/package/hpkg/PackageFileHeapAccessorBase.h @@ -99,23 +99,23 @@ public: public: static const size_t kChunkSize = 64 * 1024; #if defined(_KERNEL_MODE) - static void* sChunkCache; + static void* sQuadChunkCache; #endif protected: virtual status_t ReadAndDecompressChunk(size_t chunkIndex, void* compressedDataBuffer, - void* uncompressedDataBuffer) = 0; + void* uncompressedDataBuffer, + iovec* scratchBuffer = NULL) = 0; status_t ReadAndDecompressChunkData(uint64 offset, size_t compressedSize, size_t uncompressedSize, void* compressedDataBuffer, - void* uncompressedDataBuffer); - status_t DecompressChunkData( - void* compressedDataBuffer, - size_t compressedSize, void* uncompressedDataBuffer, - size_t uncompressedSize); + iovec* scratchBuffer = NULL); + status_t DecompressChunkData(const iovec& compressedBuffer, + iovec& uncompressedBuffer, + iovec* scratchBuffer = NULL); status_t ReadFileData(uint64 offset, void* buffer, size_t size); diff --git a/headers/private/package/hpkg/PackageFileHeapReader.h b/headers/private/package/hpkg/PackageFileHeapReader.h index 00206eff3d..650af43096 100644 --- a/headers/private/package/hpkg/PackageFileHeapReader.h +++ b/headers/private/package/hpkg/PackageFileHeapReader.h @@ -42,7 +42,8 @@ public: protected: virtual status_t ReadAndDecompressChunk(size_t chunkIndex, void* compressedDataBuffer, - void* uncompressedDataBuffer); + void* uncompressedDataBuffer, + iovec* scratchBuffer = NULL); private: OffsetArray fOffsets; diff --git a/headers/private/package/hpkg/PackageFileHeapWriter.h b/headers/private/package/hpkg/PackageFileHeapWriter.h index 49588f1686..0bc8fbd051 100644 --- a/headers/private/package/hpkg/PackageFileHeapWriter.h +++ b/headers/private/package/hpkg/PackageFileHeapWriter.h @@ -57,7 +57,8 @@ public: protected: virtual status_t ReadAndDecompressChunk(size_t chunkIndex, void* compressedDataBuffer, - void* uncompressedDataBuffer); + void* uncompressedDataBuffer, + iovec* scratchBuffer = NULL); private: struct Chunk; diff --git a/headers/private/support/CompressionAlgorithm.h b/headers/private/support/CompressionAlgorithm.h index f2ca69c74d..fdd5a98937 100644 --- a/headers/private/support/CompressionAlgorithm.h +++ b/headers/private/support/CompressionAlgorithm.h @@ -7,6 +7,7 @@ #include +#include class BCompressionParameters { @@ -41,17 +42,12 @@ public: const BDecompressionParameters* parameters, BDataIO*& _stream); - virtual status_t CompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters - = NULL); - virtual status_t DecompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, - size_t& _uncompressedSize, - const BDecompressionParameters* parameters - = NULL); + virtual status_t CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters = NULL, + iovec* scratch = NULL); + virtual status_t DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters = NULL, + iovec* scratch = NULL); protected: class BAbstractStream; diff --git a/headers/private/support/ZlibCompressionAlgorithm.h b/headers/private/support/ZlibCompressionAlgorithm.h index df9ddae54f..f99407bc13 100644 --- a/headers/private/support/ZlibCompressionAlgorithm.h +++ b/headers/private/support/ZlibCompressionAlgorithm.h @@ -73,17 +73,12 @@ public: const BDecompressionParameters* parameters, BDataIO*& _stream); - virtual status_t CompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters - = NULL); - virtual status_t DecompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, - size_t& _uncompressedSize, - const BDecompressionParameters* parameters - = NULL); + virtual status_t CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters = NULL, + iovec* scratch = NULL); + virtual status_t DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters = NULL, + iovec* scratch = NULL); private: struct CompressionStrategy; diff --git a/headers/private/support/ZstdCompressionAlgorithm.h b/headers/private/support/ZstdCompressionAlgorithm.h index 207462188f..c43a442acc 100644 --- a/headers/private/support/ZstdCompressionAlgorithm.h +++ b/headers/private/support/ZstdCompressionAlgorithm.h @@ -69,17 +69,12 @@ public: const BDecompressionParameters* parameters, BDataIO*& _stream); - virtual status_t CompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters - = NULL); - virtual status_t DecompressBuffer(const void* input, - size_t inputSize, void* output, - size_t outputSize, - size_t& _uncompressedSize, - const BDecompressionParameters* parameters - = NULL); + virtual status_t CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters = NULL, + iovec* scratch = NULL); + virtual status_t DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters = NULL, + iovec* scratch = NULL); private: struct CompressionStrategy; diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 7122663e2b..bfff8a7dcf 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -12,7 +12,7 @@ if [ FIsBuildFeatureEnabled zstd ] { UseBuildFeatureHeaders zstd ; Includes [ FGristFiles $(zstdSources) ] : [ BuildFeatureAttribute zstd : headers ] ; - SubDirC++Flags -DZSTD_ENABLED ; + SubDirC++Flags -DZSTD_ENABLED -DZSTD_STATIC_LINKING_ONLY ; } local subDirs = diff --git a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp index 124bc937ed..8c50f5644e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp @@ -1144,11 +1144,13 @@ packagefs_std_ops(int32 op, ...) return error; } - PackageFileHeapAccessorBase::sChunkCache = - create_object_cache_etc("pkgfs heap buffers", - PackageFileHeapAccessorBase::kChunkSize, sizeof(void*), - 0, /* magazine capacity, count */ 2, 1, - 0, NULL, NULL, NULL, NULL); + object_cache* quadChunkCache; + PackageFileHeapAccessorBase::sQuadChunkCache = quadChunkCache = + create_object_cache("pkgfs heap buffers", + PackageFileHeapAccessorBase::kChunkSize * 4, + 0, NULL, NULL, NULL); + object_cache_set_minimum_reserve(quadChunkCache, 1); + TwoKeyAVLTreeNode::sNodeCache = create_object_cache_etc("pkgfs TKAVLTreeNodes", sizeof(TwoKeyAVLTreeNode), 8, @@ -1172,7 +1174,7 @@ packagefs_std_ops(int32 op, ...) PackageFSRoot::GlobalUninit(); delete_object_cache(TwoKeyAVLTreeNode::sNodeCache); delete_object_cache((object_cache*) - PackageFileHeapAccessorBase::sChunkCache); + PackageFileHeapAccessorBase::sQuadChunkCache); StringConstants::Cleanup(); StringPool::Cleanup(); exit_debugging(); diff --git a/src/kits/package/hpkg/PackageFileHeapAccessorBase.cpp b/src/kits/package/hpkg/PackageFileHeapAccessorBase.cpp index 46c091d056..e0c6d3f6bd 100644 --- a/src/kits/package/hpkg/PackageFileHeapAccessorBase.cpp +++ b/src/kits/package/hpkg/PackageFileHeapAccessorBase.cpp @@ -31,7 +31,7 @@ namespace BPrivate { #if defined(_KERNEL_MODE) -void* PackageFileHeapAccessorBase::sChunkCache = NULL; +void* PackageFileHeapAccessorBase::sQuadChunkCache = NULL; #endif @@ -218,7 +218,7 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size, // allocate buffers for compressed and uncompressed data uint16* compressedDataBuffer, *uncompressedDataBuffer; - MemoryDeleter compressedMemoryDeleter, uncompressedMemoryDeleter; + iovec* scratch = NULL; #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) struct ObjectCacheDeleter { @@ -238,21 +238,24 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size, } }; - ObjectCacheDeleter compressedCacheDeleter((object_cache*)sChunkCache), - uncompressedCacheDeleter((object_cache*)sChunkCache); - if (sChunkCache != NULL) { - compressedDataBuffer = (uint16*)object_cache_alloc((object_cache*)sChunkCache, 0); - uncompressedDataBuffer = (uint16*)object_cache_alloc((object_cache*)sChunkCache, 0); - compressedCacheDeleter.object = compressedDataBuffer; - uncompressedCacheDeleter.object = uncompressedDataBuffer; - } else + ObjectCacheDeleter chunkBufferDeleter((object_cache*)sQuadChunkCache); + uint8* quadChunkBuffer = (uint8*)object_cache_alloc((object_cache*)sQuadChunkCache, 0); + chunkBufferDeleter.object = quadChunkBuffer; + + // segment data buffer + iovec localScratch; + compressedDataBuffer = (uint16*)(quadChunkBuffer + 0); + uncompressedDataBuffer = (uint16*)(quadChunkBuffer + kChunkSize); + localScratch.iov_base = (quadChunkBuffer + (kChunkSize * 2)); + localScratch.iov_len = kChunkSize * 2; + scratch = &localScratch; +#else + MemoryDeleter compressedMemoryDeleter, uncompressedMemoryDeleter; + compressedDataBuffer = (uint16*)malloc(kChunkSize); + uncompressedDataBuffer = (uint16*)malloc(kChunkSize); + compressedMemoryDeleter.SetTo(compressedDataBuffer); + uncompressedMemoryDeleter.SetTo(uncompressedDataBuffer); #endif - { - compressedDataBuffer = (uint16*)malloc(kChunkSize); - uncompressedDataBuffer = (uint16*)malloc(kChunkSize); - compressedMemoryDeleter.SetTo(compressedDataBuffer); - uncompressedMemoryDeleter.SetTo(uncompressedDataBuffer); - } if (compressedDataBuffer == NULL || uncompressedDataBuffer == NULL) return B_NO_MEMORY; @@ -264,7 +267,7 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size, while (remainingBytes > 0) { status_t error = ReadAndDecompressChunk(chunkIndex, - compressedDataBuffer, uncompressedDataBuffer); + compressedDataBuffer, uncompressedDataBuffer, scratch); if (error != B_OK) return error; @@ -289,8 +292,9 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size, status_t PackageFileHeapAccessorBase::ReadAndDecompressChunkData(uint64 offset, - size_t compressedSize, size_t uncompressedSize, void* compressedDataBuffer, - void* uncompressedDataBuffer) + size_t compressedSize, size_t uncompressedSize, + void* compressedDataBuffer, void* uncompressedDataBuffer, + iovec* scratchBuffer) { // if uncompressed, read directly into the uncompressed data buffer if (compressedSize == uncompressedSize) @@ -301,27 +305,26 @@ PackageFileHeapAccessorBase::ReadAndDecompressChunkData(uint64 offset, if (error != B_OK) return error; - return DecompressChunkData(compressedDataBuffer, compressedSize, - uncompressedDataBuffer, uncompressedSize); + iovec compressed = { compressedDataBuffer, compressedSize }, + uncompressed = { uncompressedDataBuffer, uncompressedSize }; + return DecompressChunkData(compressed, uncompressed, scratchBuffer); } status_t -PackageFileHeapAccessorBase::DecompressChunkData(void* compressedDataBuffer, - size_t compressedSize, void* uncompressedDataBuffer, - size_t uncompressedSize) +PackageFileHeapAccessorBase::DecompressChunkData(const iovec& compressed, + iovec& uncompressed, iovec* scratchBuffer) { - size_t actualSize; + const size_t uncompressedSize = uncompressed.iov_len; status_t error = fDecompressionAlgorithm->algorithm->DecompressBuffer( - compressedDataBuffer, compressedSize, uncompressedDataBuffer, - uncompressedSize, actualSize, fDecompressionAlgorithm->parameters); + compressed, uncompressed, fDecompressionAlgorithm->parameters, scratchBuffer); if (error != B_OK) { fErrorOutput->PrintError("Failed to decompress chunk data: %s\n", strerror(error)); return error; } - if (actualSize != uncompressedSize) { + if (uncompressed.iov_len != uncompressedSize) { fErrorOutput->PrintError("Failed to decompress chunk data: size " "mismatch\n"); return B_ERROR; diff --git a/src/kits/package/hpkg/PackageFileHeapReader.cpp b/src/kits/package/hpkg/PackageFileHeapReader.cpp index 796e51e1a4..5bbeeb0ff7 100644 --- a/src/kits/package/hpkg/PackageFileHeapReader.cpp +++ b/src/kits/package/hpkg/PackageFileHeapReader.cpp @@ -153,7 +153,8 @@ PackageFileHeapReader::Clone() const status_t PackageFileHeapReader::ReadAndDecompressChunk(size_t chunkIndex, - void* compressedDataBuffer, void* uncompressedDataBuffer) + void* compressedDataBuffer, void* uncompressedDataBuffer, + iovec* scratchBuffer) { uint64 offset = fOffsets[chunkIndex]; bool isLastChunk @@ -166,7 +167,7 @@ PackageFileHeapReader::ReadAndDecompressChunk(size_t chunkIndex, : kChunkSize; return ReadAndDecompressChunkData(offset, compressedSize, uncompressedSize, - compressedDataBuffer, uncompressedDataBuffer); + compressedDataBuffer, uncompressedDataBuffer, scratchBuffer); } diff --git a/src/kits/package/hpkg/PackageFileHeapWriter.cpp b/src/kits/package/hpkg/PackageFileHeapWriter.cpp index a86510784c..e5ac8991c3 100644 --- a/src/kits/package/hpkg/PackageFileHeapWriter.cpp +++ b/src/kits/package/hpkg/PackageFileHeapWriter.cpp @@ -409,9 +409,9 @@ PackageFileHeapWriter::RemoveDataRanges( } else if (decompressedChunk == &chunk) { uncompressedData = decompressionBuffer; } else { - status_t error = DecompressChunkData(chunk.buffer, - chunk.compressedSize, decompressionBuffer, - chunk.uncompressedSize); + iovec compressed = { chunk.buffer, chunk.compressedSize }, + uncompressed = { decompressionBuffer, chunk.uncompressedSize }; + status_t error = DecompressChunkData(compressed, uncompressed); if (error != B_OK) throw error; @@ -479,7 +479,8 @@ PackageFileHeapWriter::Finish() status_t PackageFileHeapWriter::ReadAndDecompressChunk(size_t chunkIndex, - void* compressedDataBuffer, void* uncompressedDataBuffer) + void* compressedDataBuffer, void* uncompressedDataBuffer, + iovec* scratchBuffer) { if (uint64(chunkIndex + 1) * kChunkSize > fUncompressedHeapSize) { // The chunk has not been written to disk yet. Its data are still in the @@ -496,7 +497,7 @@ PackageFileHeapWriter::ReadAndDecompressChunk(size_t chunkIndex, : fOffsets[chunkIndex + 1] - offset; return ReadAndDecompressChunkData(offset, compressedSize, kChunkSize, - compressedDataBuffer, uncompressedDataBuffer); + compressedDataBuffer, uncompressedDataBuffer, scratchBuffer); } @@ -562,9 +563,10 @@ PackageFileHeapWriter::_WriteDataCompressed(const void* data, size_t size) if (fCompressionAlgorithm == NULL) return B_BUFFER_OVERFLOW; - size_t compressedSize; - status_t error = fCompressionAlgorithm->algorithm->CompressBuffer(data, - size, fCompressedDataBuffer, size, compressedSize, + const iovec uncompressed = { (void*)data, size }; + iovec compressed = { fCompressedDataBuffer, size }; + status_t error = fCompressionAlgorithm->algorithm->CompressBuffer( + uncompressed, compressed, fCompressionAlgorithm->parameters); if (error != B_OK) { if (error != B_BUFFER_OVERFLOW) { @@ -575,10 +577,10 @@ PackageFileHeapWriter::_WriteDataCompressed(const void* data, size_t size) } // only use compressed data when we've actually saved space - if (compressedSize == size) + if (compressed.iov_len == size) return B_BUFFER_OVERFLOW; - return _WriteDataUncompressed(fCompressedDataBuffer, compressedSize); + return _WriteDataUncompressed(fCompressedDataBuffer, compressed.iov_len); } diff --git a/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp b/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp index 8b21446b5c..63d1bd6f42 100644 --- a/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp +++ b/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp @@ -293,12 +293,11 @@ private: if (error != B_OK) return error; - size_t actuallyUncompressedSize; - BZlibCompressionAlgorithm().DecompressBuffer( - readBuffer->Buffer(), compressedSize, - fUncompressBuffer->Buffer(), uncompressedSize, - actuallyUncompressedSize); - if (error == B_OK && actuallyUncompressedSize != uncompressedSize) + iovec compressed = { readBuffer->Buffer(), compressedSize }, + uncompressed = { fUncompressBuffer->Buffer(), uncompressedSize }; + error = BZlibCompressionAlgorithm().DecompressBuffer( + compressed, uncompressed); + if (error == B_OK && uncompressed.iov_len != uncompressedSize) error = B_BAD_DATA; } diff --git a/src/kits/support/CompressionAlgorithm.cpp b/src/kits/support/CompressionAlgorithm.cpp index ab7eb2cfff..e10d5e4e6a 100644 --- a/src/kits/support/CompressionAlgorithm.cpp +++ b/src/kits/support/CompressionAlgorithm.cpp @@ -84,18 +84,16 @@ BCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output, status_t -BCompressionAlgorithm::CompressBuffer(const void* input, size_t inputSize, - void* output, size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters) +BCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters, iovec* scratch) { return B_NOT_SUPPORTED; } status_t -BCompressionAlgorithm::DecompressBuffer(const void* input, - size_t inputSize, void* output, size_t outputSize, - size_t& _uncompressedSize, const BDecompressionParameters* parameters) +BCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters, iovec* scratch) { return B_NOT_SUPPORTED; } diff --git a/src/kits/support/ZlibCompressionAlgorithm.cpp b/src/kits/support/ZlibCompressionAlgorithm.cpp index f49a781a25..05694e9348 100644 --- a/src/kits/support/ZlibCompressionAlgorithm.cpp +++ b/src/kits/support/ZlibCompressionAlgorithm.cpp @@ -366,9 +366,8 @@ BZlibCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output, status_t -BZlibCompressionAlgorithm::CompressBuffer(const void* input, - size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters) +BZlibCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters, iovec* scratch) { #ifdef B_ZLIB_COMPRESSION_SUPPORT const BZlibCompressionParameters* zlibParameters @@ -377,13 +376,13 @@ BZlibCompressionAlgorithm::CompressBuffer(const void* input, ? zlibParameters->CompressionLevel() : B_ZLIB_COMPRESSION_DEFAULT; - uLongf bytesUsed = outputSize; - int zlibError = compress2((Bytef*)output, &bytesUsed, (const Bytef*)input, - (uLong)inputSize, compressionLevel); + uLongf bytesUsed = output.iov_len; + int zlibError = compress2((Bytef*)output.iov_base, &bytesUsed, + (const Bytef*)input.iov_base, (uLong)input.iov_len, compressionLevel); if (zlibError != Z_OK) return _TranslateZlibError(zlibError); - _compressedSize = (size_t)bytesUsed; + output.iov_len = (size_t)bytesUsed; return B_OK; #else return B_NOT_SUPPORTED; @@ -392,17 +391,16 @@ BZlibCompressionAlgorithm::CompressBuffer(const void* input, status_t -BZlibCompressionAlgorithm::DecompressBuffer(const void* input, - size_t inputSize, void* output, size_t outputSize, - size_t& _uncompressedSize, const BDecompressionParameters* parameters) +BZlibCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters, iovec* scratch) { - uLongf bytesUsed = outputSize; - int zlibError = uncompress((Bytef*)output, &bytesUsed, (const Bytef*)input, - (uLong)inputSize); + uLongf bytesUsed = output.iov_len; + int zlibError = uncompress((Bytef*)output.iov_base, &bytesUsed, + (const Bytef*)input.iov_base, (uLong)input.iov_len); if (zlibError != Z_OK) return _TranslateZlibError(zlibError); - _uncompressedSize = (size_t)bytesUsed; + output.iov_len = (size_t)bytesUsed; return B_OK; } diff --git a/src/kits/support/ZstdCompressionAlgorithm.cpp b/src/kits/support/ZstdCompressionAlgorithm.cpp index 5b6a1a2245..e3f3ee0312 100644 --- a/src/kits/support/ZstdCompressionAlgorithm.cpp +++ b/src/kits/support/ZstdCompressionAlgorithm.cpp @@ -18,6 +18,7 @@ #include #endif +#include #include @@ -367,23 +368,23 @@ BZstdCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output, status_t -BZstdCompressionAlgorithm::CompressBuffer(const void* input, - size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize, - const BCompressionParameters* parameters) +BZstdCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output, + const BCompressionParameters* parameters, iovec* scratch) { #ifdef B_ZSTD_COMPRESSION_SUPPORT + // TODO: Make use of scratch buffer (if available.) const BZstdCompressionParameters* zstdParameters = dynamic_cast(parameters); int compressionLevel = zstdParameters != NULL ? zstdParameters->CompressionLevel() : B_ZSTD_COMPRESSION_DEFAULT; - size_t zstdError = ZSTD_compress(output, outputSize, input, - inputSize, compressionLevel); + size_t zstdError = ZSTD_compress(output.iov_base, output.iov_len, + input.iov_base, input.iov_len, compressionLevel); if (ZSTD_isError(zstdError)) return _TranslateZstdError(zstdError); - _compressedSize = zstdError; + output.iov_len = zstdError; return B_OK; #else return B_NOT_SUPPORTED; @@ -392,17 +393,26 @@ BZstdCompressionAlgorithm::CompressBuffer(const void* input, status_t -BZstdCompressionAlgorithm::DecompressBuffer(const void* input, - size_t inputSize, void* output, size_t outputSize, - size_t& _uncompressedSize, const BDecompressionParameters* parameters) +BZstdCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output, + const BDecompressionParameters* parameters, iovec* scratch) { #ifdef ZSTD_ENABLED - size_t zstdError = ZSTD_decompress(output, outputSize, input, - inputSize); + ZSTD_DCtx* dctx; + CObjectDeleter dctxDeleter; +#if defined(ZSTD_STATIC_LINKING_ONLY) + if (scratch != NULL) + dctx = ZSTD_initStaticDCtx(scratch->iov_base, scratch->iov_len); + else +#endif + dctxDeleter.SetTo(dctx = ZSTD_createDCtx()); + + size_t zstdError = ZSTD_decompressDCtx(dctx, + output.iov_base, output.iov_len, + input.iov_base, input.iov_len); if (ZSTD_isError(zstdError)) return _TranslateZstdError(zstdError); - _uncompressedSize = zstdError; + output.iov_len = zstdError; return B_OK; #else return B_NOT_SUPPORTED;