[git commit] gzip: add support for compression levels 4-9

Denys Vlasenko vda.linux at googlemail.com
Sun Apr 26 12:22:37 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=bbd53216f80912944da0d4ca72bf3ed3188ca156
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
gzip_main                                            192     282     +90
static.gzip_level_config                               -      24     +24
packed_usage                                       30439   30459     +20
fill_window                                          216     220      +4
pack_gzip                                           1789    1729     -60
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/1 up/down: 138/-60)            Total: 78 bytes

Signed-off-by: Aaro Koskinen <aaro.koskinen at iki.fi>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 archival/gzip.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/archival/gzip.c b/archival/gzip.c
index bc1f9c6..42b2f0b 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -62,14 +62,27 @@ aa:      85.1% -- replaced with aa.gz
 //config:	  1: larger buffers, larger hash-tables
 //config:	  2: larger buffers, largest hash-tables
 //config:	  Larger models may give slightly better compression
+//config:
+//config:config FEATURE_GZIP_LEVELS
+//config:	bool "Enable compression levels"
+//config:	default n
+//config:	depends on GZIP
+//config:	help
+//config:	  Enable support for compression levels 4-9. The default level
+//config:	  is 6. If levels 1-3 are specified, 4 is used.
+//config:	  If this option is not selected, -N options are ignored and -9
+//config:	  is used.
 
 //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP))
 //kbuild:lib-$(CONFIG_GZIP) += gzip.o
 
 //usage:#define gzip_trivial_usage
-//usage:       "[-cfd] [FILE]..."
+//usage:       "[-cfd" IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..."
 //usage:#define gzip_full_usage "\n\n"
 //usage:       "Compress FILEs (or stdin)\n"
+//usage:	IF_FEATURE_GZIP_LEVELS(
+//usage:     "\n	-1..9	Compression level"
+//usage:	)
 //usage:     "\n	-d	Decompress"
 //usage:     "\n	-c	Write to stdout"
 //usage:     "\n	-f	Force"
@@ -252,6 +265,8 @@ enum {
  * input file length plus MIN_LOOKAHEAD.
  */
 
+#ifndef ENABLE_FEATURE_GZIP_LEVELS
+
 	max_chain_length = 4096,
 /* To speed up deflation, hash chains are never searched beyond this length.
  * A higher limit improves compression ratio but degrades the speed.
@@ -283,11 +298,23 @@ enum {
  * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
  * meaning.
  */
+#endif /* ENABLE_FEATURE_GZIP_LEVELS */
 };
 
 
 struct globals {
 
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+	unsigned max_chain_length;
+	unsigned max_lazy_match;
+	unsigned good_match;
+	unsigned nice_match;
+#define max_chain_length (G1.max_chain_length)
+#define max_lazy_match   (G1.max_lazy_match)
+#define good_match	 (G1.good_match)
+#define nice_match	 (G1.nice_match)
+#endif
+
 	lng block_start;
 
 /* window position at the beginning of the current output block. Gets
@@ -2161,24 +2188,48 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
 #endif
 {
 	unsigned opt;
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+	static const struct {
+		uint8_t good;
+		uint8_t chain_shift;
+		uint8_t lazy2;
+		uint8_t nice2;
+	} gzip_level_config[6] = {
+		{4,   4,   4/2,  16/2}, /* Level 4 */
+		{8,   5,  16/2,  32/2}, /* Level 5 */
+		{8,   7,  16/2, 128/2}, /* Level 6 */
+		{8,   8,  32/2, 128/2}, /* Level 7 */
+		{32, 10, 128/2, 258/2}, /* Level 8 */
+		{32, 12, 258/2, 258/2}, /* Level 9 */
+	};
+#endif
+
+	SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2))
+			+ sizeof(struct globals));
 
 #if ENABLE_FEATURE_GZIP_LONG_OPTIONS
 	applet_long_options = gzip_longopts;
 #endif
 	/* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
-	opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "q123456789n");
+	opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789");
 #if ENABLE_GUNZIP /* gunzip_main may not be visible... */
 	if (opt & 0x18) // -d and/or -t
 		return gunzip_main(argc, argv);
 #endif
-	option_mask32 &= 0x7; /* ignore -q, -0..9 */
-	//if (opt & 0x1) // -c
-	//if (opt & 0x2) // -f
-	//if (opt & 0x4) // -v
-	argv += optind;
-
-	SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2))
-			+ sizeof(struct globals));
+#ifdef ENABLE_FEATURE_GZIP_LEVELS
+	opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */
+	if (opt == 0)
+		opt = 1 << 6; /* default: 6 */
+	/* Map 1..3 to 4 */
+	if (opt & 0x7)
+		opt |= 1 << 4;
+	opt = ffs(opt >> 3);
+	max_chain_length = 1 << gzip_level_config[opt].chain_shift;
+	good_match	 = gzip_level_config[opt].good;
+	max_lazy_match	 = gzip_level_config[opt].lazy2 * 2;
+	nice_match	 = gzip_level_config[opt].nice2 * 2;
+#endif
+	option_mask32 &= 0x7; /* retain only -cfv */
 
 	/* Allocate all global buffers (for DYN_ALLOC option) */
 	ALLOC(uch, G1.l_buf, INBUFSIZ);
@@ -2190,5 +2241,6 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
 	/* Initialize the CRC32 table */
 	global_crc32_table = crc32_filltable(NULL, 0);
 
+	argv += optind;
 	return bbunpack(argv, pack_gzip, append_ext, "gz");
 }


More information about the busybox-cvs mailing list