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 */
25typedef struct lzma_index_s lzma_index;
26
27
28/**
29 * \brief Index Record and its location
30 */
31typedef 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 */
95extern 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 */
109extern 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 */
118extern 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 */
143extern 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 */
152extern 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 */
161extern 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 */
171extern 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 */
181extern 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 */
193extern 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 */
200extern 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 */
207extern 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 */
218extern 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 */
243extern 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 */
270extern 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 */
283extern 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 */
295extern 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 */
314extern 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 */
345extern 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 */
371extern 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 */
402extern 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