aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2023-04-13 15:33:03 -0700
committerMark Adler <madler@alumni.caltech.edu>2023-04-13 15:41:32 -0700
commit7e6dc429af8e430e3ae5e748fb34dd61128c5546 (patch)
tree1eb9d9aa7a3c6af2b42299a7217706e79b985ffe /examples
parenteb0e038b297f2c9877ed8b3515c6718a4b65d485 (diff)
downloadzlib-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.c93
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.
252static 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.
276static 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.
241ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, 330ptrdiff_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.