1 | /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | // vim: expandtab:ts=8:sw=4:softtabstop=4: |
3 | /** |
4 | * \file lzma/index.h |
5 | * \brief Handling of .xz Index lists |
6 | */ |
7 | |
8 | /* |
9 | * Author: Lasse Collin |
10 | * |
11 | * This file has been put into the public domain. |
12 | * You can do whatever you want with this file. |
13 | * |
14 | * See ../lzma.h for information about liblzma as a whole. |
15 | */ |
16 | |
17 | #ifndef LZMA_H_INTERNAL |
18 | # error Never include this file directly. Use <lzma.h> instead. |
19 | #endif |
20 | |
21 | |
22 | /** |
23 | * \brief Opaque data type to hold the Index |
24 | */ |
25 | typedef struct lzma_index_s lzma_index; |
26 | |
27 | |
28 | /** |
29 | * \brief Index Record and its location |
30 | */ |
31 | typedef struct { |
32 | /** |
33 | * \brief Total encoded size of a Block including Block Padding |
34 | * |
35 | * This value is useful if you need to know the actual size of the |
36 | * Block that the Block decoder will read. |
37 | */ |
38 | lzma_vli total_size; |
39 | |
40 | /** |
41 | * \brief Encoded size of a Block excluding Block Padding |
42 | * |
43 | * This value is stored in the Index. When doing random-access |
44 | * reading, you should give this value to the Block decoder along |
45 | * with uncompressed_size. |
46 | */ |
47 | lzma_vli unpadded_size; |
48 | |
49 | /** |
50 | * \brief Uncompressed Size of a Block |
51 | */ |
52 | lzma_vli uncompressed_size; |
53 | |
54 | /** |
55 | * \brief Compressed offset in the Stream(s) |
56 | * |
57 | * This is the offset of the first byte of the Block, that is, |
58 | * where you need to seek to decode the Block. The offset |
59 | * is relative to the beginning of the Stream, or if there are |
60 | * multiple Indexes combined, relative to the beginning of the |
61 | * first Stream. |
62 | */ |
63 | lzma_vli stream_offset; |
64 | |
65 | /** |
66 | * \brief Uncompressed offset |
67 | * |
68 | * When doing random-access reading, it is possible that the target |
69 | * offset is not exactly at Block boundary. One will need to compare |
70 | * the target offset against uncompressed_offset, and possibly decode |
71 | * and throw away some amount of data before reaching the target |
72 | * offset. |
73 | */ |
74 | lzma_vli uncompressed_offset; |
75 | |
76 | } lzma_index_record; |
77 | |
78 | |
79 | /** |
80 | * \brief Calculate memory usage for Index with given number of Records |
81 | * |
82 | * On disk, the size of the Index field depends on both the number of Records |
83 | * stored and how big values the Records store (due to variable-length integer |
84 | * encoding). When the Index is kept in lzma_index structure, the memory usage |
85 | * depends only on the number of Records stored in the Index. The size in RAM |
86 | * is almost always a lot bigger than in encoded form on disk. |
87 | * |
88 | * This function calculates an approximate amount of memory needed hold the |
89 | * given number of Records in lzma_index structure. This value may vary |
90 | * between liblzma versions if the internal implementation is modified. |
91 | * |
92 | * If you want to know how much memory an existing lzma_index structure is |
93 | * using, use lzma_index_memusage(lzma_index_count(i)). |
94 | */ |
95 | extern LZMA_API(uint64_t) lzma_index_memusage(lzma_vli record_count) |
96 | lzma_nothrow; |
97 | |
98 | |
99 | /** |
100 | * \brief Allocate and initialize a new lzma_index structure |
101 | * |
102 | * If i is NULL, a new lzma_index structure is allocated, initialized, |
103 | * and a pointer to it returned. If allocation fails, NULL is returned. |
104 | * |
105 | * If i is non-NULL, it is reinitialized and the same pointer returned. |
106 | * In this case, return value cannot be NULL or a different pointer than |
107 | * the i that was given as an argument. |
108 | */ |
109 | extern LZMA_API(lzma_index *) lzma_index_init( |
110 | lzma_index *i, lzma_allocator *allocator) lzma_nothrow; |
111 | |
112 | |
113 | /** |
114 | * \brief Deallocate the Index |
115 | * |
116 | * If i is NULL, this does nothing. |
117 | */ |
118 | extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator) |
119 | lzma_nothrow; |
120 | |
121 | |
122 | /** |
123 | * \brief Add a new Record to an Index |
124 | * |
125 | * \param i Pointer to a lzma_index structure |
126 | * \param allocator Pointer to lzma_allocator, or NULL to |
127 | * use malloc() |
128 | * \param unpadded_size Unpadded Size of a Block. This can be |
129 | * calculated with lzma_block_unpadded_size() |
130 | * after encoding or decoding the Block. |
131 | * \param uncompressed_size Uncompressed Size of a Block. This can be |
132 | * taken directly from lzma_block structure |
133 | * after encoding or decoding the Block. |
134 | * |
135 | * Appending a new Record does not affect the read position. |
136 | * |
137 | * \return - LZMA_OK |
138 | * - LZMA_MEM_ERROR |
139 | * - LZMA_DATA_ERROR: Compressed or uncompressed size of the |
140 | * Stream or size of the Index field would grow too big. |
141 | * - LZMA_PROG_ERROR |
142 | */ |
143 | extern LZMA_API(lzma_ret) lzma_index_append( |
144 | lzma_index *i, lzma_allocator *allocator, |
145 | lzma_vli unpadded_size, lzma_vli uncompressed_size) |
146 | lzma_nothrow lzma_attr_warn_unused_result; |
147 | |
148 | |
149 | /** |
150 | * \brief Get the number of Records |
151 | */ |
152 | extern LZMA_API(lzma_vli) lzma_index_count(const lzma_index *i) |
153 | lzma_nothrow lzma_attr_pure; |
154 | |
155 | |
156 | /** |
157 | * \brief Get the size of the Index field as bytes |
158 | * |
159 | * This is needed to verify the Backward Size field in the Stream Footer. |
160 | */ |
161 | extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i) |
162 | lzma_nothrow lzma_attr_pure; |
163 | |
164 | |
165 | /** |
166 | * \brief Get the total size of the Blocks |
167 | * |
168 | * This doesn't include the Stream Header, Stream Footer, Stream Padding, |
169 | * or Index fields. |
170 | */ |
171 | extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i) |
172 | lzma_nothrow lzma_attr_pure; |
173 | |
174 | |
175 | /** |
176 | * \brief Get the total size of the Stream |
177 | * |
178 | * If multiple Indexes have been combined, this works as if the Blocks |
179 | * were in a single Stream. |
180 | */ |
181 | extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i) |
182 | lzma_nothrow lzma_attr_pure; |
183 | |
184 | |
185 | /** |
186 | * \brief Get the total size of the file |
187 | * |
188 | * When no Indexes have been combined with lzma_index_cat(), this function is |
189 | * identical to lzma_index_stream_size(). If multiple Indexes have been |
190 | * combined, this includes also the headers of each separate Stream and the |
191 | * possible Stream Padding fields. |
192 | */ |
193 | extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i) |
194 | lzma_nothrow lzma_attr_pure; |
195 | |
196 | |
197 | /** |
198 | * \brief Get the uncompressed size of the Stream |
199 | */ |
200 | extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i) |
201 | lzma_nothrow lzma_attr_pure; |
202 | |
203 | |
204 | /** |
205 | * \brief Get the next Record from the Index |
206 | */ |
207 | extern LZMA_API(lzma_bool) lzma_index_read( |
208 | lzma_index *i, lzma_index_record *record) |
209 | lzma_nothrow lzma_attr_warn_unused_result; |
210 | |
211 | |
212 | /** |
213 | * \brief Rewind the Index |
214 | * |
215 | * Rewind the Index so that next call to lzma_index_read() will return the |
216 | * first Record. |
217 | */ |
218 | extern LZMA_API(void) lzma_index_rewind(lzma_index *i) lzma_nothrow; |
219 | |
220 | |
221 | /** |
222 | * \brief Locate a Record |
223 | * |
224 | * When the Index is available, it is possible to do random-access reading |
225 | * with granularity of Block size. |
226 | * |
227 | * \param i Pointer to lzma_index structure |
228 | * \param record Pointer to a structure to hold the search results |
229 | * \param target Uncompressed target offset which the caller would |
230 | * like to locate from the Stream |
231 | * |
232 | * If the target is smaller than the uncompressed size of the Stream (can be |
233 | * checked with lzma_index_uncompressed_size()): |
234 | * - Information about the Record containing the requested uncompressed |
235 | * offset is stored into *record. |
236 | * - Read offset will be adjusted so that calling lzma_index_read() can be |
237 | * used to read subsequent Records. |
238 | * - This function returns false. |
239 | * |
240 | * If target is greater than the uncompressed size of the Stream, *record |
241 | * and the read position are not modified, and this function returns true. |
242 | */ |
243 | extern LZMA_API(lzma_bool) lzma_index_locate( |
244 | lzma_index *i, lzma_index_record *record, lzma_vli target) |
245 | lzma_nothrow; |
246 | |
247 | |
248 | /** |
249 | * \brief Concatenate Indexes of two Streams |
250 | * |
251 | * Concatenating Indexes is useful when doing random-access reading in |
252 | * multi-Stream .xz file, or when combining multiple Streams into single |
253 | * Stream. |
254 | * |
255 | * \param dest Destination Index after which src is appended |
256 | * \param src Source Index. If this function succeeds, the |
257 | * memory allocated for src is freed or moved to |
258 | * be part of dest. |
259 | * \param allocator Custom memory allocator; can be NULL to use |
260 | * malloc() and free(). |
261 | * \param padding Size of the Stream Padding field between Streams. |
262 | * This must be a multiple of four. |
263 | * |
264 | * \return - LZMA_OK: Indexes concatenated successfully. src is now |
265 | * a dangling pointer. |
266 | * - LZMA_DATA_ERROR: *dest would grow too big. |
267 | * - LZMA_MEM_ERROR |
268 | * - LZMA_PROG_ERROR |
269 | */ |
270 | extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *lzma_restrict dest, |
271 | lzma_index *lzma_restrict src, |
272 | lzma_allocator *allocator, lzma_vli padding) |
273 | lzma_nothrow lzma_attr_warn_unused_result; |
274 | |
275 | |
276 | /** |
277 | * \brief Duplicate an Index list |
278 | * |
279 | * Makes an identical copy of the Index. Also the read position is copied. |
280 | * |
281 | * \return A copy of the Index, or NULL if memory allocation failed. |
282 | */ |
283 | extern LZMA_API(lzma_index *) lzma_index_dup( |
284 | const lzma_index *i, lzma_allocator *allocator) |
285 | lzma_nothrow lzma_attr_warn_unused_result; |
286 | |
287 | |
288 | /** |
289 | * \brief Compare if two Index lists are identical |
290 | * |
291 | * Read positions are not compared. |
292 | * |
293 | * \return True if *a and *b are equal, false otherwise. |
294 | */ |
295 | extern LZMA_API(lzma_bool) lzma_index_equal( |
296 | const lzma_index *a, const lzma_index *b) |
297 | lzma_nothrow lzma_attr_pure; |
298 | |
299 | |
300 | /** |
301 | * \brief Initialize .xz Index encoder |
302 | * |
303 | * \param strm Pointer to properly prepared lzma_stream |
304 | * \param i Pointer to lzma_index which should be encoded. |
305 | * The read position will be at the end of the Index |
306 | * after lzma_code() has returned LZMA_STREAM_END. |
307 | * |
308 | * The only valid action value for lzma_code() is LZMA_RUN. |
309 | * |
310 | * \return - LZMA_OK: Initialization succeeded, continue with lzma_code(). |
311 | * - LZMA_MEM_ERROR |
312 | * - LZMA_PROG_ERROR |
313 | */ |
314 | extern LZMA_API(lzma_ret) lzma_index_encoder(lzma_stream *strm, lzma_index *i) |
315 | lzma_nothrow lzma_attr_warn_unused_result; |
316 | |
317 | |
318 | /** |
319 | * \brief Initialize .xz Index decoder |
320 | * |
321 | * \param strm Pointer to properly prepared lzma_stream |
322 | * \param i Pointer to a pointer that will be made to point |
323 | * to the final decoded Index once lzma_code() has |
324 | * returned LZMA_STREAM_END. That is, |
325 | * lzma_index_decoder() always takes care of |
326 | * allocating a new lzma_index structure, and *i |
327 | * doesn't need to be initialized by the caller. |
328 | * \param memlimit How much memory the resulting Index is allowed |
329 | * to require. |
330 | * |
331 | * The only valid action value for lzma_code() is LZMA_RUN. |
332 | * |
333 | * \return - LZMA_OK: Initialization succeeded, continue with lzma_code(). |
334 | * - LZMA_MEM_ERROR |
335 | * - LZMA_MEMLIMIT_ERROR |
336 | * - LZMA_PROG_ERROR |
337 | * |
338 | * \note The memory usage limit is checked early in the decoding |
339 | * (within the first dozen input bytes or so). The actual memory |
340 | * is allocated later in smaller pieces. If the memory usage |
341 | * limit is modified with lzma_memlimit_set() after a part |
342 | * of the Index has already been decoded, the new limit may |
343 | * get ignored. |
344 | */ |
345 | extern LZMA_API(lzma_ret) lzma_index_decoder( |
346 | lzma_stream *strm, lzma_index **i, uint64_t memlimit) |
347 | lzma_nothrow lzma_attr_warn_unused_result; |
348 | |
349 | |
350 | /** |
351 | * \brief Single-call .xz Index encoder |
352 | * |
353 | * \param i Index to be encoded. The read position will be at |
354 | * the end of the Index if encoding succeeds, or at |
355 | * unspecified position in case an error occurs. |
356 | * \param out Beginning of the output buffer |
357 | * \param out_pos The next byte will be written to out[*out_pos]. |
358 | * *out_pos is updated only if encoding succeeds. |
359 | * \param out_size Size of the out buffer; the first byte into |
360 | * which no data is written to is out[out_size]. |
361 | * |
362 | * \return - LZMA_OK: Encoding was successful. |
363 | * - LZMA_BUF_ERROR: Output buffer is too small. Use |
364 | * lzma_index_size() to find out how much output |
365 | * space is needed. |
366 | * - LZMA_PROG_ERROR |
367 | * |
368 | * \note This function doesn't take allocator argument since all |
369 | * the internal data is allocated on stack. |
370 | */ |
371 | extern LZMA_API(lzma_ret) lzma_index_buffer_encode(lzma_index *i, |
372 | uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow; |
373 | |
374 | |
375 | /** |
376 | * \brief Single-call .xz Index decoder |
377 | * |
378 | * \param i Pointer to a pointer that will be made to point |
379 | * to the final decoded Index if decoding is |
380 | * successful. That is, lzma_index_buffer_decode() |
381 | * always takes care of allocating a new |
382 | * lzma_index structure, and *i doesn't need to be |
383 | * initialized by the caller. |
384 | * \param memlimit Pointer to how much memory the resulting Index |
385 | * is allowed to require. The value pointed by |
386 | * this pointer is modified if and only if |
387 | * LZMA_MEMLIMIT_ERROR is returned. |
388 | * \param allocator Pointer to lzma_allocator, or NULL to use malloc() |
389 | * \param in Beginning of the input buffer |
390 | * \param in_pos The next byte will be read from in[*in_pos]. |
391 | * *in_pos is updated only if decoding succeeds. |
392 | * \param in_size Size of the input buffer; the first byte that |
393 | * won't be read is in[in_size]. |
394 | * |
395 | * \return - LZMA_OK: Decoding was successful. |
396 | * - LZMA_MEM_ERROR |
397 | * - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached. |
398 | * The minimum required memlimit value was stored to *memlimit. |
399 | * - LZMA_DATA_ERROR |
400 | * - LZMA_PROG_ERROR |
401 | */ |
402 | extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i, |
403 | uint64_t *memlimit, lzma_allocator *allocator, |
404 | const uint8_t *in, size_t *in_pos, size_t in_size) |
405 | lzma_nothrow; |
406 | |