]> wimlib.net Git - wimlib/blob - include/wimlib/lz_mf.h
221418d6806270ca6c58063ed4238c0bd631ea4b
[wimlib] / include / wimlib / lz_mf.h
1 /*
2  * lz_mf.h
3  *
4  * Interface for Lempel-Ziv match-finders.
5  *
6  * Copyright (c) 2014 Eric Biggers.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*
33  * Example usage of the match-finder API:
34  *
35  * ----------------------------------------------------------------------------
36  *
37  * Fill in a 'struct lz_mf_params'.
38  * (Optional) Call lz_mf_params_valid() to validate the parameters.
39  * Call lz_mf_alloc() to allocate the match-finder.
40  * For each block of data to be compressed:
41  *      Call lz_mf_load_window() to load the block into the match finder.
42  *      While the block is not yet fully compressed:
43  *              Call lz_mf_get_matches() to get matches at the current position.
44  *              If matches were found:
45  *                      Output the longest match.
46  *                      Call lz_mf_skip_positions() to skip the remaining length of the match.
47  *              Else:
48  *                      Output a literal.
49  *              End If
50  *      End While
51  * End For
52  * Call lz_mf_free() to free the match-finder.
53  *
54  * ----------------------------------------------------------------------------
55  *
56  * That example did "greedy parsing" --- that is, always choosing the longest
57  * match at each position.  However, this interface can be (and is intended to
58  * be) used for "optimal parsing" as well.  It can also be used for in-between
59  * strategies such as "lazy parsing" and "flexible parsing".  For the best
60  * performance try different match-finding algorithms and parameters to see what
61  * works best for your parsing strategy, and your typical data and block sizes.
62  */
63
64 #ifndef _WIMLIB_LZ_MF_H
65 #define _WIMLIB_LZ_MF_H
66
67 #include "wimlib/types.h"
68
69 /* When ENABLE_LZ_DEBUG is defined, we check all matches for correctness and
70  * perform other validations.  Use for debugging only, as it slows things down
71  * significantly.  */
72
73 //#define ENABLE_LZ_DEBUG
74 #ifdef ENABLE_LZ_DEBUG
75 #  include <assert.h>
76 #  include <string.h>
77 #  define LZ_ASSERT assert
78 #else
79 #  define LZ_ASSERT(...)
80 #endif
81
82 struct lz_mf;
83
84 /* Representation of a Lempel-Ziv match.  */
85 struct lz_match {
86
87         /* The number of bytes matched.  */
88         u32 len;
89
90         /* The offset back from the current position that was matched.  */
91         u32 offset;
92 };
93
94 /*
95  * Specifies a match-finding algorithm.
96  */
97 enum lz_mf_algo {
98
99         /*
100          * Use the default algorithm for the specified maximum window size.
101          */
102         LZ_MF_DEFAULT = 0,
103
104         /*
105          * "Null" algorithm that never reports any matches.
106          *
107          * This algorithm exists for comparison, benchmarking, and testing
108          * purposes only.  It is not intended to be used in real compressors.
109          */
110         LZ_MF_NULL = 1,
111
112         /*
113          * Brute Force match-finding algorithm.
114          *
115          * This algorithm exists for comparison, benchmarking, and testing
116          * purposes only.  It is not intended to be used in real compressors.
117          */
118         LZ_MF_BRUTE_FORCE = 2,
119
120         /*
121          * Hash Chain match-finding algorithm.
122          *
123          * This works well on small windows.
124          *
125          * The memory usage is 4 bytes per position, plus 131072 bytes for a
126          * hash table.
127          *
128          * lz_mf_skip_positions() with this algorithm is very fast, so it's good
129          * if you're doing "greedy" rather than "optimal" parsing.  However, if
130          * using large windows you might be better off with binary trees or
131          * suffix arrays, even if doing greedy parsing.
132          */
133         LZ_MF_HASH_CHAINS = 3,
134
135         /*
136          * Binary Tree match-finding algorithm.
137          *
138          * This works well on small to medium-sized windows.
139          *
140          * The memory usage is 8 bytes per position, plus 262144 bytes for a
141          * hash table.
142          *
143          * lz_mf_skip_positions() with this algorithm takes a significant amount
144          * of time, almost as much as a call to lz_mf_get_matches().  This makes
145          * this algorithm better suited for optimal parsing than for greedy
146          * parsing.  However, if the window size becomes sufficiently large,
147          * this algorithm can outperform hash chains, even when using greedy
148          * parsing.
149          */
150         LZ_MF_BINARY_TREES = 4,
151
152         /*
153          * Longest Common Prefix Interval Tree match-finding algorithm.
154          *
155          * This is a suffix array-based algorithm.  It works well on medium to
156          * large windows.  However, due to an implementation detail, it is
157          * currently limited to a maximum window size of 33554432 bytes.
158          *
159          * The memory usage is 12 bytes per position.
160          *
161          * Unlike the hash chain and binary tree algorithms, the LCP interval
162          * tree algorithm performs most of its work in lz_mf_load_window().  The
163          * calls to lz_mf_get_matches() and lz_mf_skip_positions() take
164          * relatively little time, and lz_mf_skip_positions() is not much faster
165          * than lz_mf_get_matches().  Therefore, if you're using this algorithm
166          * you might as well be doing "optimal" rather than "greedy" parsing.
167          */
168         LZ_MF_LCP_INTERVAL_TREE = 5,
169
170         /*
171          * Linked Suffix Array match-finding algorithm.
172          *
173          * This can be used on very large windows.
174          *
175          * The memory usage is 14 bytes per position.
176          *
177          * Currently, this method usually performs slightly worse than the LCP
178          * interval tree algorithm.  However, it can be used on windows
179          * exceeding the 33554432 byte limit of the LCP interval tree algorithm.
180          */
181         LZ_MF_LINKED_SUFFIX_ARRAY = 6,
182 };
183
184 /* Parameters for Lempel-Ziv match-finding.  */
185 struct lz_mf_params {
186
187         /*
188          * The match-finding algorithm to use.  This must be one of the 'enum
189          * lz_mf_algo' constants defined above.
190          *
191          * If this is LZ_MF_DEFAULT, the default algorithm for the specified
192          * @max_window_size is used.
193          */
194         u32 algorithm;
195
196         /*
197          * The maximum window size, in bytes, that shall be supported by the
198          * match-finder.  This is the maximum size that can be passed to
199          * subsequent calls to lz_mf_load_window().
200          *
201          * Note: this interface is intended to be used for block compression, so
202          * none of the match-finding algorithms support sliding windows.  It's
203          * expected that the window for LZ match-finding simply be the block of
204          * data being compressed.
205          *
206          * Match-finders generally require an amount of memory proportional to
207          * this parameter.  Use lz_mf_get_needed_memory() to query the needed
208          * memory size for a specific match-finding algorithm and maximum window
209          * size.
210          *
211          * This parameter cannot be 0; there is no default value.
212          *
213          * Match-finding algorithms may place additional restrictions on this
214          * parameter.  However, currently only the LCP interval tree
215          * match-finding algorithm places such a restriction (it doesn't support
216          * windows larger than 33554432 bytes).
217          */
218         u32 max_window_size;
219
220         /*
221          * The minimum length, in bytes, of matches that can be produced by the
222          * match-finder (by a call to lz_mf_get_matches()).
223          *
224          * If this parameter is not 0, it must be 2 or greater.
225          *
226          * If this parameter is 0, the match-finding algorithm sets it to a
227          * default value.  The default value will be at least 2 and at most 16.
228          */
229         u32 min_match_len;
230
231         /*
232          * The maximum length, in bytes, of matches that can be produced by the
233          * match-finder (by a call to lz_mf_get_matches()).
234          *
235          * If this parameter is not 0, it must be greater than or equal to
236          * @min_match_len, or the default value the match-finding algorithm
237          * selected for @min_match_len in the case that @min_match_len was
238          * specified as 0.
239          *
240          * If this parameter is 0, the match-finding algorithm sets it to a
241          * default value.  In general, the caller must be prepared to handle
242          * arbitrarily long matches (up to the window size minus 1) in this
243          * case.
244          */
245         u32 max_match_len;
246
247         /*
248          * When using the hash chains or binary trees match-finding algorithm,
249          * this parameter defines the maximum number of search steps at each
250          * position.  A typical value to use is 32.  Higher values result in
251          * better matches and slower performance.
252          *
253          * The suffix array-based match-finding algorithms treat this parameter
254          * slightly differently because they find the longest matches first.
255          * They still honor the intent of the parameter but may scale it down to
256          * an appropriate value.
257          *
258          * If this parameter is 0, the match-finding algorithm sets it to a
259          * default value.
260          */
261         u32 max_search_depth;
262
263         /*
264          * When using the hash chains, binary trees, or LCP interval tree
265          * match-finding algorithm, this parameter defines the maximum match
266          * length to which the full algorithm will be applied.  This can also be
267          * thought of as the length above which the algorithm will not try to
268          * search for additional matches.
269          *
270          * Usually, setting this parameter to a reasonable value (such as 24,
271          * 32, or 48) will speed up match-finding but will not hurt the
272          * compression ratio too much.  This is because these settings of this
273          * parameter cause the match-finder to not waste too much time examining
274          * very long matches, which are already highly compressible.
275          *
276          * In addition, if the longest match exceeds this length, the
277          * match-finding algorithm will still report its full length.
278          *
279          * The linked suffix array match-finding algorithm ignores this
280          * parameter.
281          *
282          * If this parameter is 0, the match-finding algorithm sets it to a
283          * default value.
284          */
285         u32 nice_match_len;
286 };
287
288 /*
289  * Lempel-Ziv match-finder operations structure.
290  *
291  * Match-finding algorithms must fill in all members.  None can be left as 0 or
292  * NULL.
293  *
294  * Don't directly access any of the members outside of lz_mf.h and lz_mf.c.
295  * Instead, use the lz_mf_*() wrappers.
296  */
297 struct lz_mf_ops {
298         bool (*params_valid)(const struct lz_mf_params *);
299
300         u64 (*get_needed_memory)(u32 max_window_size);
301
302         bool (*init)(struct lz_mf *);
303
304         void (*load_window)(struct lz_mf *mf, const u8 *, u32);
305
306         u32 (*get_matches)(struct lz_mf *, struct lz_match *);
307
308         void (*skip_positions)(struct lz_mf *, u32);
309
310         void (*destroy)(struct lz_mf *);
311
312         size_t struct_size;
313 };
314
315 /*
316  * Lempel-Ziv match-finder structure.
317  *
318  * Match-finding algorithms must embed this structure inside a private
319  * structure.
320  *
321  * Don't directly access any of the members outside of lz_mf.h, lz_mf.c, and
322  * match-finding algorithms.  Instead, use the lz_mf_*() wrappers.
323  */
324 struct lz_mf {
325         struct lz_mf_params params;
326         struct lz_mf_ops ops;
327         const u8 *cur_window;
328         u32 cur_window_pos;
329         u32 cur_window_size;
330 };
331
332 extern bool
333 lz_mf_params_valid(const struct lz_mf_params *params);
334
335 extern u64
336 lz_mf_get_needed_memory(enum lz_mf_algo algorithm, u32 max_window_size);
337
338 extern struct lz_mf *
339 lz_mf_alloc(const struct lz_mf_params *params);
340
341 extern void
342 lz_mf_load_window(struct lz_mf *mf, const u8 *window, u32 size);
343
344 #ifdef ENABLE_LZ_DEBUG
345 extern u32
346 lz_mf_get_matches(struct lz_mf *mf, struct lz_match *matches);
347 #else
348 /* See non-inline definition for comment  */
349 static inline u32
350 lz_mf_get_matches(struct lz_mf *mf, struct lz_match *matches)
351 {
352         return mf->ops.get_matches(mf, matches);
353 }
354 #endif
355
356 #ifdef ENABLE_LZ_DEBUG
357 extern void
358 lz_mf_skip_positions(struct lz_mf *mf, u32 n);
359 #else
360 /* See non-inline definition for comment  */
361 static inline void
362 lz_mf_skip_positions(struct lz_mf *mf, u32 n)
363 {
364         mf->ops.skip_positions(mf, n);
365 }
366 #endif
367
368 extern void
369 lz_mf_free(struct lz_mf *mf);
370
371 /*
372  * Returns the match-finder's current position in the window.
373  *
374  * The current position begins at 0.  It increases by 1 when lz_mf_get_matches()
375  * is called, and by 'n' when lz_mf_skip_positions() is called.
376  *
377  * Note: The behavior is undefined if the match-finder is advanced beyond the
378  * end of the window.  (If this happens in ENABLE_LZ_DEBUG mode, an assertion
379  * will be triggered.)
380  */
381 static inline u32
382 lz_mf_get_position(const struct lz_mf *mf)
383 {
384         return mf->cur_window_pos;
385 }
386
387 /*
388  * Returns the number of bytes remaining in the window.
389  */
390 static inline u32
391 lz_mf_get_bytes_remaining(const struct lz_mf *mf)
392 {
393         return mf->cur_window_size - mf->cur_window_pos;
394 }
395
396 /*
397  * Returns a pointer to the current window, offset by the current position.
398  * Equivalently, this returns a pointer to the byte sequence that the next call
399  * to lz_mf_get_matches() will match against.
400  */
401 static inline const u8 *
402 lz_mf_get_window_ptr(const struct lz_mf *mf)
403 {
404         return &mf->cur_window[mf->cur_window_pos];
405 }
406
407 #endif /* _WIMLIB_LZ_MF_H */