mirror of https://git.tukaani.org/xz.git
xz: Use lzma_str_from_filters().
Two uses: Displaying encoder filter chain when compressing with -vv, and displaying the decoder filter chain in --list -vv.
This commit is contained in:
parent
cedeeca2ea
commit
7484744af6
|
@ -52,10 +52,13 @@ typedef struct {
|
|||
uint64_t memusage;
|
||||
|
||||
/// The filter chain of this Block in human-readable form
|
||||
char filter_chain[FILTERS_STR_SIZE];
|
||||
char *filter_chain;
|
||||
|
||||
} block_header_info;
|
||||
|
||||
#define BLOCK_HEADER_INFO_INIT { .filter_chain = NULL }
|
||||
#define block_header_info_end(bhi) free((bhi)->filter_chain)
|
||||
|
||||
|
||||
/// Strings ending in a colon. These are used for lines like
|
||||
/// " Foo: 123 MiB". These are grouped because translated strings
|
||||
|
@ -566,10 +569,19 @@ parse_block_header(file_pair *pair, const lzma_index_iter *iter,
|
|||
}
|
||||
|
||||
// Convert the filter chain to human readable form.
|
||||
message_filters_to_str(bhi->filter_chain, filters, false);
|
||||
const lzma_ret str_ret = lzma_str_from_filters(
|
||||
&bhi->filter_chain, filters,
|
||||
LZMA_STR_DECODER | LZMA_STR_GETOPT_LONG, NULL);
|
||||
|
||||
// Free the memory allocated by lzma_block_header_decode().
|
||||
lzma_filters_free(filters, NULL);
|
||||
|
||||
// Check if the stringification succeeded.
|
||||
if (str_ret != LZMA_OK) {
|
||||
message_error("%s: %s", pair->src_name, message_strm(str_ret));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
data_error:
|
||||
|
@ -864,9 +876,6 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
|||
// Cache the verbosity level to a local variable.
|
||||
const bool detailed = message_verbosity_get() >= V_DEBUG;
|
||||
|
||||
// Information collected from Block Headers
|
||||
block_header_info bhi;
|
||||
|
||||
// Print information about the Blocks but only if there is
|
||||
// at least one Block.
|
||||
if (lzma_index_block_count(xfi->idx) > 0) {
|
||||
|
@ -916,8 +925,11 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
|||
|
||||
// Iterate over the Blocks.
|
||||
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
|
||||
// If in detailed mode, collect the information from
|
||||
// Block Header before starting to print the next line.
|
||||
block_header_info bhi = BLOCK_HEADER_INFO_INIT;
|
||||
if (detailed && parse_details(pair, &iter, &bhi, xfi))
|
||||
return true;
|
||||
return true;
|
||||
|
||||
const char *cols1[4] = {
|
||||
uint64_to_str(iter.stream.number, 0),
|
||||
|
@ -1001,6 +1013,7 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
|||
}
|
||||
|
||||
putchar('\n');
|
||||
block_header_info_end(&bhi);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1058,9 +1071,9 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
|
|||
iter.stream.padding);
|
||||
|
||||
lzma_index_iter_rewind(&iter);
|
||||
block_header_info bhi;
|
||||
|
||||
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
|
||||
block_header_info bhi = BLOCK_HEADER_INFO_INIT;
|
||||
if (message_verbosity_get() >= V_DEBUG
|
||||
&& parse_details(
|
||||
pair, &iter, &bhi, xfi))
|
||||
|
@ -1091,6 +1104,7 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
|
|||
bhi.filter_chain);
|
||||
|
||||
putchar('\n');
|
||||
block_header_info_end(&bhi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
175
src/xz/message.c
175
src/xz/message.c
|
@ -900,181 +900,20 @@ message_mem_needed(enum message_verbosity v, uint64_t memusage)
|
|||
}
|
||||
|
||||
|
||||
/// \brief Convert uint32_t to a nice string for --lzma[12]=dict=SIZE
|
||||
///
|
||||
/// The idea is to use KiB or MiB suffix when possible.
|
||||
static const char *
|
||||
uint32_to_optstr(uint32_t num)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
if ((num & ((UINT32_C(1) << 20) - 1)) == 0)
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32 "MiB", num >> 20);
|
||||
else if ((num & ((UINT32_C(1) << 10) - 1)) == 0)
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32 "KiB", num >> 10);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32, num);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
message_filters_to_str(char buf[FILTERS_STR_SIZE],
|
||||
const lzma_filter *filters, bool all_known)
|
||||
{
|
||||
char *pos = buf;
|
||||
size_t left = FILTERS_STR_SIZE;
|
||||
|
||||
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
|
||||
// Add the dashes for the filter option. A space is
|
||||
// needed after the first and later filters.
|
||||
my_snprintf(&pos, &left, "%s", i == 0 ? "--" : " --");
|
||||
|
||||
switch (filters[i].id) {
|
||||
case LZMA_FILTER_LZMA1:
|
||||
case LZMA_FILTER_LZMA2: {
|
||||
const lzma_options_lzma *opt = filters[i].options;
|
||||
const char *mode = NULL;
|
||||
const char *mf = NULL;
|
||||
|
||||
if (all_known) {
|
||||
switch (opt->mode) {
|
||||
case LZMA_MODE_FAST:
|
||||
mode = "fast";
|
||||
break;
|
||||
|
||||
case LZMA_MODE_NORMAL:
|
||||
mode = "normal";
|
||||
break;
|
||||
|
||||
default:
|
||||
mode = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opt->mf) {
|
||||
case LZMA_MF_HC3:
|
||||
mf = "hc3";
|
||||
break;
|
||||
|
||||
case LZMA_MF_HC4:
|
||||
mf = "hc4";
|
||||
break;
|
||||
|
||||
case LZMA_MF_BT2:
|
||||
mf = "bt2";
|
||||
break;
|
||||
|
||||
case LZMA_MF_BT3:
|
||||
mf = "bt3";
|
||||
break;
|
||||
|
||||
case LZMA_MF_BT4:
|
||||
mf = "bt4";
|
||||
break;
|
||||
|
||||
default:
|
||||
mf = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the filter name and dictionary size, which
|
||||
// is always known.
|
||||
my_snprintf(&pos, &left, "lzma%c=dict=%s",
|
||||
filters[i].id == LZMA_FILTER_LZMA2
|
||||
? '2' : '1',
|
||||
uint32_to_optstr(opt->dict_size));
|
||||
|
||||
// With LZMA1 also lc/lp/pb are known when
|
||||
// decompressing, but this function is never
|
||||
// used to print information about .lzma headers.
|
||||
assert(filters[i].id == LZMA_FILTER_LZMA2
|
||||
|| all_known);
|
||||
|
||||
// Print the rest of the options, which are known
|
||||
// only when compressing.
|
||||
if (all_known)
|
||||
my_snprintf(&pos, &left,
|
||||
",lc=%" PRIu32 ",lp=%" PRIu32
|
||||
",pb=%" PRIu32
|
||||
",mode=%s,nice=%" PRIu32 ",mf=%s"
|
||||
",depth=%" PRIu32,
|
||||
opt->lc, opt->lp, opt->pb,
|
||||
mode, opt->nice_len, mf, opt->depth);
|
||||
break;
|
||||
}
|
||||
|
||||
case LZMA_FILTER_X86:
|
||||
case LZMA_FILTER_POWERPC:
|
||||
case LZMA_FILTER_IA64:
|
||||
case LZMA_FILTER_ARM:
|
||||
case LZMA_FILTER_ARMTHUMB:
|
||||
case LZMA_FILTER_SPARC: {
|
||||
static const char bcj_names[][9] = {
|
||||
"x86",
|
||||
"powerpc",
|
||||
"ia64",
|
||||
"arm",
|
||||
"armthumb",
|
||||
"sparc",
|
||||
};
|
||||
|
||||
const lzma_options_bcj *opt = filters[i].options;
|
||||
my_snprintf(&pos, &left, "%s", bcj_names[filters[i].id
|
||||
- LZMA_FILTER_X86]);
|
||||
|
||||
// Show the start offset only when really needed.
|
||||
if (opt != NULL && opt->start_offset != 0)
|
||||
my_snprintf(&pos, &left, "=start=%" PRIu32,
|
||||
opt->start_offset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LZMA_FILTER_ARM64: {
|
||||
// FIXME TODO: Merge with the above generic BCJ list
|
||||
// once the Filter ID is changed to the final value.
|
||||
const lzma_options_bcj *opt = filters[i].options;
|
||||
my_snprintf(&pos, &left, "arm64");
|
||||
|
||||
// Show the start offset only when really needed.
|
||||
if (opt != NULL && opt->start_offset != 0)
|
||||
my_snprintf(&pos, &left, "=start=%" PRIu32,
|
||||
opt->start_offset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LZMA_FILTER_DELTA: {
|
||||
const lzma_options_delta *opt = filters[i].options;
|
||||
my_snprintf(&pos, &left, "delta=dist=%" PRIu32,
|
||||
opt->dist);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// This should be possible only if liblzma is
|
||||
// newer than the xz tool.
|
||||
my_snprintf(&pos, &left, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
message_filters_show(enum message_verbosity v, const lzma_filter *filters)
|
||||
{
|
||||
if (v > verbosity)
|
||||
return;
|
||||
|
||||
char buf[FILTERS_STR_SIZE];
|
||||
message_filters_to_str(buf, filters, true);
|
||||
char *buf;
|
||||
const lzma_ret ret = lzma_str_from_filters(&buf, filters,
|
||||
LZMA_STR_ENCODER | LZMA_STR_GETOPT_LONG, NULL);
|
||||
if (ret != LZMA_OK)
|
||||
message_fatal("%s", message_strm(ret));
|
||||
|
||||
fprintf(stderr, _("%s: Filter chain: %s\n"), progname, buf);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue