From 6583fa3f0ab8b7ab7c34888a07b20af852a2ef3c Mon Sep 17 00:00:00 2001 From: Binh Vo Date: Wed, 9 Jun 2021 14:00:29 -0400 Subject: [PATCH] Add support for --long-param flag --- programs/zstdcli.c | 73 +++++++++++++++++++++++++++++++++++----------- tests/playTests.sh | 7 +++++ 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 9e2133c4f..28fc980a2 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -206,6 +206,7 @@ static void usage_advanced(const char* programName) DISPLAYOUT( "--ultra : enable levels beyond %i, up to %i (requires more memory) \n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); DISPLAYOUT( "--long[=#]: enable long distance matching with given window log (default: %u) \n", g_defaultMaxWindowLog); DISPLAYOUT( "--fast[=#]: switch to very fast compression levels (default: %u) \n", 1); + DISPLAYOUT( "--long-param=#: specify compression level, accepts negative values as fast compression levels \n"); DISPLAYOUT( "--adapt : dynamically adapt compression level to I/O conditions \n"); DISPLAYOUT( "--[no-]row-match-finder : force enable/disable usage of fast row-based matchfinder for greedy, lazy, and lazy2 strategies \n"); DISPLAYOUT( "--patch-from=FILE : specify the file to be used as a reference point for zstd's diff engine. \n"); @@ -354,6 +355,25 @@ static unsigned readU32FromChar(const char** stringPtr) { return result; } +#ifndef ZSTD_NOCOMPRESS +/*! readIntFromChar() : + * @return : signed integer value read from input in `char` format. + * allows and interprets K, KB, KiB, M, MB and MiB suffix. + * Will also modify `*stringPtr`, advancing it to position where it stopped reading. + * Note : function will exit() program if digit sequence overflows */ +static int readIntFromChar(const char** stringPtr) { + static const char errorMsg[] = "error: numeric value overflows 32-bit int"; + int sign = 1; + unsigned result; + if (**stringPtr=='-') { + (*stringPtr)++; + sign = -1; + } + if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } + return (int) result * sign; +} +#endif + /*! readSizeTFromCharChecked() : * @return 0 if success, and store the result in *value. * allows and interprets K, KB, KiB, M, MB and MiB suffix. @@ -940,23 +960,6 @@ int main(int const argCount, const char* argv[]) if (longCommandWArg(&argument, "--trace")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; } #endif if (longCommandWArg(&argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); continue; } - if (longCommandWArg(&argument, "--long")) { - unsigned ldmWindowLog = 0; - ldmFlag = 1; - /* Parse optional window log */ - if (*argument == '=') { - ++argument; - ldmWindowLog = readU32FromChar(&argument); - } else if (*argument != 0) { - /* Invalid character following --long */ - badusage(programName); - CLEAN_RETURN(1); - } - /* Only set windowLog if not already set by --zstd */ - if (compressionParams.windowLog == 0) - compressionParams.windowLog = ldmWindowLog; - continue; - } #ifndef ZSTD_NOCOMPRESS /* linking ZSTD_minCLevel() requires compression support */ if (longCommandWArg(&argument, "--fast")) { /* Parse optional acceleration factor */ @@ -981,8 +984,44 @@ int main(int const argCount, const char* argv[]) } continue; } + + if (longCommandWArg(&argument, "--long-param")) { + if (*argument == '=') { + int maxLevel = ZSTD_maxCLevel(); + int minLevel = ZSTD_minCLevel(); + int readLevel; + ++argument; + readLevel = readIntFromChar(&argument); + if (readLevel > maxLevel) readLevel = maxLevel; + if (readLevel < minLevel) readLevel = minLevel; + cLevel = readLevel; + } else { + /* --long-param requires an argument */ + badusage(programName); + CLEAN_RETURN(1); + } + continue; + } #endif + if (longCommandWArg(&argument, "--long")) { + unsigned ldmWindowLog = 0; + ldmFlag = 1; + /* Parse optional window log */ + if (*argument == '=') { + ++argument; + ldmWindowLog = readU32FromChar(&argument); + } else if (*argument != 0) { + /* Invalid character following --long */ + badusage(programName); + CLEAN_RETURN(1); + } + /* Only set windowLog if not already set by --zstd */ + if (compressionParams.windowLog == 0) + compressionParams.windowLog = ldmWindowLog; + continue; + } + if (longCommandWArg(&argument, "--filelist")) { const char* listName; NEXT_FIELD(listName); diff --git a/tests/playTests.sh b/tests/playTests.sh index 252939006..09dae1a29 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -191,6 +191,13 @@ zstd --fast=3 -f tmp # == -3 zstd --fast=200000 -f tmp # too low compression level, automatic fixed zstd --fast=5000000000 -f tmp && die "too large numeric value : must fail" zstd -c --fast=0 tmp > $INTOVOID && die "--fast must not accept value 0" +println "test : --long-param compression levels" +zstd --long-param=1 -f tmp +zstd --long-param=0 -f tmp +zstd --long-param=-1 -f tmp +zstd --long-param=-10000 -f tmp # too low, automatic fixed +zstd --long-param=10000 -f tmp # too high, automatic fixed +zstd --long-param -f tmp > $INTOVOID && die "--long-param must be given a value" println "test : too large numeric argument" zstd --fast=9999999999 -f tmp && die "should have refused numeric value" println "test : set compression level with environment variable ZSTD_CLEVEL"