]> wimlib.net Git - wimlib/blob - src/lzms-compress.c
Share LZMS x86 filter between compressor and decompressor
[wimlib] / src / lzms-compress.c
1 /*
2  * lzms-compress.c
3  *
4  * A compressor for the LZMS compression format.
5  */
6
7 /*
8  * Copyright (C) 2013 Eric Biggers
9  *
10  * This file is part of wimlib, a library for working with WIM files.
11  *
12  * wimlib is free software; you can redistribute it and/or modify it under the
13  * terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 3 of the License, or (at your option)
15  * any later version.
16  *
17  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19  * A PARTICULAR PURPOSE. See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with wimlib; if not, see http://www.gnu.org/licenses/.
24  */
25
26 /* This a compressor for the LZMS compression format.  More details about this
27  * format can be found in lzms-decompress.c.  */
28
29 #ifdef HAVE_CONFIG_H
30 #  include "config.h"
31 #endif
32
33 #include "wimlib.h"
34 #include "wimlib/assert.h"
35 #include "wimlib/compressor_ops.h"
36 #include "wimlib/compress_common.h"
37 #include "wimlib/endianness.h"
38 #include "wimlib/error.h"
39 #include "wimlib/lzms.h"
40 #include "wimlib/util.h"
41
42 #include <string.h>
43
44 struct lzms_compressor {
45         u8 *window;
46         u32 window_size;
47         u32 max_block_size;
48         s32 *last_target_usages;
49 };
50
51 static size_t
52 lzms_compress(const void *uncompressed_data, size_t uncompressed_size,
53               void *compressed_data, size_t compressed_size_avail, void *_ctx)
54 {
55         struct lzms_compressor *ctx = _ctx;
56
57         if (uncompressed_size > ctx->max_block_size) {
58                 LZMS_DEBUG("Can't compress %su bytes: LZMS context "
59                            "only supports %u bytes",
60                            uncompressed_size, ctx->max_block_size);
61                 return 0;
62         }
63
64         memcpy(ctx->window, uncompressed_data, uncompressed_size);
65         ctx->window_size = uncompressed_size;
66
67         lzms_x86_filter(ctx->window, ctx->window_size,
68                         ctx->last_target_usages, false);
69
70         return 0;
71 }
72
73 static void
74 lzms_free_compressor(void *_ctx)
75 {
76         struct lzms_compressor *ctx = _ctx;
77
78         if (ctx) {
79                 FREE(ctx->window);
80                 FREE(ctx->last_target_usages);
81                 FREE(ctx);
82         }
83 }
84
85 static int
86 lzms_create_compressor(size_t max_block_size,
87                        const struct wimlib_compressor_params_header *params,
88                        void **ctx_ret)
89 {
90         struct lzms_compressor *ctx;
91
92         if (max_block_size == 0 || max_block_size > 1U << 26) {
93                 LZMS_DEBUG("Invalid max_block_size (%u)", max_block_size);
94                 return WIMLIB_ERR_INVALID_PARAM;
95         }
96
97         ctx = CALLOC(1, sizeof(struct lzms_compressor));
98         if (ctx == NULL)
99                 goto oom;
100
101         ctx->window = MALLOC(max_block_size);
102         if (ctx->window == NULL)
103                 goto oom;
104         ctx->max_block_size = max_block_size;
105
106         ctx->last_target_usages = MALLOC(65536 * sizeof(ctx->last_target_usages[0]));
107         if (ctx->last_target_usages == NULL)
108                 goto oom;
109
110         *ctx_ret = ctx;
111         return 0;
112
113 oom:
114         lzms_free_compressor(ctx);
115         return WIMLIB_ERR_NOMEM;
116 }
117
118 const struct compressor_ops lzms_compressor_ops = {
119         .create_compressor  = lzms_create_compressor,
120         .compress           = lzms_compress,
121         .free_compressor    = lzms_free_compressor,
122 };