static void write_zstd(int f, int fd, const char *arg) { ZSTD_inBuffer zin; ZSTD_outBuffer zout; size_t const inbufsz = ZSTD_CStreamInSize(); zin.src = malloc(inbufsz); zout.size = ZSTD_CStreamOutSize(); zout.dst = malloc(zout.size); if (!zin.src || !zout.dst) goto zstd_w_no_stream; ZSTD_CStream* const stream = ZSTD_createCStream(); if (!stream) goto zstd_w_no_stream; if (ZSTD_isError(ZSTD_initCStream(stream, 3))) goto zstd_w_error; size_t s; while ((s = read(fd, (void*)zin.src, inbufsz)) > 0) { zin.size = s; zin.pos = 0; while (zin.pos < zin.size) { zout.pos = 0; size_t w = ZSTD_compressStream(stream, &zout, &zin); if (ZSTD_isError(w)) goto zstd_w_error; if (write(f, zout.dst, zout.pos) != (ssize_t)zout.pos) goto zstd_w_error; } } zout.pos = 0; ZSTD_endStream(stream, &zout); // no way to handle an error here write(f, zout.dst, zout.pos); zstd_w_error: ZSTD_freeCStream(stream); zstd_w_no_stream: free((void*)zin.src); free(zout.dst); close(f); close(fd); }
static void compressFile_orDie(const char* fname, const char* outName, int cLevel, unsigned frameSize) { FILE* const fin = fopen_orDie(fname, "rb"); FILE* const fout = fopen_orDie(outName, "wb"); size_t const buffInSize = ZSTD_CStreamInSize(); /* can always read one full block */ void* const buffIn = malloc_orDie(buffInSize); size_t const buffOutSize = ZSTD_CStreamOutSize(); /* can always flush a full block */ void* const buffOut = malloc_orDie(buffOutSize); ZSTD_seekable_CStream* const cstream = ZSTD_seekable_createCStream(); if (cstream==NULL) { fprintf(stderr, "ZSTD_seekable_createCStream() error \n"); exit(10); } size_t const initResult = ZSTD_seekable_initCStream(cstream, cLevel, 1, frameSize); if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_seekable_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); } size_t read, toRead = buffInSize; while( (read = fread_orDie(buffIn, toRead, fin)) ) { ZSTD_inBuffer input = { buffIn, read, 0 }; while (input.pos < input.size) { ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; toRead = ZSTD_seekable_compressStream(cstream, &output , &input); /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */ if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_seekable_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); } if (toRead > buffInSize) toRead = buffInSize; /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/ fwrite_orDie(buffOut, output.pos, fout); } } while (1) { ZSTD_outBuffer output = { buffOut, buffOutSize, 0 }; size_t const remainingToFlush = ZSTD_seekable_endStream(cstream, &output); /* close stream */ if (ZSTD_isError(remainingToFlush)) { fprintf(stderr, "ZSTD_seekable_endStream() error : %s \n", ZSTD_getErrorName(remainingToFlush)); exit(13); } fwrite_orDie(buffOut, output.pos, fout); if (!remainingToFlush) break; } ZSTD_seekable_freeCStream(cstream); fclose_orDie(fout); fclose_orDie(fin); free(buffIn); free(buffOut); }
ByteArray CompressFile(const FilePath& path, const int32 compressionLevel) { BinaryReader reader(path); if (!reader) { return ByteArray(); } const size_t inputBufferSize = ZSTD_CStreamInSize(); const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize); const size_t outputBufferSize = ZSTD_CStreamOutSize(); const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize); ZSTD_CStream* const cStream = ZSTD_createCStream(); if (!cStream) { return ByteArray(); } const size_t initResult = ZSTD_initCStream(cStream, compressionLevel); if (ZSTD_isError(initResult)) { ZSTD_freeCStream(cStream); return ByteArray(); } size_t toRead = inputBufferSize; 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_compressStream(cStream, &output, &input); if (ZSTD_isError(toRead)) { ZSTD_freeCStream(cStream); return ByteArray(); } if (toRead > inputBufferSize) { toRead = inputBufferSize; } buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos); } } ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 }; const size_t remainingToFlush = ZSTD_endStream(cStream, &output); ZSTD_freeCStream(cStream); if (remainingToFlush) { return ByteArray(); } buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos); return ByteArray(std::move(buffer)); }
bool CompressFileToFile(const FilePath& inputPath, const FilePath& outputPath, const int32 compressionLevel) { BinaryReader reader(inputPath); if (!reader) { return false; } const size_t inputBufferSize = ZSTD_CStreamInSize(); const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize); const size_t outputBufferSize = ZSTD_CStreamOutSize(); const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize); ZSTD_CStream* const cStream = ZSTD_createCStream(); if (!cStream) { return false; } const size_t initResult = ZSTD_initCStream(cStream, compressionLevel); if (ZSTD_isError(initResult)) { ZSTD_freeCStream(cStream); return false; } size_t toRead = inputBufferSize; BinaryWriter writer(outputPath); if (!writer) { ZSTD_freeCStream(cStream); 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_compressStream(cStream, &output, &input); if (ZSTD_isError(toRead)) { writer.clear(); ZSTD_freeCStream(cStream); return false; } if (toRead > inputBufferSize) { toRead = inputBufferSize; } writer.write(pOutputBuffer.get(), output.pos); } } ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 }; const size_t remainingToFlush = ZSTD_endStream(cStream, &output); ZSTD_freeCStream(cStream); if (remainingToFlush) { writer.clear(); return false; } writer.write(pOutputBuffer.get(), output.pos); return true; }
size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_CStreamOutSize(); }