ByteArray DecompressFile(const FilePath& path) { BinaryReader reader(path); if (!reader) { return ByteArray(); } const size_t inputBufferSize = ZSTD_DStreamInSize(); const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize); const size_t outputBufferSize = ZSTD_DStreamOutSize(); const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize); ZSTD_DStream* const dStream = ZSTD_createDStream(); if (!dStream) { return ByteArray(); } const size_t initResult = ZSTD_initDStream(dStream); if (ZSTD_isError(initResult)) { ZSTD_freeDStream(dStream); return ByteArray(); } size_t toRead = initResult; Array<Byte> buffer; while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead))) { ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 }; while (input.pos < input.size) { ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 }; toRead = ZSTD_decompressStream(dStream, &output, &input); if (ZSTD_isError(toRead)) { ZSTD_freeDStream(dStream); return ByteArray(); } buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos); } } ZSTD_freeDStream(dStream); return ByteArray(std::move(buffer)); }
static void read_zstd(int f, int fd, const char *arg) { ZSTD_inBuffer zin; ZSTD_outBuffer zout; size_t const inbufsz = ZSTD_DStreamInSize(); zin.src = malloc(inbufsz); zout.size = ZSTD_DStreamOutSize(); zout.dst = malloc(zout.size); if (!zin.src || !zout.dst) goto zstd_r_no_stream; ZSTD_DStream* const stream = ZSTD_createDStream(); if (!stream) goto zstd_r_no_stream; if (ZSTD_isError(ZSTD_initDStream(stream))) goto zstd_r_error; size_t s; while ((s = read(f, (void*)zin.src, inbufsz)) > 0) { zin.size = s; zin.pos = 0; while (zin.pos < zin.size) { zout.pos = 0; size_t w = ZSTD_decompressStream(stream, &zout, &zin); if (ZSTD_isError(w)) goto zstd_r_error; if (write(fd, zout.dst, zout.pos) != (ssize_t)zout.pos) goto zstd_r_error; } } zstd_r_error: ZSTD_freeDStream(stream); zstd_r_no_stream: free((void*)zin.src); free(zout.dst); close(f); close(fd); }
bool DecompressFileToFile(const FilePath& inputPath, const FilePath& outputPath) { BinaryReader reader(inputPath); if (!reader) { return false; } const size_t inputBufferSize = ZSTD_DStreamInSize(); const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize); const size_t outputBufferSize = ZSTD_DStreamOutSize(); const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize); ZSTD_DStream* const dStream = ZSTD_createDStream(); if (!dStream) { return false; } const size_t initResult = ZSTD_initDStream(dStream); if (ZSTD_isError(initResult)) { ZSTD_freeDStream(dStream); return false; } size_t toRead = initResult; BinaryWriter writer(outputPath); if (!writer) { ZSTD_freeDStream(dStream); return false; } while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead))) { ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 }; while (input.pos < input.size) { ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 }; toRead = ZSTD_decompressStream(dStream, &output, &input); if (ZSTD_isError(toRead)) { writer.clear(); ZSTD_freeDStream(dStream); return false; } writer.write(pOutputBuffer.get(), output.pos); } } ZSTD_freeDStream(dStream); return true; }
bool DecompressToFile(const ByteArrayView view, const FilePath& outputPath) { const size_t inputBufferSize = ZSTD_DStreamInSize(); const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize); const size_t outputBufferSize = ZSTD_DStreamOutSize(); const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize); ZSTD_DStream* const dStream = ZSTD_createDStream(); if (!dStream) { return false; } const size_t initResult = ZSTD_initDStream(dStream); if (ZSTD_isError(initResult)) { ZSTD_freeDStream(dStream); return false; } size_t toRead = initResult; BinaryWriter writer(outputPath); if (!writer) { ZSTD_freeDStream(dStream); return false; } ReaderView reader(view.data(), view.size()); for (;;) { const size_t read = std::min<size_t>(toRead, view.size() - static_cast<size_t>(reader.getPos())); if (read == 0) { break; } reader.read(pInputBuffer.get(), read); ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 }; while (input.pos < input.size) { ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 }; toRead = ZSTD_decompressStream(dStream, &output, &input); if (ZSTD_isError(toRead)) { writer.clear(); ZSTD_freeDStream(dStream); return false; } writer.write(pOutputBuffer.get(), output.pos); } } ZSTD_freeDStream(dStream); return true; }