diff options
author | Jia Tan <jiat0218@gmail.com> | 2023-01-06 00:02:29 +0800 |
---|---|---|
committer | Jia Tan <jiat0218@gmail.com> | 2023-07-17 23:34:55 +0800 |
commit | 9ded880a0221f4d1256845fc4ab957ffd377c760 (patch) | |
tree | 29c2b360d4cd4156ef73d40dcbab00dc5a76a32b /src/xz | |
parent | Tests: Improve feature testing for skipping. (diff) | |
download | xz-9ded880a0221f4d1256845fc4ab957ffd377c760.tar.xz |
xz: Add --filters option to CLI.
The --filters option uses the new lzma_str_to_filters() function
to convert a string into a full filter chain. Using this option
will reset all previous filters set by --preset, --[filter], or
--filters.
Diffstat (limited to 'src/xz')
-rw-r--r-- | src/xz/args.c | 9 | ||||
-rw-r--r-- | src/xz/coder.c | 50 | ||||
-rw-r--r-- | src/xz/coder.h | 3 |
3 files changed, 58 insertions, 4 deletions
diff --git a/src/xz/args.c b/src/xz/args.c index b831946f..e21aee93 100644 --- a/src/xz/args.c +++ b/src/xz/args.c @@ -136,7 +136,8 @@ static void parse_real(args_info *args, int argc, char **argv) { enum { - OPT_X86 = INT_MIN, + OPT_FILTERS = INT_MIN, + OPT_X86, OPT_POWERPC, OPT_IA64, OPT_ARM, @@ -206,6 +207,7 @@ parse_real(args_info *args, int argc, char **argv) { "best", no_argument, NULL, '9' }, // Filters + { "filters", optional_argument, NULL, OPT_FILTERS}, { "lzma1", optional_argument, NULL, OPT_LZMA1 }, { "lzma2", optional_argument, NULL, OPT_LZMA2 }, { "x86", optional_argument, NULL, OPT_X86 }, @@ -372,7 +374,10 @@ parse_real(args_info *args, int argc, char **argv) opt_mode = MODE_COMPRESS; break; - // Filter setup + // --filters + case OPT_FILTERS: + coder_add_filters_from_str(optarg); + break; case OPT_X86: coder_add_filter(LZMA_FILTER_X86, diff --git a/src/xz/coder.c b/src/xz/coder.c index 05f22888..b998cb2b 100644 --- a/src/xz/coder.c +++ b/src/xz/coder.c @@ -45,6 +45,11 @@ static uint32_t filters_count = 0; /// Number of the preset (0-9) static uint32_t preset_number = LZMA_PRESET_DEFAULT; +/// True if the current filter chain was set using the --filters option. +/// The filter chain is reset if a preset option (like -9) or an old-style +/// filter option (like --lzma2) is used after a --filters option. +static bool string_to_filter_used = false; + /// Integrity check type static lzma_check check; @@ -77,14 +82,15 @@ coder_set_check(lzma_check new_check) static void forget_filter_chain(void) { - // Setting a preset makes us forget a possibly defined custom - // filter chain. + // Setting a preset or using --filters makes us forget + // the earlier custom filter chain (if any). while (filters_count > 0) { --filters_count; free(filters[filters_count].options); filters[filters_count].options = NULL; } + string_to_filter_used = false; return; } @@ -114,6 +120,9 @@ coder_add_filter(lzma_vli id, void *options) if (filters_count == LZMA_FILTERS_MAX) message_fatal(_("Maximum number of filters is four")); + if (string_to_filter_used) + forget_filter_chain(); + filters[filters_count].id = id; filters[filters_count].options = options; ++filters_count; @@ -128,6 +137,43 @@ coder_add_filter(lzma_vli id, void *options) } +extern void +coder_add_filters_from_str(const char *filter_str) +{ + // Forget presets and previously defined filter chain. See + // coder_add_filter() above for why preset_number must be reset too. + forget_filter_chain(); + preset_number = LZMA_PRESET_DEFAULT; + + string_to_filter_used = true; + + // Include LZMA_STR_ALL_FILTERS so this can be used with --format=raw. + int error_pos; + const char *err = lzma_str_to_filters(filter_str, &error_pos, + filters, LZMA_STR_ALL_FILTERS, NULL); + + if (err != NULL) { + // FIXME? The message in err isn't translated. + // Including the translations in the xz translations is + // slightly ugly but possible. Creating a new domain for + // liblzma might not be worth it especially since on some + // OSes it adds extra dependencies to translation libraries. + message(V_ERROR, _("Error in --filters=FILTERS option:")); + message(V_ERROR, "%s", filter_str); + message(V_ERROR, "%*s^", error_pos, ""); + message_fatal("%s", err); + } + + // Set the filters_count to be the number of filters converted from + // the string. + for (filters_count = 0; filters[filters_count].id != LZMA_VLI_UNKNOWN; + ++filters_count) ; + + assert(filters_count > 0); + return; +} + + static void lzma_attribute((__noreturn__)) memlimit_too_small(uint64_t memory_usage) { diff --git a/src/xz/coder.h b/src/xz/coder.h index b4f43a2b..997d2586 100644 --- a/src/xz/coder.h +++ b/src/xz/coder.h @@ -77,3 +77,6 @@ extern void coder_run(const char *filename); /// Free the memory allocated for the coder and kill the worker threads. extern void coder_free(void); #endif + +/// Create filter chain from string +extern void coder_add_filters_from_str(const char *filter_str); |