# define o_stream_create_gz NULL
# define i_stream_create_deflate NULL
# define o_stream_create_deflate NULL
+# define compression_get_min_level_gz NULL
+# define compression_get_default_level_gz NULL
+# define compression_get_max_level_gz NULL
#endif
#ifndef HAVE_BZLIB
# define i_stream_create_bz2 NULL
# define o_stream_create_bz2 NULL
+# define compression_get_min_level_bz2 NULL
+# define compression_get_default_level_bz2 NULL
+# define compression_get_max_level_bz2 NULL
#endif
#ifndef HAVE_LZMA
# define i_stream_create_lzma NULL
#ifndef HAVE_LZ4
# define i_stream_create_lz4 NULL
# define o_stream_create_lz4 NULL
+# define compression_get_min_level_lz4 NULL
+# define compression_get_default_level_lz4 NULL
+# define compression_get_max_level_lz4 NULL
#endif
#ifndef HAVE_ZSTD
# define i_stream_create_zstd NULL
# define o_stream_create_zstd NULL
+# define compression_get_min_level_zstd NULL
+# define compression_get_default_level_zstd NULL
+# define compression_get_max_level_zstd NULL
#endif
static bool is_compressed_zlib(struct istream *input)
return -1;
}
+static int compression_get_min_level_unsupported(void)
+{
+ return -1;
+}
+
+static int compression_get_default_level_unsupported(void)
+{
+ return -1;
+}
+
+static int compression_get_max_level_unsupported(void)
+{
+ return -1;
+}
+
const struct compression_handler compression_handlers[] = {
{
.name = "gz",
.is_compressed = is_compressed_zlib,
.create_istream = i_stream_create_gz,
.create_ostream = o_stream_create_gz,
+ .get_min_level = compression_get_min_level_gz,
+ .get_default_level = compression_get_default_level_gz,
+ .get_max_level = compression_get_max_level_gz,
},
{
.name = "bz2",
.is_compressed = is_compressed_bzlib,
.create_istream = i_stream_create_bz2,
.create_ostream = o_stream_create_bz2,
+ .get_min_level = compression_get_min_level_bz2,
+ .get_default_level = compression_get_default_level_bz2,
+ .get_max_level = compression_get_max_level_bz2,
},
{
.name = "deflate",
.is_compressed = NULL,
.create_istream = i_stream_create_deflate,
.create_ostream = o_stream_create_deflate,
+ .get_min_level = compression_get_min_level_gz,
+ .get_default_level = compression_get_default_level_gz,
+ .get_max_level = compression_get_max_level_gz,
},
{
.name = "xz",
.is_compressed = is_compressed_xz,
.create_istream = i_stream_create_lzma,
.create_ostream = NULL,
+ .get_min_level = compression_get_min_level_unsupported,
+ .get_default_level = compression_get_default_level_unsupported,
+ .get_max_level = compression_get_max_level_unsupported,
},
{
.name = "lz4",
.is_compressed = is_compressed_lz4,
.create_istream = i_stream_create_lz4,
.create_ostream = o_stream_create_lz4,
+ .get_min_level = compression_get_min_level_lz4, /* does not actually support any of this */
+ .get_default_level = compression_get_default_level_lz4,
+ .get_max_level = compression_get_max_level_lz4,
},
{
.name = "zstd",
.is_compressed = is_compressed_zstd,
.create_istream = i_stream_create_zstd,
.create_ostream = o_stream_create_zstd,
+ .get_min_level = compression_get_min_level_zstd,
+ .get_default_level = compression_get_default_level_zstd,
+ .get_max_level = compression_get_max_level_zstd,
},
{
.name = "unsupported",
bool flushed:1;
};
+/* in bzlib, level is actually block size. From bzlib manual:
+
+ The block size affects both the compression ratio achieved,
+ and the amount of memory needed for compression and decompression.
+
+ BlockSize 1 through BlockSize 9 specify the block size to be 100,000 bytes
+ through 900,000 bytes respectively. The default is to use the maximum block
+ size.
+
+ Larger block sizes give rapidly diminishing marginal returns.
+ Most of the compression comes from the first two or three hundred k of
+ block size, a fact worth bearing in mind when using bzip2 on small machines.
+ It is also important to appreciate that the decompression memory
+ requirement is set at compression time by the choice of block size.
+
+ * In general, try and use the largest block size memory constraints
+ allow, since that maximises the compression achieved.
+ * Compression and decompression speed are virtually unaffected by block
+ size.
+
+ Another significant point applies to files which fit in a single block -
+ that means most files you'd encounter using a large block size. The
+ amount of real memory touched is proportional to the size of the file,
+ since the file is smaller than a block. For example, compressing a file
+ 20,000 bytes long with the flag BlockSize 9 will cause the compressor to
+ allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 kbytes
+ of it. Similarly, the decompressor will allocate 3700k but only
+ touch 100k + 20000 * 4 = 180 kbytes.
+*/
+
+int compression_get_min_level_bz2(void)
+{
+ return 1;
+}
+
+int compression_get_default_level_bz2(void)
+{
+ /* default is maximum level */
+ return 9;
+}
+
+int compression_get_max_level_bz2(void)
+{
+ return 9;
+}
+
static void o_stream_bzlib_close(struct iostream_private *stream,
bool close_parent)
{
unsigned int outbuf_offset, outbuf_used;
};
+/* There is no actual compression level in LZ4, so for legacy
+ reasons we allow 1-9 to avoid breaking anyone's config. */
+int compression_get_min_level_lz4(void)
+{
+ return 1;
+}
+
+int compression_get_default_level_lz4(void)
+{
+ return 1;
+}
+
+int compression_get_max_level_lz4(void)
+{
+ return 9;
+}
+
static void o_stream_lz4_close(struct iostream_private *stream,
bool close_parent)
{
bool flushed:1;
};
+int compression_get_min_level_gz(void)
+{
+ return Z_NO_COMPRESSION;
+}
+
+int compression_get_default_level_gz(void)
+{
+ return Z_DEFAULT_COMPRESSION;
+}
+
+int compression_get_max_level_gz(void)
+{
+ return Z_BEST_COMPRESSION;
+}
+
static void o_stream_zlib_close(struct iostream_private *stream,
bool close_parent)
{
struct zlib_ostream *zstream;
int ret;
- i_assert(level >= 1 && level <= 9);
+ /* accepted range is 0..9 and -1 is default compression */
+ i_assert(level >= -1 && level <= 9);
zstream = i_new(struct zlib_ostream, 1);
zstream->ostream.sendv = o_stream_zlib_sendv;
struct ostream *o_stream_create_lz4(struct ostream *output, int level);
struct ostream *o_stream_create_zstd(struct ostream *output, int level);
+int compression_get_min_level_gz(void);
+int compression_get_default_level_gz(void);
+int compression_get_max_level_gz(void);
+
+int compression_get_min_level_bz2(void);
+int compression_get_default_level_bz2(void);
+int compression_get_max_level_bz2(void);
+
+int compression_get_min_level_lz4(void);
+int compression_get_default_level_lz4(void);
+int compression_get_max_level_lz4(void);
+
+int compression_get_min_level_zstd(void);
+int compression_get_default_level_zstd(void);
+int compression_get_max_level_zstd(void);
+
#endif
bool finished:1;
};
+int compression_get_min_level_zstd(void)
+{
+#if HAVE_DECL_ZSTD_MINCLEVEL == 1
+ return ZSTD_minCLevel();
+#else
+ return 1;
+#endif
+}
+
+int compression_get_default_level_zstd(void)
+{
+#ifdef ZSTD_CLEVEL_DEFAULT
+ return ZSTD_CLEVEL_DEFAULT;
+#else
+ /* This means default */
+ return 0;
+#endif
+}
+
+int compression_get_max_level_zstd(void)
+{
+ return ZSTD_maxCLevel();
+}
+
static void o_stream_zstd_write_error(struct zstd_ostream *zstream, size_t err)
{
ZSTD_ErrorCode errcode = zstd_version_errcode(ZSTD_getErrorCode(err));