]> wimlib.net Git - wimlib/blob - src/compress_serial.c
libattr is no longer needed
[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 usize;
41         u8 *result_data;
42         u32 result_size;
43 };
44
45 static void
46 serial_chunk_compressor_destroy(struct chunk_compressor *_ctx)
47 {
48         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
49
50         if (ctx == NULL)
51                 return;
52
53         wimlib_free_compressor(ctx->compressor);
54         FREE(ctx->udata);
55         FREE(ctx->cdata);
56         FREE(ctx);
57 }
58
59 static void *
60 serial_chunk_compressor_get_chunk_buffer(struct chunk_compressor *_ctx)
61 {
62         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
63
64         if (ctx->result_data)
65                 return NULL;
66         return ctx->udata;
67 }
68
69 static void
70 serial_chunk_compressor_signal_chunk_filled(struct chunk_compressor *_ctx, u32 usize)
71 {
72         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx;
73         u32 csize;
74
75         wimlib_assert(usize > 0);
76         wimlib_assert(usize <= ctx->base.out_chunk_size);
77
78         ctx->usize = usize;
79         csize = wimlib_compress(ctx->udata, usize, ctx->cdata, usize - 1,
80                                 ctx->compressor);
81         if (csize) {
82                 ctx->result_data = ctx->cdata;
83                 ctx->result_size = csize;
84         } else {
85                 ctx->result_data = ctx->udata;
86                 ctx->result_size = ctx->usize;
87         }
88 }
89
90 static bool
91 serial_chunk_compressor_get_compression_result(struct chunk_compressor *_ctx,
92                                                const void **cdata_ret, u32 *csize_ret,
93                                                u32 *usize_ret)
94 {
95         struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor *)_ctx;
96
97         if (!ctx->result_data)
98                 return false;
99
100         *cdata_ret = ctx->result_data;
101         *csize_ret = ctx->result_size;
102         *usize_ret = ctx->usize;
103
104         ctx->result_data = NULL;
105         return true;
106 }
107
108 int
109 new_serial_chunk_compressor(int out_ctype, u32 out_chunk_size,
110                             struct chunk_compressor **compressor_ret)
111 {
112         struct serial_chunk_compressor *ctx;
113         int ret;
114
115         wimlib_assert(out_chunk_size > 0);
116
117         ctx = CALLOC(1, sizeof(*ctx));
118         if (ctx == NULL)
119                 return WIMLIB_ERR_NOMEM;
120
121         ctx->base.out_ctype = out_ctype;
122         ctx->base.out_chunk_size = out_chunk_size;
123         ctx->base.num_threads = 1;
124         ctx->base.destroy = serial_chunk_compressor_destroy;
125         ctx->base.get_chunk_buffer = serial_chunk_compressor_get_chunk_buffer;
126         ctx->base.signal_chunk_filled = serial_chunk_compressor_signal_chunk_filled;
127         ctx->base.get_compression_result = serial_chunk_compressor_get_compression_result;
128
129         ret = wimlib_create_compressor(out_ctype, out_chunk_size,
130                                        WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE,
131                                        &ctx->compressor);
132         if (ret)
133                 goto err;
134
135         ctx->udata = MALLOC(out_chunk_size);
136         ctx->cdata = MALLOC(out_chunk_size - 1);
137         if (ctx->udata == NULL || ctx->cdata == NULL) {
138                 ret = WIMLIB_ERR_NOMEM;
139                 goto err;
140         }
141         ctx->result_data = NULL;
142
143         *compressor_ret = &ctx->base;
144         return 0;
145
146 err:
147         serial_chunk_compressor_destroy(&ctx->base);
148         return ret;
149 }