unsigned long long FIOv07_decompressFrame(dRessv07_t ress, FILE* foutput, FILE* finput) { U64 frameSize = 0; size_t readSize = 4; MEM_writeLE32(ress.srcBuffer, ZSTDv07_MAGICNUMBER); ZBUFFv07_decompressInitDictionary(ress.dctx, ress.dictBuffer, ress.dictBufferSize); while (1) { /* Decode */ size_t inSize=readSize, decodedSize=ress.dstBufferSize; size_t toRead = ZBUFFv07_decompressContinue(ress.dctx, ress.dstBuffer, &decodedSize, ress.srcBuffer, &inSize); if (ZBUFFv07_isError(toRead)) EXM_THROW(36, "Decoding error : %s", ZBUFFv07_getErrorName(toRead)); readSize -= inSize; /* Write block */ { size_t const sizeCheck = fwrite(ress.dstBuffer, 1, decodedSize, foutput); if (sizeCheck != decodedSize) EXM_THROW(37, "Write error : unable to write data block to destination file"); } frameSize += decodedSize; DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)(frameSize>>20) ); if (toRead == 0) break; if (readSize) EXM_THROW(38, "Decoding error : should consume entire input"); /* Fill input buffer */ if (toRead > ress.srcBufferSize) EXM_THROW(34, "too large block"); readSize = fread(ress.srcBuffer, 1, toRead, finput); if (readSize != toRead) EXM_THROW(35, "Read error"); } return frameSize; }
unsigned long long FIOv01_decompressFrame(FILE* foutput, FILE* finput) { size_t const outBuffSize = 512 KB; BYTE* outBuff = (BYTE*)malloc(outBuffSize); size_t inBuffSize = 128 KB + 8; BYTE inBuff[128 KB + 8]; BYTE* op = outBuff; BYTE* const oend = outBuff + outBuffSize; U64 filesize = 0; size_t toRead; size_t sizeCheck; ZSTDv01_Dctx* dctx = ZSTDv01_createDCtx(); /* init */ if (outBuff==NULL) EXM_THROW(41, "Error : not enough memory to decode legacy frame"); /* restore header, already read from input */ MEM_writeLE32(inBuff, ZSTDv01_magicNumberLE); sizeCheck = ZSTDv01_decompressContinue(dctx, NULL, 0, inBuff, sizeof(ZSTDv01_magicNumberLE)); /* Decode frame header */ if (ZSTDv01_isError(sizeCheck)) EXM_THROW(42, "Error decoding legacy header"); /* Main decompression Loop */ toRead = ZSTDv01_nextSrcSizeToDecompress(dctx); while (toRead){ size_t readSize, decodedSize; /* Fill input buffer */ if (toRead > inBuffSize) EXM_THROW(43, "too large block"); readSize = fread(inBuff, 1, toRead, finput); if (readSize != toRead) EXM_THROW(44, "Read error"); /* Decode block */ decodedSize = ZSTDv01_decompressContinue(dctx, op, oend-op, inBuff, readSize); if (ZSTDv01_isError(decodedSize)) EXM_THROW(45, "Decoding error : input corrupted"); if (decodedSize) { /* not a header */ /* Write block */ sizeCheck = fwrite(op, 1, decodedSize, foutput); if (sizeCheck != decodedSize) EXM_THROW(46, "Write error : unable to write data block to destination file"); filesize += decodedSize; op += decodedSize; if (op==oend) op = outBuff; DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)(filesize>>20) ); } /* prepare for next Block */ toRead = ZSTDv01_nextSrcSizeToDecompress(dctx); } /* release resources */ free(outBuff); free(dctx); return filesize; }
/* ZSTDMT_flushNextJob() : * output : will be updated with amount of data flushed . * blockToFlush : if >0, the function will block and wait if there is no data available to flush . * @return : amount of data remaining within internal buffer, 1 if unknown but > 0, 0 if no more, or an error code */ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned blockToFlush) { unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask; if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */ PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex); while (zcs->jobs[wJobID].jobCompleted==0) { DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID); if (!blockToFlush) { pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */ pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */ } pthread_mutex_unlock(&zcs->jobCompleted_mutex); /* compression job completed : output can be flushed */ { ZSTDMT_jobDescription job = zcs->jobs[wJobID]; if (!job.jobScanned) { if (ZSTD_isError(job.cSize)) { DEBUGLOG(5, "compression error detected "); ZSTDMT_waitForAllJobsCompleted(zcs); ZSTDMT_releaseAllJobResources(zcs); return job.cSize; } ZSTDMT_releaseCCtx(zcs->cctxPool, job.cctx); zcs->jobs[wJobID].cctx = NULL; DEBUGLOG(5, "zcs->params.fParams.checksumFlag : %u ", zcs->params.fParams.checksumFlag); if (zcs->params.fParams.checksumFlag) { XXH64_update(&zcs->xxhState, (const char*)job.srcStart + job.dictSize, job.srcSize); if (zcs->frameEnded && (zcs->doneJobID+1 == zcs->nextJobID)) { /* write checksum at end of last section */ U32 const checksum = (U32)XXH64_digest(&zcs->xxhState); DEBUGLOG(4, "writing checksum : %08X \n", checksum); MEM_writeLE32((char*)job.dstBuff.start + job.cSize, checksum); job.cSize += 4; zcs->jobs[wJobID].cSize += 4; } } ZSTDMT_releaseBuffer(zcs->buffPool, job.src); zcs->jobs[wJobID].srcStart = NULL; zcs->jobs[wJobID].src = g_nullBuffer; zcs->jobs[wJobID].jobScanned = 1; } { size_t const toWrite = MIN(job.cSize - job.dstFlushed, output->size - output->pos); DEBUGLOG(4, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID); memcpy((char*)output->dst + output->pos, (const char*)job.dstBuff.start + job.dstFlushed, toWrite); output->pos += toWrite; job.dstFlushed += toWrite; } if (job.dstFlushed == job.cSize) { /* output buffer fully flushed => move to next one */ ZSTDMT_releaseBuffer(zcs->buffPool, job.dstBuff); zcs->jobs[wJobID].dstBuff = g_nullBuffer; zcs->jobs[wJobID].jobCompleted = 0; zcs->doneJobID++; } else { zcs->jobs[wJobID].dstFlushed = job.dstFlushed; } /* return value : how many bytes left in buffer ; fake it to 1 if unknown but >0 */ if (job.cSize > job.dstFlushed) return (job.cSize - job.dstFlushed); if (zcs->doneJobID < zcs->nextJobID) return 1; /* still some buffer to flush */ zcs->allJobsCompleted = zcs->frameEnded; /* frame completed and entirely flushed */ return 0; /* everything flushed */ } }
static inline size_t ZSTD_stwrite32(ZSTD_frameLog* fl, ZSTD_outBuffer* output, U32 const value, U32 const offset) { if (fl->seekTablePos < offset + 4) { BYTE tmp[4]; /* so that we can work with buffers too small to write a whole word to */ size_t const lenWrite = MIN(output->size - output->pos, offset + 4 - fl->seekTablePos); MEM_writeLE32(tmp, value); memcpy((BYTE*)output->dst + output->pos, tmp + (fl->seekTablePos - offset), lenWrite); output->pos += lenWrite; fl->seekTablePos += lenWrite; if (lenWrite < 4) return ZSTD_seekable_seekTableSize(fl) - fl->seekTablePos; } return 0; }