]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
CLI: simplified handling of separated-fields arguments
authorYann Collet <cyan@fb.com>
Fri, 17 Jul 2020 19:46:36 +0000 (12:46 -0700)
committerYann Collet <cyan@fb.com>
Fri, 17 Jul 2020 19:46:36 +0000 (12:46 -0700)
this patch reduces complexity associated with
commands requiring a separated arguments
such as :
-o filename
-D dictionary
--output-dir-flat dir
--output-dir-mirror dir

It used to be a multi-stage process with explicit context,
it's now simplified as a single macro.

Thanks to this simplification,
separated arguments logic has also been extended to
--patch-from XXX
--filelist XXX
which extends existing capability using =XXX
--patch-from=XXX
--filelist=XXX

Separated argument is useful for filenames and directories,
as it benefits from shell expansion
such as ~/dir/file
where the ~ is automatically translated by the shell.
In contrast --long-command=FILE does not interpret FILE,
so ~/ is transmitted as is to the main() function,
generally resulting in incorrect file name.

programs/zstdcli.c

index 06a8a446ff3d7d492dbce9dc5917fe1d7e629b02..d366e22dba0168041d34899fbb4ab11875bba5d0 100644 (file)
@@ -615,8 +615,17 @@ static int init_cLevel(void) {
     return ZSTDCLI_CLEVEL_DEFAULT;
 }
 
-#define ZSTD_NB_STRATEGIES 9
+#define NEXT_FIELD(ptr) {      \
+    argNb++;                   \
+    if (argNb >= argCount) {   \
+        DISPLAY("error: missing command argument \n"); \
+        exit(1);               \
+    }                          \
+    ptr = argv[argNb];         \
+    assert(ptr != NULL);       \
+}
 
+#define ZSTD_NB_STRATEGIES 9
 static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast",
                 "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2",
                 "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"};
@@ -647,13 +656,9 @@ int main(int const argCount, const char* argv[])
         adaptMin = MINCLEVEL,
         adaptMax = MAXCLEVEL,
         rsyncable = 0,
-        nextArgumentIsOutFileName = 0,
-        nextArgumentIsOutDirName = 0,
-        nextArgumentIsMirroredOutDirName = 0,
         nextArgumentIsMaxDict = 0,
         nextArgumentIsDictID = 0,
         nextArgumentsAreFiles = 0,
-        nextEntryIsDictionary = 0,
         operationResult = 0,
         separateFiles = 0,
         setRealTimePrio = 0,
@@ -773,10 +778,12 @@ int main(int const argCount, const char* argv[])
                 if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(prefs, 0); continue; }
                 if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(prefs, 1); continue; }
                 if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; }
-                if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; }
+                if (!strcmp(argument, "--output-dir-flat")) { NEXT_FIELD(outDirName); continue; }
 #ifdef UTIL_HAS_MIRRORFILELIST
-                if (!strcmp(argument, "--output-dir-mirror")) {nextArgumentIsMirroredOutDirName=1; lastCommand=1; continue; }
+                if (!strcmp(argument, "--output-dir-mirror")) { NEXT_FIELD(outMirroredDirName); continue; }
 #endif
+                if (!strcmp(argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); continue; }
+                if (!strcmp(argument, "--filelist")) { const char* listName; NEXT_FIELD(listName); UTIL_refFilename(file_of_names, listName); continue; }
                 if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; }
                 if (!strcmp(argument, "--content-size")) { contentSize = 1; continue; }
                 if (!strcmp(argument, "--no-content-size")) { contentSize = 0; continue; }
@@ -936,7 +943,7 @@ int main(int const argCount, const char* argv[])
                 case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
 
                     /* Use file content as dictionary */
-                case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
+                case 'D': NEXT_FIELD(dictFileName); argument++; break;
 
                     /* Overwrite */
                 case 'f': FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; argument++; break;
@@ -957,7 +964,10 @@ int main(int const argCount, const char* argv[])
                 case 't': operation=zom_test; argument++; break;
 
                     /* destination file name */
-                case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
+                case 'o':
+                    NEXT_FIELD(outFileName);
+                    if (!strcmp(outFileName, "-")) outFileName = stdoutmark;
+                    argument++; break;
 
                     /* limit memory */
                 case 'M':
@@ -1054,35 +1064,6 @@ int main(int const argCount, const char* argv[])
             continue;
         }
 
-        if (nextEntryIsDictionary) {
-            nextEntryIsDictionary = 0;
-            lastCommand = 0;
-            dictFileName = argument;
-            continue;
-        }
-
-        if (nextArgumentIsOutFileName) {
-            nextArgumentIsOutFileName = 0;
-            lastCommand = 0;
-            outFileName = argument;
-            if (!strcmp(outFileName, "-")) outFileName = stdoutmark;
-            continue;
-        }
-
-        if (nextArgumentIsOutDirName) {
-            nextArgumentIsOutDirName = 0;
-            lastCommand = 0;
-            outDirName = argument;
-            continue;
-        }
-
-        if (nextArgumentIsMirroredOutDirName) {
-            nextArgumentIsMirroredOutDirName = 0;
-            lastCommand = 0;
-            outMirroredDirName = argument;
-            continue;
-        }
-
         /* none of the above : add filename to list */
         UTIL_refFilename(filenames, argument);
     }