diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/zran.c | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/examples/zran.c b/examples/zran.c index 1ffba7f..32c9368 100644 --- a/examples/zran.c +++ b/examples/zran.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* zran.c -- example of deflate stream indexing and random access | 1 | /* zran.c -- example of deflate stream indexing and random access |
2 | * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler | 2 | * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | * Version 1.3 18 Feb 2023 Mark Adler */ | 4 | * Version 1.4 13 Apr 2023 Mark Adler */ |
5 | 5 | ||
6 | /* Version History: | 6 | /* Version History: |
7 | 1.0 29 May 2005 First version | 7 | 1.0 29 May 2005 First version |
@@ -13,6 +13,7 @@ | |||
13 | Support a size_t size when extracting (was an int) | 13 | Support a size_t size when extracting (was an int) |
14 | Do a binary search over the index for an access point | 14 | Do a binary search over the index for an access point |
15 | Expose the access point type to enable save and load | 15 | Expose the access point type to enable save and load |
16 | 1.4 13 Apr 2023 Add a NOPRIME define to not use inflatePrime() | ||
16 | */ | 17 | */ |
17 | 18 | ||
18 | // Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() | 19 | // Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() |
@@ -237,6 +238,94 @@ int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) { | |||
237 | return index->have; | 238 | return index->have; |
238 | } | 239 | } |
239 | 240 | ||
241 | #ifdef NOPRIME | ||
242 | // Support zlib versions before 1.2.3 (July 2005), or incomplete zlib clones | ||
243 | // that do not have inflatePrime(). | ||
244 | |||
245 | # define INFLATEPRIME inflatePreface | ||
246 | |||
247 | // Append the low bits bits of value to in[] at bit position *have, updating | ||
248 | // *have. value must be zero above its low bits bits. bits must be positive. | ||
249 | // This assumes that any bits above the *have bits in the last byte are zeros. | ||
250 | // That assumption is preserved on return, as any bits above *have + bits in | ||
251 | // the last byte written will be set to zeros. | ||
252 | static inline void append_bits(unsigned value, int bits, | ||
253 | unsigned char *in, int *have) { | ||
254 | in += *have >> 3; // where the first bits from value will go | ||
255 | int k = *have & 7; // the number of bits already there | ||
256 | *have += bits; | ||
257 | if (k) | ||
258 | *in |= value << k; // write value above the low k bits | ||
259 | else | ||
260 | *in = value; | ||
261 | k = 8 - k; // the number of bits just appended | ||
262 | while (bits > k) { | ||
263 | value >>= k; // drop the bits appended | ||
264 | bits -= k; | ||
265 | k = 8; // now at a byte boundary | ||
266 | *++in = value; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | // Insert enough bits in the form of empty deflate blocks in front of the the | ||
271 | // low bits bits of value, in order to bring the sequence to a byte boundary. | ||
272 | // Then feed that to inflate(). This does what inflatePrime() does, except that | ||
273 | // a negative value of bits is not supported. bits must be in 0..16. If the | ||
274 | // arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return | ||
275 | // value from inflate() is returned. | ||
276 | static int inflatePreface(z_stream *strm, int bits, int value) { | ||
277 | // Check input. | ||
278 | if (strm == Z_NULL || bits < 0 || bits > 16) | ||
279 | return Z_STREAM_ERROR; | ||
280 | if (bits == 0) | ||
281 | return Z_OK; | ||
282 | value &= (2 << (bits - 1)) - 1; | ||
283 | |||
284 | // An empty dynamic block with an odd number of bits (95). The high bit of | ||
285 | // the last byte is unused. | ||
286 | static const unsigned char dyn[] = { | ||
287 | 4, 0xe0, 0x81, 8, 0, 0, 0, 0, 0x20, 0xa8, 0xab, 0x1f | ||
288 | }; | ||
289 | const int dynlen = 95; // number of bits in the block | ||
290 | |||
291 | // Build an input buffer for inflate that is a multiple of eight bits in | ||
292 | // length, and that ends with the low bits bits of value. | ||
293 | unsigned char in[(dynlen + 3 * 10 + 16 + 7) / 8]; | ||
294 | int have = 0; | ||
295 | if (bits & 1) { | ||
296 | // Insert an empty dynamic block to get to an odd number of bits, so | ||
297 | // when bits bits from value are appended, we are at an even number of | ||
298 | // bits. | ||
299 | memcpy(in, dyn, sizeof(dyn)); | ||
300 | have = dynlen; | ||
301 | } | ||
302 | while ((have + bits) & 7) | ||
303 | // Insert empty fixed blocks until appending bits bits would put us on | ||
304 | // a byte boundary. This will insert at most three fixed blocks. | ||
305 | append_bits(2, 10, in, &have); | ||
306 | |||
307 | // Append the bits bits from value, which takes us to a byte boundary. | ||
308 | append_bits(value, bits, in, &have); | ||
309 | |||
310 | // Deliver the input to inflate(). There is no output space provided, but | ||
311 | // inflate() can't get stuck waiting on output not ingesting all of the | ||
312 | // provided input. The reason is that there will be at most 16 bits of | ||
313 | // input from value after the empty deflate blocks (which themselves | ||
314 | // generate no output). At least ten bits are needed to generate the first | ||
315 | // output byte from a fixed block. The last two bytes of the buffer have to | ||
316 | // be ingested in order to get ten bits, which is the most that value can | ||
317 | // occupy. | ||
318 | strm->avail_in = have >> 3; | ||
319 | strm->next_in = in; | ||
320 | strm->avail_out = 0; | ||
321 | strm->next_out = in; // not used, but can't be NULL | ||
322 | return inflate(strm, Z_NO_FLUSH); | ||
323 | } | ||
324 | |||
325 | #else | ||
326 | # define INFLATEPRIME inflatePrime | ||
327 | #endif | ||
328 | |||
240 | // See comments in zran.h. | 329 | // See comments in zran.h. |
241 | ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, | 330 | ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, |
242 | off_t offset, unsigned char *buf, size_t len) { | 331 | off_t offset, unsigned char *buf, size_t len) { |
@@ -272,7 +361,7 @@ ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, | |||
272 | if (ret != Z_OK) | 361 | if (ret != Z_OK) |
273 | return ret; | 362 | return ret; |
274 | if (point->bits) | 363 | if (point->bits) |
275 | inflatePrime(&strm, point->bits, ch >> (8 - point->bits)); | 364 | INFLATEPRIME(&strm, point->bits, ch >> (8 - point->bits)); |
276 | inflateSetDictionary(&strm, point->window, WINSIZE); | 365 | inflateSetDictionary(&strm, point->window, WINSIZE); |
277 | 366 | ||
278 | // Skip uncompressed bytes until offset reached, then satisfy request. | 367 | // Skip uncompressed bytes until offset reached, then satisfy request. |