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