From c523c93b262daf0e94af6b71feff68758c13cfe2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Aug 2017 15:57:53 -0700 Subject: [PATCH] improved and fixed --list command, original patches by @ib (#772) accepts all skippable frame identifiers. display in MB or KB, depending on frame size. fixed combination of skippable and zstd frames. --- NEWS | 1 + programs/fileio.c | 95 ++++++++++++++++++++--------------------------- 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/NEWS b/NEWS index b3c2613f..641551d9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ v1.3.1 perf: substantially decreased memory usage in Multi-threading mode, thanks to reports by Tino Reichardt perf: Multi-threading supports up to 256 threads. Cap at 256 when more are requested (#760) +cli : improved and fixed --list command, by @ib (#772) build: fix Visual compilation for non x86/x64 targets, reported by Greg Slazinski (#718) API exp : breaking change : ZSTD_getframeHeader() provides more information API exp : breaking change : pinned down values of error codes diff --git a/programs/fileio.c b/programs/fileio.c index e729e37e..e6fa61f6 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -947,6 +947,7 @@ static int getFileInfo(fileInfo_t* info, const char* inFileName){ return 3; } info->compressedSize = (unsigned long long)UTIL_getFileSize(inFileName); + /* begin analyzing frame */ for ( ; ; ) { BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; @@ -966,37 +967,31 @@ static int getFileInfo(fileInfo_t* info, const char* inFileName){ break; } } - { - U32 const magicNumber = MEM_readLE32(headerBuffer); + { U32 const magicNumber = MEM_readLE32(headerBuffer); + /* Zstandard frame */ if (magicNumber == ZSTD_MAGICNUMBER) { U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead); if (frameContentSize == ZSTD_CONTENTSIZE_ERROR || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN) { info->decompUnavailable = 1; - } - else { + } else { info->decompressedSize += frameContentSize; } - { - /* move to the end of the frame header */ - size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead); + /* move to the end of the frame header */ + { size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead); if (ZSTD_isError(headerSize)) { DISPLAY("Error: could not determine frame header size\n"); detectError = 1; break; } - { - int const ret = fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR); + { int const ret = fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR); if (ret != 0) { DISPLAY("Error: could not move to end of frame header\n"); detectError = 1; break; - } - } - } + } } } /* skip the rest of the blocks in the frame */ - { - int lastBlock = 0; + { int lastBlock = 0; do { BYTE blockHeaderBuffer[3]; U32 blockHeader; @@ -1009,24 +1004,20 @@ static int getFileInfo(fileInfo_t* info, const char* inFileName){ } blockHeader = MEM_readLE24(blockHeaderBuffer); lastBlock = blockHeader & 1; - blockSize = blockHeader >> 3; - { - int const ret = fseek(srcFile, blockSize, SEEK_CUR); + blockSize = blockHeader >> 3; /* Warning : does not work when block is RLE type */ + { int const ret = fseek(srcFile, blockSize, SEEK_CUR); if (ret != 0) { DISPLAY("Error: could not skip to end of block\n"); detectError = 1; break; - } - } + } } } while (lastBlock != 1); - if (detectError) { - break; - } + if (detectError) break; } - { - /* check if checksum is used */ - BYTE const frameHeaderDescriptor = headerBuffer[4]; + + /* check if checksum is used */ + { BYTE const frameHeaderDescriptor = headerBuffer[4]; int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2; if (contentChecksumFlag) { int const ret = fseek(srcFile, 4, SEEK_CUR); @@ -1035,64 +1026,60 @@ static int getFileInfo(fileInfo_t* info, const char* inFileName){ DISPLAY("Error: could not skip past checksum\n"); detectError = 1; break; - } - } - } + } } } info->numActualFrames++; } - else if (magicNumber == ZSTD_MAGIC_SKIPPABLE_START) { - BYTE frameSizeBuffer[4]; - size_t const readBytes = fread(frameSizeBuffer, 1, 4, srcFile); - if (readBytes != 4) { - DISPLAY("There was an error reading skippable frame size"); + /* Skippable frame */ + else if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + U32 const frameSize = MEM_readLE32(headerBuffer + 4); + long const seek = -numBytesRead + 8 + frameSize; + int const ret = LONG_SEEK(srcFile, seek, SEEK_CUR); + if (ret != 0) { + DISPLAY("Error: could not find end of skippable frame\n"); detectError = 1; break; } - { - U32 const frameSize = MEM_readLE32(frameSizeBuffer); - int const ret = LONG_SEEK(srcFile, frameSize, SEEK_CUR); - if (ret != 0) { - DISPLAY("Error: could not find end of skippable frame\n"); - detectError = 1; - break; - } - } info->numSkippableFrames++; } + /* unknown content */ else { detectError = 2; break; } } - } + } /* end analyzing frame */ fclose(srcFile); return detectError; } static void displayInfo(const char* inFileName, fileInfo_t* info, int displayLevel){ - double const compressedSizeMB = (double)info->compressedSize/(1 MB); - double const decompressedSizeMB = (double)info->decompressedSize/(1 MB); + unsigned const unit = info->compressedSize < (1 MB) ? (1 KB) : (1 MB); + const char* const unitStr = info->compressedSize < (1 MB) ? "KB" : "MB"; + double const compressedSizeUnit = (double)info->compressedSize / unit; + double const decompressedSizeUnit = (double)info->decompressedSize / unit; double const ratio = (info->compressedSize == 0) ? 0 : ((double)info->decompressedSize)/info->compressedSize; const char* const checkString = (info->usesCheck ? "XXH64" : "None"); if (displayLevel <= 2) { if (!info->decompUnavailable) { DISPLAYOUT("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n"); - DISPLAYOUT("%9d %13d %7.2f MB %9.2f MB %5.3f %5s %s\n", - info->numSkippableFrames, info->numActualFrames, compressedSizeMB, decompressedSizeMB, + DISPLAYOUT("%9d %13d %7.2f %2s %9.2f %2s %5.3f %5s %s\n", + info->numSkippableFrames, info->numActualFrames, + compressedSizeUnit, unitStr, decompressedSizeUnit, unitStr, ratio, checkString, inFileName); - } - else { + } else { DISPLAYOUT("Skippable Non-Skippable Compressed Check Filename\n"); DISPLAYOUT("%9d %13d %7.2f MB %5s %s\n", - info->numSkippableFrames, info->numActualFrames, compressedSizeMB, checkString, inFileName); + info->numSkippableFrames, info->numActualFrames, + compressedSizeUnit, checkString, inFileName); } - } - else{ + } else { DISPLAYOUT("# Zstandard Frames: %d\n", info->numActualFrames); DISPLAYOUT("# Skippable Frames: %d\n", info->numSkippableFrames); - DISPLAYOUT("Compressed Size: %.2f MB (%llu B)\n", compressedSizeMB, info->compressedSize); + DISPLAYOUT("Compressed Size: %.2f %2s (%llu B)\n", + compressedSizeUnit, unitStr, info->compressedSize); if (!info->decompUnavailable) { - DISPLAYOUT("Decompressed Size: %.2f MB (%llu B)\n", decompressedSizeMB, info->decompressedSize); + DISPLAYOUT("Decompressed Size: %.2f %2s (%llu B)\n", + decompressedSizeUnit, unitStr, info->decompressedSize); DISPLAYOUT("Ratio: %.4f\n", ratio); } DISPLAYOUT("Check: %s\n", checkString);