]> wimlib.net Git - wimlib/blob - src/compress_serial.c
01187ad383f2f2a8c4ad7f6bc54aca5ea4a158fd
[wimlib] / src / compress_serial.c
1 /*
2  * compress_serial.c
3  *
4  * Compress chunks of data (serial version).
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 Software
14  * Foundation; either version 3 of the License, or (at your option) any later
15  * 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 details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * wimlib; if not, see http://www.gnu.org/licenses/.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include "config.h"
27 #endif
28
29 #include "wimlib.h"
30 #include "wimlib/assert.h"
31 #include "wimlib/chunk_compressor.h"
32 #include "wimlib/util.h"
33
34 #include <string.h>
35
36 struct serial_chunk_compressor {
37         struct chunk_compressor base;
38         struct wimlib_compressor *compressor;
39         u8 *udata;
40         u8 *cdata;
41         u32 ulen;
42 };
43
44 static void
45 serial_chunk_compressor_destroy(struct chunk_compressor *_ctx)
46 {
47         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
48
49         if (ctx == NULL)
50                 return;
51
52         wimlib_free_compressor(ctx->compressor);
53         FREE(ctx->udata);
54         FREE(ctx->cdata);
55         FREE(ctx);
56 }
57
58 static bool
59 serial_chunk_compressor_submit_chunk(struct chunk_compressor *_ctx,
60                                      const void *chunk, u32 size)
61 {
62         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
63
64         if (ctx->ulen != 0)
65                 return false;
66
67         wimlib_assert(size > 0);
68         wimlib_assert(size <= ctx->base.out_chunk_size);
69
70         memcpy(ctx->udata, chunk, size);
71         ctx->ulen = size;
72         return true;
73 }
74
75 static bool
76 serial_chunk_compressor_get_chunk(struct chunk_compressor *_ctx,
77                                   const void **cdata_ret, u32 *csize_ret,
78                                   u32 *usize_ret)
79 {
80         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
81         u32 clen;
82
83         if (ctx->ulen == 0)
84                 return false;
85
86         clen = wimlib_compress(ctx->udata, ctx->ulen,
87                                ctx->cdata, ctx->ulen - 1,
88                                ctx->compressor);
89
90         if (clen) {
91                 *cdata_ret = ctx->cdata;
92                 *csize_ret = clen;
93         } else {
94                 *cdata_ret = ctx->udata;
95                 *csize_ret = ctx->ulen;
96         }
97         *usize_ret = ctx->ulen;
98
99         ctx->ulen = 0;
100         return true;
101 }
102
103 int
104 new_serial_chunk_compressor(int out_ctype, u32 out_chunk_size,
105                             struct chunk_compressor **compressor_ret)
106 {
107         struct serial_chunk_compressor *ctx;
108         int ret;
109
110         wimlib_assert(out_chunk_size > 0);
111
112         ctx = CALLOC(1, sizeof(*ctx));
113         if (ctx == NULL)
114                 return WIMLIB_ERR_NOMEM;
115
116         ctx->base.out_ctype = out_ctype;
117         ctx->base.out_chunk_size = out_chunk_size;
118         ctx->base.num_threads = 1;
119         ctx->base.destroy = serial_chunk_compressor_destroy;
120         ctx->base.submit_chunk = serial_chunk_compressor_submit_chunk;
121         ctx->base.get_chunk = serial_chunk_compressor_get_chunk;
122
123         ret = wimlib_create_compressor(out_ctype, out_chunk_size,
124                                        0, &ctx->compressor);
125         if (ret)
126                 goto err;
127
128         ctx->udata = MALLOC(out_chunk_size);
129         ctx->cdata = MALLOC(out_chunk_size - 1);
130         ctx->ulen = 0;
131         if (ctx->udata == NULL || ctx->cdata == NULL) {
132                 ret = WIMLIB_ERR_NOMEM;
133                 goto err;
134         }
135
136         *compressor_ret = &ctx->base;
137         return 0;
138
139 err:
140         serial_chunk_compressor_destroy(&ctx->base);
141         return ret;
142 }