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;
|
uint64_t memusage;
|
||||||
|
|
||||||
/// The filter chain of this Block in human-readable form
|
/// The filter chain of this Block in human-readable form
|
||||||
char filter_chain[FILTERS_STR_SIZE];
|
char *filter_chain;
|
||||||
|
|
||||||
} block_header_info;
|
} 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
|
/// Strings ending in a colon. These are used for lines like
|
||||||
/// " Foo: 123 MiB". These are grouped because translated strings
|
/// " 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.
|
// 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().
|
// Free the memory allocated by lzma_block_header_decode().
|
||||||
lzma_filters_free(filters, NULL);
|
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;
|
return false;
|
||||||
|
|
||||||
data_error:
|
data_error:
|
||||||
|
@ -864,9 +876,6 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
||||||
// Cache the verbosity level to a local variable.
|
// Cache the verbosity level to a local variable.
|
||||||
const bool detailed = message_verbosity_get() >= V_DEBUG;
|
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
|
// Print information about the Blocks but only if there is
|
||||||
// at least one Block.
|
// at least one Block.
|
||||||
if (lzma_index_block_count(xfi->idx) > 0) {
|
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.
|
// Iterate over the Blocks.
|
||||||
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
|
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))
|
if (detailed && parse_details(pair, &iter, &bhi, xfi))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const char *cols1[4] = {
|
const char *cols1[4] = {
|
||||||
uint64_to_str(iter.stream.number, 0),
|
uint64_to_str(iter.stream.number, 0),
|
||||||
|
@ -1001,6 +1013,7 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
||||||
}
|
}
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
block_header_info_end(&bhi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,9 +1071,9 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
|
||||||
iter.stream.padding);
|
iter.stream.padding);
|
||||||
|
|
||||||
lzma_index_iter_rewind(&iter);
|
lzma_index_iter_rewind(&iter);
|
||||||
block_header_info bhi;
|
|
||||||
|
|
||||||
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
|
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
|
||||||
|
block_header_info bhi = BLOCK_HEADER_INFO_INIT;
|
||||||
if (message_verbosity_get() >= V_DEBUG
|
if (message_verbosity_get() >= V_DEBUG
|
||||||
&& parse_details(
|
&& parse_details(
|
||||||
pair, &iter, &bhi, xfi))
|
pair, &iter, &bhi, xfi))
|
||||||
|
@ -1091,6 +1104,7 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
|
||||||
bhi.filter_chain);
|
bhi.filter_chain);
|
||||||
|
|
||||||
putchar('\n');
|
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
|
extern void
|
||||||
message_filters_show(enum message_verbosity v, const lzma_filter *filters)
|
message_filters_show(enum message_verbosity v, const lzma_filter *filters)
|
||||||
{
|
{
|
||||||
if (v > verbosity)
|
if (v > verbosity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char buf[FILTERS_STR_SIZE];
|
char *buf;
|
||||||
message_filters_to_str(buf, filters, true);
|
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);
|
fprintf(stderr, _("%s: Filter chain: %s\n"), progname, buf);
|
||||||
|
free(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue