Split message_filters().
authorLasse Collin <lasse.collin@tukaani.org>
Sun, 16 May 2010 15:42:22 +0000 (18:42 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Sun, 16 May 2010 15:42:22 +0000 (18:42 +0300)
message_filters_to_str() converts the filter chain to
a string. message_filters_show() replaces the original
message_filters().

uint32_to_optstr() was also added to show the dictionary
size in nicer format when possible.

src/xz/coder.c
src/xz/message.c
src/xz/message.h

index 2ee0c70..8d882d2 100644 (file)
@@ -168,7 +168,7 @@ coder_set_compression_settings(void)
                                                "with the .xz format"));
 
        // Print the selected filter chain.
-       message_filters(V_DEBUG, filters);
+       message_filters_show(V_DEBUG, filters);
 
        // If using --format=raw, we can be decoding. The memusage function
        // also validates the filter chain and the options used for the
index f24e98e..9414013 100644 (file)
@@ -876,16 +876,37 @@ message_mem_needed(enum message_verbosity v, uint64_t memusage)
 }
 
 
-extern void
-message_filters(enum message_verbosity v, const lzma_filter *filters)
+/// \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)
 {
-       if (v > verbosity)
-               return;
+       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 const char *
+message_filters_get(const lzma_filter *filters, bool all_known)
+{
+       static char buf[512];
 
-       fprintf(stderr, _("%s: Filter chain:"), progname);
+       char *pos = buf;
+       size_t left = sizeof(buf);
 
        for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
-               fprintf(stderr, " --");
+               // 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:
@@ -894,96 +915,128 @@ message_filters(enum message_verbosity v, const lzma_filter *filters)
                        const char *mode;
                        const char *mf;
 
-                       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;
+                       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;
+                               }
                        }
 
-                       fprintf(stderr, "lzma%c=dict=%" PRIu32
+                       // 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,
-                                       filters[i].id == LZMA_FILTER_LZMA2
-                                               ? '2' : '1',
-                                       opt->dict_size,
                                        opt->lc, opt->lp, opt->pb,
                                        mode, opt->nice_len, mf, opt->depth);
                        break;
                }
 
                case LZMA_FILTER_X86:
-                       fprintf(stderr, "x86");
-                       break;
-
                case LZMA_FILTER_POWERPC:
-                       fprintf(stderr, "powerpc");
-                       break;
-
                case LZMA_FILTER_IA64:
-                       fprintf(stderr, "ia64");
-                       break;
-
                case LZMA_FILTER_ARM:
-                       fprintf(stderr, "arm");
-                       break;
-
                case LZMA_FILTER_ARMTHUMB:
-                       fprintf(stderr, "armthumb");
-                       break;
+               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);
 
-               case LZMA_FILTER_SPARC:
-                       fprintf(stderr, "sparc");
                        break;
+               }
 
                case LZMA_FILTER_DELTA: {
                        const lzma_options_delta *opt = filters[i].options;
-                       fprintf(stderr, "delta=dist=%" PRIu32, opt->dist);
+                       my_snprintf(&pos, &left, "delta=dist=%" PRIu32,
+                                       opt->dist);
                        break;
                }
 
                default:
-                       fprintf(stderr, "UNKNOWN");
+                       // This should be possible only if liblzma is
+                       // newer than the xz tool.
+                       my_snprintf(&pos, &left, "UNKNOWN");
                        break;
                }
        }
 
-       fputc('\n', stderr);
+       return buf;
+}
+
+
+extern void
+message_filters_show(enum message_verbosity v, const lzma_filter *filters)
+{
+       if (v > verbosity)
+               return;
+
+       fprintf(stderr, _("%s: Filter chain: %s\n"), progname,
+                       message_filters_get(filters, true));
        return;
 }
 
index 7d637df..8f01187 100644 (file)
@@ -86,8 +86,20 @@ extern const char *message_strm(lzma_ret code);
 extern void message_mem_needed(enum message_verbosity v, uint64_t memusage);
 
 
+/// \brief      Get the filter chain as a string
+///
+/// \param      filters     Pointer to the filter chain
+/// \param      all_known   If true, all filter options are printed.
+///                         If false, only the options that get stored
+///                         into .xz headers are printed.
+///
+/// \return     Pointer to a statically allocated buffer.
+extern const char *message_filters_get(
+               const lzma_filter *filters, bool all_known);
+
+
 /// Print the filter chain.
-extern void message_filters(
+extern void message_filters_show(
                enum message_verbosity v, const lzma_filter *filters);