X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fcompress.c;h=259e7a4caca38aa3434d7f4ac3742346428144a0;hp=32d5fb49fc28b0885ef261dfeece9bc3231d82f5;hb=719a063c87e3abab99b0fb53ebc80223fbf33123;hpb=883833a4b3dabec325edf1ca938000f91d587c00 diff --git a/src/compress.c b/src/compress.c index 32d5fb49..259e7a4c 100644 --- a/src/compress.c +++ b/src/compress.c @@ -6,22 +6,20 @@ */ /* - * Copyright (C) 2013 Eric Biggers + * Copyright (C) 2013, 2014 Eric Biggers * - * This file is part of wimlib, a library for working with WIM files. + * This file is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. * - * wimlib is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) - * any later version. - * - * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * - * You should have received a copy of the GNU General Public License - * along with wimlib; if not, see http://www.gnu.org/licenses/. + * You should have received a copy of the GNU Lesser General Public License + * along with this file; if not, see http://www.gnu.org/licenses/. */ #ifdef HAVE_CONFIG_H @@ -29,26 +27,28 @@ #endif #include "wimlib.h" +#include "wimlib/error.h" #include "wimlib/compressor_ops.h" #include "wimlib/util.h" struct wimlib_compressor { const struct compressor_ops *ops; void *private; + enum wimlib_compression_type ctype; + size_t max_block_size; }; static const struct compressor_ops *compressor_ops[] = { - [WIMLIB_COMPRESSION_TYPE_LZX] = &lzx_compressor_ops, [WIMLIB_COMPRESSION_TYPE_XPRESS] = &xpress_compressor_ops, + [WIMLIB_COMPRESSION_TYPE_LZX] = &lzx_compressor_ops, [WIMLIB_COMPRESSION_TYPE_LZMS] = &lzms_compressor_ops, }; -static struct wimlib_compressor_params_header * -compressor_default_params[ARRAY_LEN(compressor_ops)] = { - [WIMLIB_COMPRESSION_TYPE_LZX] = NULL, - [WIMLIB_COMPRESSION_TYPE_XPRESS] = NULL, - [WIMLIB_COMPRESSION_TYPE_LZMS] = NULL, -}; +/* Scale: 10 = low, 50 = medium, 100 = high */ + +#define DEFAULT_COMPRESSION_LEVEL 50 + +static unsigned int default_compression_levels[ARRAY_LEN(compressor_ops)]; static bool compressor_ctype_valid(int ctype) @@ -59,64 +59,104 @@ compressor_ctype_valid(int ctype) } WIMLIBAPI int -wimlib_set_default_compressor_params(enum wimlib_compression_type ctype, - const struct wimlib_compressor_params_header *params) +wimlib_set_default_compression_level(int ctype, unsigned int compression_level) { - struct wimlib_compressor_params_header *dup; - - if (!compressor_ctype_valid(ctype)) - return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; - - dup = NULL; - if (params) { - dup = memdup(params, params->size); - if (dup == NULL) - return WIMLIB_ERR_NOMEM; + if (ctype == -1) { + for (int i = 0; i < ARRAY_LEN(default_compression_levels); i++) + default_compression_levels[i] = compression_level; + } else { + if (!compressor_ctype_valid(ctype)) + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + + default_compression_levels[ctype] = compression_level; } - - FREE(compressor_default_params[ctype]); - compressor_default_params[ctype] = dup; return 0; } -void -cleanup_compressor_params(void) +WIMLIBAPI u64 +wimlib_get_compressor_needed_memory(enum wimlib_compression_type ctype, + size_t max_block_size, + unsigned int compression_level) { - for (size_t i = 0; i < ARRAY_LEN(compressor_default_params); i++) { - FREE(compressor_default_params[i]); - compressor_default_params[i] = NULL; + bool destructive; + const struct compressor_ops *ops; + u64 size; + + destructive = (compression_level & WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE); + compression_level &= ~WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE; + + if (!compressor_ctype_valid(ctype)) + return 0; + + if (compression_level > 0xFFFFFF) + return 0; + + if (max_block_size == 0) + return 0; + + ops = compressor_ops[ctype]; + + if (compression_level == 0) + compression_level = default_compression_levels[ctype]; + if (compression_level == 0) + compression_level = DEFAULT_COMPRESSION_LEVEL; + + if (ops->get_needed_memory) { + size = ops->get_needed_memory(max_block_size, compression_level, + destructive); + + /* 0 is never valid and indicates an invalid max_block_size. */ + if (size == 0) + return 0; + } else { + size = 0; } + return size + sizeof(struct wimlib_compressor); } WIMLIBAPI int wimlib_create_compressor(enum wimlib_compression_type ctype, size_t max_block_size, - const struct wimlib_compressor_params_header *extra_params, + unsigned int compression_level, struct wimlib_compressor **c_ret) { + bool destructive; struct wimlib_compressor *c; - if (c_ret == NULL) - return WIMLIB_ERR_INVALID_PARAM; + destructive = (compression_level & WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE); + compression_level &= ~WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE; if (!compressor_ctype_valid(ctype)) return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; + if (compression_level > 0xFFFFFF) + return WIMLIB_ERR_INVALID_PARAM; + + if (c_ret == NULL) + return WIMLIB_ERR_INVALID_PARAM; + + if (max_block_size == 0) + return WIMLIB_ERR_INVALID_PARAM; + c = MALLOC(sizeof(*c)); if (c == NULL) return WIMLIB_ERR_NOMEM; c->ops = compressor_ops[ctype]; c->private = NULL; + c->ctype = ctype; + c->max_block_size = max_block_size; if (c->ops->create_compressor) { - const struct wimlib_compressor_params_header *params; int ret; - if (extra_params) - params = extra_params; - else - params = compressor_default_params[ctype]; + if (compression_level == 0) + compression_level = default_compression_levels[ctype]; + if (compression_level == 0) + compression_level = DEFAULT_COMPRESSION_LEVEL; + ret = c->ops->create_compressor(max_block_size, - params, &c->private); + compression_level, + destructive, + &c->private); if (ret) { FREE(c); return ret; @@ -131,6 +171,9 @@ wimlib_compress(const void *uncompressed_data, size_t uncompressed_size, void *compressed_data, size_t compressed_size_avail, struct wimlib_compressor *c) { + if (unlikely(uncompressed_size == 0 || uncompressed_size > c->max_block_size)) + return 0; + return c->ops->compress(uncompressed_data, uncompressed_size, compressed_data, compressed_size_avail, c->private);