]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/common.h
Remove some redundant code from LZMA encoder.
[icculus/xz.git] / src / liblzma / common / common.h
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       common.h
4 /// \brief      Definitions common to the whole liblzma library
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #ifndef LZMA_COMMON_H
21 #define LZMA_COMMON_H
22
23 #include "../../common/sysdefs.h"
24 #include "../../common/integer.h"
25
26 // Don't use ifdef...
27 #if HAVE_VISIBILITY
28 #       define LZMA_API __attribute__((__visibility__("default")))
29 #else
30 #       define LZMA_API
31 #endif
32
33
34 // These allow helping the compiler in some often-executed branches, whose
35 // result is almost always the same.
36 #ifdef __GNUC__
37 #       define likely(expr) __builtin_expect(expr, true)
38 #       define unlikely(expr) __builtin_expect(expr, false)
39 #else
40 #       define likely(expr) (expr)
41 #       define unlikely(expr) (expr)
42 #endif
43
44
45 /// Size of temporary buffers needed in some filters
46 #define LZMA_BUFFER_SIZE 4096
47
48
49 /// Internal helper filter used by Subblock decoder. It is mapped to an
50 /// otherwise invalid Filter ID, which is impossible to get from any input
51 /// file (even if malicious file).
52 #define LZMA_FILTER_SUBBLOCK_HELPER (UINT64_MAX - 2)
53
54
55 ///////////
56 // Types //
57 ///////////
58
59 typedef struct lzma_coder_s lzma_coder;
60
61 typedef struct lzma_next_coder_s lzma_next_coder;
62
63 typedef struct lzma_filter_info_s lzma_filter_info;
64
65
66 typedef lzma_ret (*lzma_init_function)(
67                 lzma_next_coder *next, lzma_allocator *allocator,
68                 const lzma_filter_info *filters);
69
70 typedef lzma_ret (*lzma_code_function)(
71                 lzma_coder *coder, lzma_allocator *allocator,
72                 const uint8_t *restrict in, size_t *restrict in_pos,
73                 size_t in_size, uint8_t *restrict out,
74                 size_t *restrict out_pos, size_t out_size,
75                 lzma_action action);
76
77 typedef void (*lzma_end_function)(
78                 lzma_coder *coder, lzma_allocator *allocator);
79
80
81 /// Hold data and function pointers of the next filter in the chain.
82 struct lzma_next_coder_s {
83         /// Pointer to coder-specific data
84         lzma_coder *coder;
85
86         /// "Pointer" to init function. This is never called here.
87         /// We need only to detect if we are initializing a coder
88         /// that was allocated earlier. See code.c and next_coder.c.
89         uintptr_t init;
90
91         /// Pointer to function to do the actual coding
92         lzma_code_function code;
93
94         /// Pointer to function to free lzma_next_coder.coder
95         lzma_end_function end;
96 };
97
98 #define LZMA_NEXT_CODER_INIT \
99         (lzma_next_coder){ \
100                 .coder = NULL, \
101                 .init = 0, \
102                 .code = NULL, \
103                 .end = NULL, \
104         }
105
106
107 struct lzma_internal_s {
108         lzma_next_coder next;
109
110         enum {
111                 ISEQ_RUN,
112                 ISEQ_SYNC_FLUSH,
113                 ISEQ_FULL_FLUSH,
114                 ISEQ_FINISH,
115                 ISEQ_END,
116                 ISEQ_ERROR,
117         } sequence;
118
119         bool supported_actions[4];
120         bool allow_buf_error;
121         size_t avail_in;
122 };
123
124
125 struct lzma_filter_info_s {
126         /// Pointer to function used to initialize the filter.
127         /// This is NULL to indicate end of array.
128         lzma_init_function init;
129
130         /// Pointer to filter's options structure
131         void *options;
132 };
133
134
135 /*
136 typedef struct {
137         lzma_init_function init;
138         uint32_t (*input_alignment)(lzma_vli id, const void *options);
139         uint32_t (*output_alignment)(lzma_vli id, const void *options);
140         bool changes_uncompressed_size;
141         bool supports_eopm;
142 } lzma_filter_hook;
143 */
144
145
146 ///////////////
147 // Functions //
148 ///////////////
149
150 /// Allocates memory
151 extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
152                 lzma_attribute((malloc));
153
154 /// Frees memory
155 extern void lzma_free(void *ptr, lzma_allocator *allocator);
156
157 /// Initializes lzma_stream FIXME desc
158 extern lzma_ret lzma_strm_init(lzma_stream *strm);
159
160 ///
161 extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
162                 lzma_allocator *allocator, const lzma_filter_info *filters);
163
164 ///
165 extern void lzma_next_coder_end(lzma_next_coder *next,
166                 lzma_allocator *allocator);
167
168
169 /// \brief      Wrapper for memcpy()
170 ///
171 /// This function copies as much data as possible from in[] to out[] and
172 /// updates *in_pos and *out_pos accordingly.
173 ///
174 static inline size_t
175 bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size,
176                 uint8_t *restrict out, size_t *restrict out_pos,
177                 size_t out_size)
178 {
179         const size_t in_avail = in_size - *in_pos;
180         const size_t out_avail = out_size - *out_pos;
181         const size_t copy_size = MIN(in_avail, out_avail);
182
183         memcpy(out + *out_pos, in + *in_pos, copy_size);
184
185         *in_pos += copy_size;
186         *out_pos += copy_size;
187
188         return copy_size;
189 }
190
191
192 /// \brief      Initializing the next coder
193 ///
194 /// lzma_next_coder can point to different types of coders. The existing
195 /// coder may be different than what we are initializing now. In that case
196 /// we must git rid of the old coder first. Otherwise we reuse the existing
197 /// coder structure.
198 ///
199 #define lzma_next_coder_init2(next, allocator, cmpfunc, func, ...) \
200 do { \
201         if ((uintptr_t)(&cmpfunc) != (next)->init) \
202                 lzma_next_coder_end(next, allocator); \
203         const lzma_ret ret = func(next, __VA_ARGS__); \
204         if (ret == LZMA_OK) { \
205                 (next)->init = (uintptr_t)(&cmpfunc); \
206                 assert((next)->code != NULL); \
207                 assert((next)->end != NULL); \
208         } else { \
209                 lzma_next_coder_end(next, allocator); \
210         } \
211         return ret; \
212 } while (0)
213
214 /// \brief      Initializing lzma_next_coder
215 ///
216 /// Call the initialization function, which must take at least one
217 /// argument in addition to lzma_next_coder and lzma_allocator.
218 #define lzma_next_coder_init(func, next, allocator, ...) \
219         lzma_next_coder_init2(next, allocator, \
220                         func, func, allocator, __VA_ARGS__)
221
222 /// \brief      Initializing lzma_next_coder
223 ///
224 /// Call the initialization function, which takes no other arguments than
225 /// lzma_next_coder and lzma_allocator.
226 #define lzma_next_coder_init0(func, next, allocator) \
227         lzma_next_coder_init2(next, allocator, func, func, allocator)
228
229
230 /// \brief      Initializing lzma_stream
231 ///
232 /// lzma_strm initialization with more detailed options.
233 #define lzma_next_strm_init2(strm, cmpfunc, func, ...) \
234 do { \
235         lzma_ret ret = lzma_strm_init(strm); \
236         if (ret != LZMA_OK) \
237                 return ret; \
238         if ((uintptr_t)(&cmpfunc) != (strm)->internal->next.init) \
239                 lzma_next_coder_end(\
240                                 &(strm)->internal->next, (strm)->allocator); \
241         ret = func(&(strm)->internal->next, __VA_ARGS__); \
242         if (ret != LZMA_OK) { \
243                 lzma_end(strm); \
244                 return ret; \
245         } \
246         (strm)->internal->next.init = (uintptr_t)(&cmpfunc); \
247         assert((strm)->internal->next.code != NULL); \
248         assert((strm)->internal->next.end != NULL); \
249 } while (0)
250
251 /// \brief      Initializing lzma_stream
252 ///
253 /// Call the initialization function, which must take at least one
254 /// argument in addition to lzma_next_coder and lzma_allocator.
255 #define lzma_next_strm_init(strm, func, ...) \
256         lzma_next_strm_init2(strm, func, func, (strm)->allocator, __VA_ARGS__)
257
258 /// \brief      Initializing lzma_stream
259 ///
260 /// Call the initialization function, which takes no other arguments than
261 /// lzma_next_coder and lzma_allocator.
262 #define lzma_next_strm_init0(strm, func) \
263         lzma_next_strm_init2(strm, func, func, (strm)->allocator)
264
265
266 /// \brief      Return if expression doesn't evaluate to LZMA_OK
267 ///
268 /// There are several situations where we want to return immediatelly
269 /// with the value of expr if it isn't LZMA_OK. This macro shortens
270 /// the code a bit.
271 ///
272 #define return_if_error(expr) \
273 do { \
274         const lzma_ret ret_ = expr; \
275         if (ret_ != LZMA_OK) \
276                 return ret_; \
277 } while (0)
278
279 #endif