|
6ea30fb…
|
florian
|
1 |
/* zran.h -- example of deflate stream indexing and random access |
|
6ea30fb…
|
florian
|
2 |
* Copyright (C) 2005, 2012, 2018, 2023, 2024, 2025 Mark Adler |
|
adb9e8e…
|
drh
|
3 |
* For conditions of distribution and use, see copyright notice in zlib.h |
|
6ea30fb…
|
florian
|
4 |
* Version 1.7 16 May 2025 Mark Adler */ |
|
adb9e8e…
|
drh
|
5 |
|
|
adb9e8e…
|
drh
|
6 |
#include <stdio.h> |
|
adb9e8e…
|
drh
|
7 |
#include "zlib.h" |
|
adb9e8e…
|
drh
|
8 |
|
|
f1f1d6c…
|
drh
|
9 |
// Access point. |
|
f1f1d6c…
|
drh
|
10 |
typedef struct point { |
|
f1f1d6c…
|
drh
|
11 |
off_t out; // offset in uncompressed data |
|
f1f1d6c…
|
drh
|
12 |
off_t in; // offset in compressed file of first full byte |
|
f1f1d6c…
|
drh
|
13 |
int bits; // 0, or number of bits (1-7) from byte at in-1 |
|
6ea30fb…
|
florian
|
14 |
unsigned dict; // number of bytes in window to use as a dictionary |
|
6ea30fb…
|
florian
|
15 |
unsigned char *window; // preceding 32K (or less) of uncompressed data |
|
f1f1d6c…
|
drh
|
16 |
} point_t; |
|
f1f1d6c…
|
drh
|
17 |
|
|
f1f1d6c…
|
drh
|
18 |
// Access point list. |
|
adb9e8e…
|
drh
|
19 |
struct deflate_index { |
|
f1f1d6c…
|
drh
|
20 |
int have; // number of access points in list |
|
f1f1d6c…
|
drh
|
21 |
int mode; // -15 for raw, 15 for zlib, or 31 for gzip |
|
f1f1d6c…
|
drh
|
22 |
off_t length; // total length of uncompressed data |
|
f1f1d6c…
|
drh
|
23 |
point_t *list; // allocated list of access points |
|
6ea30fb…
|
florian
|
24 |
z_stream strm; // re-usable inflate engine for extraction |
|
adb9e8e…
|
drh
|
25 |
}; |
|
adb9e8e…
|
drh
|
26 |
|
|
f1f1d6c…
|
drh
|
27 |
// Make one pass through a zlib, gzip, or raw deflate compressed stream and |
|
f1f1d6c…
|
drh
|
28 |
// build an index, with access points about every span bytes of uncompressed |
|
f1f1d6c…
|
drh
|
29 |
// output. gzip files with multiple members are fully indexed. span should be |
|
f1f1d6c…
|
drh
|
30 |
// chosen to balance the speed of random access against the memory requirements |
|
f1f1d6c…
|
drh
|
31 |
// of the list, which is about 32K bytes per access point. The return value is |
|
f1f1d6c…
|
drh
|
32 |
// the number of access points on success (>= 1), Z_MEM_ERROR for out of |
|
f1f1d6c…
|
drh
|
33 |
// memory, Z_BUF_ERROR for a premature end of input, Z_DATA_ERROR for a format |
|
f1f1d6c…
|
drh
|
34 |
// or verification error in the input file, or Z_ERRNO for a file read error. |
|
6ea30fb…
|
florian
|
35 |
// On success, *built points to the resulting index, otherwise it's NULL. |
|
adb9e8e…
|
drh
|
36 |
int deflate_index_build(FILE *in, off_t span, struct deflate_index **built); |
|
adb9e8e…
|
drh
|
37 |
|
|
f1f1d6c…
|
drh
|
38 |
// Use the index to read len bytes from offset into buf. Return the number of |
|
f1f1d6c…
|
drh
|
39 |
// bytes read or a negative error code. If data is requested past the end of |
|
f1f1d6c…
|
drh
|
40 |
// the uncompressed data, then deflate_index_extract() will return a value less |
|
f1f1d6c…
|
drh
|
41 |
// than len, indicating how much was actually read into buf. If given a valid |
|
f1f1d6c…
|
drh
|
42 |
// index, this function should not return an error unless the file was modified |
|
f1f1d6c…
|
drh
|
43 |
// somehow since the index was generated, given that deflate_index_build() had |
|
f1f1d6c…
|
drh
|
44 |
// validated all of the input. If nevertheless there is a failure, Z_BUF_ERROR |
|
f1f1d6c…
|
drh
|
45 |
// is returned if the compressed data ends prematurely, Z_DATA_ERROR if the |
|
f1f1d6c…
|
drh
|
46 |
// deflate compressed data is not valid, Z_MEM_ERROR if out of memory, |
|
f1f1d6c…
|
drh
|
47 |
// Z_STREAM_ERROR if the index is not valid, or Z_ERRNO if there is an error |
|
f1f1d6c…
|
drh
|
48 |
// reading or seeking on the input file. |
|
f1f1d6c…
|
drh
|
49 |
ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, |
|
f1f1d6c…
|
drh
|
50 |
off_t offset, unsigned char *buf, size_t len); |
|
f1f1d6c…
|
drh
|
51 |
|
|
f1f1d6c…
|
drh
|
52 |
// Deallocate an index built by deflate_index_build(). |
|
f1f1d6c…
|
drh
|
53 |
void deflate_index_free(struct deflate_index *index); |