diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2023-04-13 15:33:03 -0700 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2023-04-13 15:41:32 -0700 |
commit | 7e6dc429af8e430e3ae5e748fb34dd61128c5546 (patch) | |
tree | 1eb9d9aa7a3c6af2b42299a7217706e79b985ffe /examples | |
parent | eb0e038b297f2c9877ed8b3515c6718a4b65d485 (diff) | |
download | zlib-7e6dc429af8e430e3ae5e748fb34dd61128c5546.tar.gz zlib-7e6dc429af8e430e3ae5e748fb34dd61128c5546.tar.bz2 zlib-7e6dc429af8e430e3ae5e748fb34dd61128c5546.zip |
Add a NOPRIME #define to zran.c to not use inflatePrime().
This supports zlib versions earlier than 1.2.3 (July 2005), as
well as incomplete clones of zlib that do not have inflatePrime().
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. |