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 | |
| 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().
| -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. |
