]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/pg_lzcompress.c
Fix end-of-loop optimization in pglz_find_match() function.
[postgresql] / src / backend / utils / adt / pg_lzcompress.c
1 /* ----------
2  * pg_lzcompress.c -
3  *
4  *              This is an implementation of LZ compression for PostgreSQL.
5  *              It uses a simple history table and generates 2-3 byte tags
6  *              capable of backward copy information for 3-273 bytes with
7  *              a max offset of 4095.
8  *
9  *              Entry routines:
10  *
11  *                      bool
12  *                      pglz_compress(const char *source, int32 slen, PGLZ_Header *dest,
13  *                                                const PGLZ_Strategy *strategy);
14  *
15  *                              source is the input data to be compressed.
16  *
17  *                              slen is the length of the input data.
18  *
19  *                              dest is the output area for the compressed result.
20  *                                      It must be at least as big as PGLZ_MAX_OUTPUT(slen).
21  *
22  *                              strategy is a pointer to some information controlling
23  *                                      the compression algorithm. If NULL, the compiled
24  *                                      in default strategy is used.
25  *
26  *                              The return value is TRUE if compression succeeded,
27  *                              FALSE if not; in the latter case the contents of dest
28  *                              are undefined.
29  *
30  *                      void
31  *                      pglz_decompress(const PGLZ_Header *source, char *dest)
32  *
33  *                              source is the compressed input.
34  *
35  *                              dest is the area where the uncompressed data will be
36  *                                      written to. It is the callers responsibility to
37  *                                      provide enough space. The required amount can be
38  *                                      obtained with the macro PGLZ_RAW_SIZE(source).
39  *
40  *                                      The data is written to buff exactly as it was handed
41  *                                      to pglz_compress(). No terminating zero byte is added.
42  *
43  *              The decompression algorithm and internal data format:
44  *
45  *                      PGLZ_Header is defined as
46  *
47  *                              typedef struct PGLZ_Header {
48  *                                      int32           vl_len_;
49  *                                      int32           rawsize;
50  *                              }
51  *
52  *                      The header is followed by the compressed data itself.
53  *
54  *                      The data representation is easiest explained by describing
55  *                      the process of decompression.
56  *
57  *                      If VARSIZE(x) == rawsize + sizeof(PGLZ_Header), then the data
58  *                      is stored uncompressed as plain bytes. Thus, the decompressor
59  *                      simply copies rawsize bytes from the location after the
60  *                      header to the destination.
61  *
62  *                      Otherwise the first byte after the header tells what to do
63  *                      the next 8 times. We call this the control byte.
64  *
65  *                      An unset bit in the control byte means, that one uncompressed
66  *                      byte follows, which is copied from input to output.
67  *
68  *                      A set bit in the control byte means, that a tag of 2-3 bytes
69  *                      follows. A tag contains information to copy some bytes, that
70  *                      are already in the output buffer, to the current location in
71  *                      the output. Let's call the three tag bytes T1, T2 and T3. The
72  *                      position of the data to copy is coded as an offset from the
73  *                      actual output position.
74  *
75  *                      The offset is in the upper nibble of T1 and in T2.
76  *                      The length is in the lower nibble of T1.
77  *
78  *                      So the 16 bits of a 2 byte tag are coded as
79  *
80  *                              7---T1--0  7---T2--0
81  *                              OOOO LLLL  OOOO OOOO
82  *
83  *                      This limits the offset to 1-4095 (12 bits) and the length
84  *                      to 3-18 (4 bits) because 3 is always added to it. To emit
85  *                      a tag of 2 bytes with a length of 2 only saves one control
86  *                      bit. But we lose one byte in the possible length of a tag.
87  *
88  *                      In the actual implementation, the 2 byte tag's length is
89  *                      limited to 3-17, because the value 0xF in the length nibble
90  *                      has special meaning. It means, that the next following
91  *                      byte (T3) has to be added to the length value of 18. That
92  *                      makes total limits of 1-4095 for offset and 3-273 for length.
93  *
94  *                      Now that we have successfully decoded a tag. We simply copy
95  *                      the output that occurred <offset> bytes back to the current
96  *                      output location in the specified <length>. Thus, a
97  *                      sequence of 200 spaces (think about bpchar fields) could be
98  *                      coded in 4 bytes. One literal space and a three byte tag to
99  *                      copy 199 bytes with a -1 offset. Whow - that's a compression
100  *                      rate of 98%! Well, the implementation needs to save the
101  *                      original data size too, so we need another 4 bytes for it
102  *                      and end up with a total compression rate of 96%, what's still
103  *                      worth a Whow.
104  *
105  *              The compression algorithm
106  *
107  *                      The following uses numbers used in the default strategy.
108  *
109  *                      The compressor works best for attributes of a size between
110  *                      1K and 1M. For smaller items there's not that much chance of
111  *                      redundancy in the character sequence (except for large areas
112  *                      of identical bytes like trailing spaces) and for bigger ones
113  *                      our 4K maximum look-back distance is too small.
114  *
115  *                      The compressor creates a table for lists of positions.
116  *                      For each input position (except the last 3), a hash key is
117  *                      built from the 4 next input bytes and the position remembered
118  *                      in the appropriate list. Thus, the table points to linked
119  *                      lists of likely to be at least in the first 4 characters
120  *                      matching strings. This is done on the fly while the input
121  *                      is compressed into the output area.  Table entries are only
122  *                      kept for the last 4096 input positions, since we cannot use
123  *                      back-pointers larger than that anyway.  The size of the hash
124  *                      table is chosen based on the size of the input - a larger table
125  *                      has a larger startup cost, as it needs to be initialized to
126  *                      zero, but reduces the number of hash collisions on long inputs.
127  *
128  *                      For each byte in the input, its hash key (built from this
129  *                      byte and the next 3) is used to find the appropriate list
130  *                      in the table. The lists remember the positions of all bytes
131  *                      that had the same hash key in the past in increasing backward
132  *                      offset order. Now for all entries in the used lists, the
133  *                      match length is computed by comparing the characters from the
134  *                      entries position with the characters from the actual input
135  *                      position.
136  *
137  *                      The compressor starts with a so called "good_match" of 128.
138  *                      It is a "prefer speed against compression ratio" optimizer.
139  *                      So if the first entry looked at already has 128 or more
140  *                      matching characters, the lookup stops and that position is
141  *                      used for the next tag in the output.
142  *
143  *                      For each subsequent entry in the history list, the "good_match"
144  *                      is lowered by 10%. So the compressor will be more happy with
145  *                      short matches the farer it has to go back in the history.
146  *                      Another "speed against ratio" preference characteristic of
147  *                      the algorithm.
148  *
149  *                      Thus there are 3 stop conditions for the lookup of matches:
150  *
151  *                              - a match >= good_match is found
152  *                              - there are no more history entries to look at
153  *                              - the next history entry is already too far back
154  *                                to be coded into a tag.
155  *
156  *                      Finally the match algorithm checks that at least a match
157  *                      of 3 or more bytes has been found, because thats the smallest
158  *                      amount of copy information to code into a tag. If so, a tag
159  *                      is omitted and all the input bytes covered by that are just
160  *                      scanned for the history add's, otherwise a literal character
161  *                      is omitted and only his history entry added.
162  *
163  *              Acknowledgements:
164  *
165  *                      Many thanks to Adisak Pochanayon, who's article about SLZ
166  *                      inspired me to write the PostgreSQL compression this way.
167  *
168  *                      Jan Wieck
169  *
170  * Copyright (c) 1999-2013, PostgreSQL Global Development Group
171  *
172  * src/backend/utils/adt/pg_lzcompress.c
173  * ----------
174  */
175 #include "postgres.h"
176
177 #include <limits.h>
178
179 #include "utils/pg_lzcompress.h"
180
181
182 /* ----------
183  * Local definitions
184  * ----------
185  */
186 #define PGLZ_MAX_HISTORY_LISTS  8192    /* must be power of 2 */
187 #define PGLZ_HISTORY_SIZE               4096
188 #define PGLZ_MAX_MATCH                  273
189
190
191 /* ----------
192  * PGLZ_HistEntry -
193  *
194  *              Linked list for the backward history lookup
195  *
196  * All the entries sharing a hash key are linked in a doubly linked list.
197  * This makes it easy to remove an entry when it's time to recycle it
198  * (because it's more than 4K positions old).
199  * ----------
200  */
201 typedef struct PGLZ_HistEntry
202 {
203         struct PGLZ_HistEntry *next;    /* links for my hash key's list */
204         struct PGLZ_HistEntry *prev;
205         int                     hindex;                 /* my current hash key */
206         const char *pos;                        /* my input position */
207 } PGLZ_HistEntry;
208
209
210 /* ----------
211  * The provided standard strategies
212  * ----------
213  */
214 static const PGLZ_Strategy strategy_default_data = {
215         32,                                                     /* Data chunks less than 32 bytes are not
216                                                                  * compressed */
217         INT_MAX,                                        /* No upper limit on what we'll try to
218                                                                  * compress */
219         25,                                                     /* Require 25% compression rate, or not worth
220                                                                  * it */
221         1024,                                           /* Give up if no compression in the first 1KB */
222         128,                                            /* Stop history lookup if a match of 128 bytes
223                                                                  * is found */
224         10                                                      /* Lower good match size by 10% at every loop
225                                                                  * iteration */
226 };
227 const PGLZ_Strategy *const PGLZ_strategy_default = &strategy_default_data;
228
229
230 static const PGLZ_Strategy strategy_always_data = {
231         0,                                                      /* Chunks of any size are compressed */
232         INT_MAX,
233         0,                                                      /* It's enough to save one single byte */
234         INT_MAX,                                        /* Never give up early */
235         128,                                            /* Stop history lookup if a match of 128 bytes
236                                                                  * is found */
237         6                                                       /* Look harder for a good match */
238 };
239 const PGLZ_Strategy *const PGLZ_strategy_always = &strategy_always_data;
240
241
242 /* ----------
243  * Statically allocated work arrays for history
244  * ----------
245  */
246 static int16 hist_start[PGLZ_MAX_HISTORY_LISTS];
247 static PGLZ_HistEntry hist_entries[PGLZ_HISTORY_SIZE + 1];
248
249 /*
250  * Element 0 in hist_entries is unused, and means 'invalid'. Likewise,
251  * INVALID_ENTRY_PTR in next/prev pointers mean 'invalid'.
252  */
253 #define INVALID_ENTRY                   0
254 #define INVALID_ENTRY_PTR               (&hist_entries[INVALID_ENTRY])
255
256 /* ----------
257  * pglz_hist_idx -
258  *
259  *              Computes the history table slot for the lookup by the next 4
260  *              characters in the input.
261  *
262  * NB: because we use the next 4 characters, we are not guaranteed to
263  * find 3-character matches; they very possibly will be in the wrong
264  * hash list.  This seems an acceptable tradeoff for spreading out the
265  * hash keys more.
266  * ----------
267  */
268 #define pglz_hist_idx(_s,_e, _mask) (                                                                           \
269                         ((((_e) - (_s)) < 4) ? (int) (_s)[0] :                                                  \
270                          (((_s)[0] << 6) ^ ((_s)[1] << 4) ^                                                             \
271                           ((_s)[2] << 2) ^ (_s)[3])) & (_mask)                          \
272                 )
273
274
275 /* ----------
276  * pglz_hist_add -
277  *
278  *              Adds a new entry to the history table.
279  *
280  * If _recycle is true, then we are recycling a previously used entry,
281  * and must first delink it from its old hashcode's linked list.
282  *
283  * NOTE: beware of multiple evaluations of macro's arguments, and note that
284  * _hn and _recycle are modified in the macro.
285  * ----------
286  */
287 #define pglz_hist_add(_hs,_he,_hn,_recycle,_s,_e, _mask)        \
288 do {                                                                    \
289                         int __hindex = pglz_hist_idx((_s),(_e), (_mask));                               \
290                         int16 *__myhsp = &(_hs)[__hindex];                                                              \
291                         PGLZ_HistEntry *__myhe = &(_he)[_hn];                                                   \
292                         if (_recycle) {                                                                                                 \
293                                 if (__myhe->prev == NULL)                                                                       \
294                                         (_hs)[__myhe->hindex] = __myhe->next - (_he);                   \
295                                 else                                                                                                            \
296                                         __myhe->prev->next = __myhe->next;                                              \
297                                 if (__myhe->next != NULL)                                                                       \
298                                         __myhe->next->prev = __myhe->prev;                                              \
299                         }                                                                                                                               \
300                         __myhe->next = &(_he)[*__myhsp];                                                                \
301                         __myhe->prev = NULL;                                                                                    \
302                         __myhe->hindex = __hindex;                                                                              \
303                         __myhe->pos  = (_s);                                                                                    \
304                         /* If there was an existing entry in this hash slot, link */    \
305                         /* this new entry to it. However, the 0th entry in the */               \
306                         /* entries table is unused, so we can freely scribble on it. */ \
307                         /* So don't bother checking if the slot was used - we'll */             \
308                         /* scribble on the unused entry if it was not, but that's */    \
309                         /* harmless. Avoiding the branch in this critical path */               \
310                         /* speeds this up a little bit. */                                                              \
311                         /* if (*__myhsp != INVALID_ENTRY) */                                                    \
312                                 (_he)[(*__myhsp)].prev = __myhe;                                                        \
313                         *__myhsp = _hn;                                                                                                 \
314                         if (++(_hn) >= PGLZ_HISTORY_SIZE + 1) {                                                 \
315                                 (_hn) = 1;                                                                                                      \
316                                 (_recycle) = true;                                                                                      \
317                         }                                                                                                                               \
318 } while (0)
319
320
321 /* ----------
322  * pglz_out_ctrl -
323  *
324  *              Outputs the last and allocates a new control byte if needed.
325  * ----------
326  */
327 #define pglz_out_ctrl(__ctrlp,__ctrlb,__ctrl,__buf) \
328 do { \
329         if ((__ctrl & 0xff) == 0)                                                                                               \
330         {                                                                                                                                               \
331                 *(__ctrlp) = __ctrlb;                                                                                           \
332                 __ctrlp = (__buf)++;                                                                                            \
333                 __ctrlb = 0;                                                                                                            \
334                 __ctrl = 1;                                                                                                                     \
335         }                                                                                                                                               \
336 } while (0)
337
338
339 /* ----------
340  * pglz_out_literal -
341  *
342  *              Outputs a literal byte to the destination buffer including the
343  *              appropriate control bit.
344  * ----------
345  */
346 #define pglz_out_literal(_ctrlp,_ctrlb,_ctrl,_buf,_byte) \
347 do { \
348         pglz_out_ctrl(_ctrlp,_ctrlb,_ctrl,_buf);                                                                \
349         *(_buf)++ = (unsigned char)(_byte);                                                                             \
350         _ctrl <<= 1;                                                                                                                    \
351 } while (0)
352
353
354 /* ----------
355  * pglz_out_tag -
356  *
357  *              Outputs a backward reference tag of 2-4 bytes (depending on
358  *              offset and length) to the destination buffer including the
359  *              appropriate control bit.
360  * ----------
361  */
362 #define pglz_out_tag(_ctrlp,_ctrlb,_ctrl,_buf,_len,_off) \
363 do { \
364         pglz_out_ctrl(_ctrlp,_ctrlb,_ctrl,_buf);                                                                \
365         _ctrlb |= _ctrl;                                                                                                                \
366         _ctrl <<= 1;                                                                                                                    \
367         if (_len > 17)                                                                                                                  \
368         {                                                                                                                                               \
369                 (_buf)[0] = (unsigned char)((((_off) & 0xf00) >> 4) | 0x0f);            \
370                 (_buf)[1] = (unsigned char)(((_off) & 0xff));                                           \
371                 (_buf)[2] = (unsigned char)((_len) - 18);                                                       \
372                 (_buf) += 3;                                                                                                            \
373         } else {                                                                                                                                \
374                 (_buf)[0] = (unsigned char)((((_off) & 0xf00) >> 4) | ((_len) - 3)); \
375                 (_buf)[1] = (unsigned char)((_off) & 0xff);                                                     \
376                 (_buf) += 2;                                                                                                            \
377         }                                                                                                                                               \
378 } while (0)
379
380
381 /* ----------
382  * pglz_find_match -
383  *
384  *              Lookup the history table if the actual input stream matches
385  *              another sequence of characters, starting somewhere earlier
386  *              in the input buffer.
387  * ----------
388  */
389 static inline int
390 pglz_find_match(int16 *hstart, const char *input, const char *end,
391                                 int *lenp, int *offp, int good_match, int good_drop, int mask)
392 {
393         PGLZ_HistEntry *hent;
394         int16           hentno;
395         int32           len = 0;
396         int32           off = 0;
397
398         /*
399          * Traverse the linked history list until a good enough match is found.
400          */
401         hentno = hstart[pglz_hist_idx(input, end, mask)];
402         hent = &hist_entries[hentno];
403         while (hent != INVALID_ENTRY_PTR)
404         {
405                 const char *ip = input;
406                 const char *hp = hent->pos;
407                 int32           thisoff;
408                 int32           thislen;
409
410                 /*
411                  * Stop if the offset does not fit into our tag anymore.
412                  */
413                 thisoff = ip - hp;
414                 if (thisoff >= 0x0fff)
415                         break;
416
417                 /*
418                  * Determine length of match. A better match must be larger than the
419                  * best so far. And if we already have a match of 16 or more bytes,
420                  * it's worth the call overhead to use memcmp() to check if this match
421                  * is equal for the same size. After that we must fallback to
422                  * character by character comparison to know the exact position where
423                  * the diff occurred.
424                  */
425                 thislen = 0;
426                 if (len >= 16)
427                 {
428                         if (memcmp(ip, hp, len) == 0)
429                         {
430                                 thislen = len;
431                                 ip += len;
432                                 hp += len;
433                                 while (ip < end && *ip == *hp && thislen < PGLZ_MAX_MATCH)
434                                 {
435                                         thislen++;
436                                         ip++;
437                                         hp++;
438                                 }
439                         }
440                 }
441                 else
442                 {
443                         while (ip < end && *ip == *hp && thislen < PGLZ_MAX_MATCH)
444                         {
445                                 thislen++;
446                                 ip++;
447                                 hp++;
448                         }
449                 }
450
451                 /*
452                  * Remember this match as the best (if it is)
453                  */
454                 if (thislen > len)
455                 {
456                         len = thislen;
457                         off = thisoff;
458                 }
459
460                 /*
461                  * Advance to the next history entry
462                  */
463                 hent = hent->next;
464
465                 /*
466                  * Be happy with lesser good matches the more entries we visited. But
467                  * no point in doing calculation if we're at end of list.
468                  */
469                 if (hent != INVALID_ENTRY_PTR)
470                 {
471                         if (len >= good_match)
472                                 break;
473                         good_match -= (good_match * good_drop) / 100;
474                 }
475         }
476
477         /*
478          * Return match information only if it results at least in one byte
479          * reduction.
480          */
481         if (len > 2)
482         {
483                 *lenp = len;
484                 *offp = off;
485                 return 1;
486         }
487
488         return 0;
489 }
490
491
492 /* ----------
493  * pglz_compress -
494  *
495  *              Compresses source into dest using strategy.
496  * ----------
497  */
498 bool
499 pglz_compress(const char *source, int32 slen, PGLZ_Header *dest,
500                           const PGLZ_Strategy *strategy)
501 {
502         unsigned char *bp = ((unsigned char *) dest) + sizeof(PGLZ_Header);
503         unsigned char *bstart = bp;
504         int                     hist_next = 1;
505         bool            hist_recycle = false;
506         const char *dp = source;
507         const char *dend = source + slen;
508         unsigned char ctrl_dummy = 0;
509         unsigned char *ctrlp = &ctrl_dummy;
510         unsigned char ctrlb = 0;
511         unsigned char ctrl = 0;
512         bool            found_match = false;
513         int32           match_len;
514         int32           match_off;
515         int32           good_match;
516         int32           good_drop;
517         int32           result_size;
518         int32           result_max;
519         int32           need_rate;
520         int                     hashsz;
521         int                     mask;
522
523         /*
524          * Our fallback strategy is the default.
525          */
526         if (strategy == NULL)
527                 strategy = PGLZ_strategy_default;
528
529         /*
530          * If the strategy forbids compression (at all or if source chunk size out
531          * of range), fail.
532          */
533         if (strategy->match_size_good <= 0 ||
534                 slen < strategy->min_input_size ||
535                 slen > strategy->max_input_size)
536                 return false;
537
538         /*
539          * Save the original source size in the header.
540          */
541         dest->rawsize = slen;
542
543         /*
544          * Limit the match parameters to the supported range.
545          */
546         good_match = strategy->match_size_good;
547         if (good_match > PGLZ_MAX_MATCH)
548                 good_match = PGLZ_MAX_MATCH;
549         else if (good_match < 17)
550                 good_match = 17;
551
552         good_drop = strategy->match_size_drop;
553         if (good_drop < 0)
554                 good_drop = 0;
555         else if (good_drop > 100)
556                 good_drop = 100;
557
558         need_rate = strategy->min_comp_rate;
559         if (need_rate < 0)
560                 need_rate = 0;
561         else if (need_rate > 99)
562                 need_rate = 99;
563
564         /*
565          * Compute the maximum result size allowed by the strategy, namely the
566          * input size minus the minimum wanted compression rate.  This had better
567          * be <= slen, else we might overrun the provided output buffer.
568          */
569         if (slen > (INT_MAX / 100))
570         {
571                 /* Approximate to avoid overflow */
572                 result_max = (slen / 100) * (100 - need_rate);
573         }
574         else
575                 result_max = (slen * (100 - need_rate)) / 100;
576
577         /*
578          * Experiments suggest that these hash sizes work pretty well. A large
579          * hash table minimizes collision, but has a higher startup cost. For
580          * a small input, the startup cost dominates. The table size must be
581          * a power of two.
582          */
583         if (slen < 128)
584                 hashsz = 512;
585         else if (slen < 256)
586                 hashsz = 1024;
587         else if (slen < 512)
588                 hashsz = 2048;
589         else if (slen < 1024)
590                 hashsz = 4096;
591         else
592                 hashsz = 8192;
593         mask = hashsz - 1;
594
595         /*
596          * Initialize the history lists to empty.  We do not need to zero the
597          * hist_entries[] array; its entries are initialized as they are used.
598          */
599         memset(hist_start, 0, hashsz * sizeof(int16));
600
601         /*
602          * Compress the source directly into the output buffer.
603          */
604         while (dp < dend)
605         {
606                 /*
607                  * If we already exceeded the maximum result size, fail.
608                  *
609                  * We check once per loop; since the loop body could emit as many as 4
610                  * bytes (a control byte and 3-byte tag), PGLZ_MAX_OUTPUT() had better
611                  * allow 4 slop bytes.
612                  */
613                 if (bp - bstart >= result_max)
614                         return false;
615
616                 /*
617                  * If we've emitted more than first_success_by bytes without finding
618                  * anything compressible at all, fail.  This lets us fall out
619                  * reasonably quickly when looking at incompressible input (such as
620                  * pre-compressed data).
621                  */
622                 if (!found_match && bp - bstart >= strategy->first_success_by)
623                         return false;
624
625                 /*
626                  * Try to find a match in the history
627                  */
628                 if (pglz_find_match(hist_start, dp, dend, &match_len,
629                                                         &match_off, good_match, good_drop, mask))
630                 {
631                         /*
632                          * Create the tag and add history entries for all matched
633                          * characters.
634                          */
635                         pglz_out_tag(ctrlp, ctrlb, ctrl, bp, match_len, match_off);
636                         while (match_len--)
637                         {
638                                 pglz_hist_add(hist_start, hist_entries,
639                                                           hist_next, hist_recycle,
640                                                           dp, dend, mask);
641                                 dp++;                   /* Do not do this ++ in the line above! */
642                                 /* The macro would do it four times - Jan.      */
643                         }
644                         found_match = true;
645                 }
646                 else
647                 {
648                         /*
649                          * No match found. Copy one literal byte.
650                          */
651                         pglz_out_literal(ctrlp, ctrlb, ctrl, bp, *dp);
652                         pglz_hist_add(hist_start, hist_entries,
653                                                   hist_next, hist_recycle,
654                                                   dp, dend, mask);
655                         dp++;                           /* Do not do this ++ in the line above! */
656                         /* The macro would do it four times - Jan.      */
657                 }
658         }
659
660         /*
661          * Write out the last control byte and check that we haven't overrun the
662          * output size allowed by the strategy.
663          */
664         *ctrlp = ctrlb;
665         result_size = bp - bstart;
666         if (result_size >= result_max)
667                 return false;
668
669         /*
670          * Success - need only fill in the actual length of the compressed datum.
671          */
672         SET_VARSIZE_COMPRESSED(dest, result_size + sizeof(PGLZ_Header));
673
674         return true;
675 }
676
677
678 /* ----------
679  * pglz_decompress -
680  *
681  *              Decompresses source into dest.
682  * ----------
683  */
684 void
685 pglz_decompress(const PGLZ_Header *source, char *dest)
686 {
687         const unsigned char *sp;
688         const unsigned char *srcend;
689         unsigned char *dp;
690         unsigned char *destend;
691
692         sp = ((const unsigned char *) source) + sizeof(PGLZ_Header);
693         srcend = ((const unsigned char *) source) + VARSIZE(source);
694         dp = (unsigned char *) dest;
695         destend = dp + source->rawsize;
696
697         while (sp < srcend && dp < destend)
698         {
699                 /*
700                  * Read one control byte and process the next 8 items (or as many as
701                  * remain in the compressed input).
702                  */
703                 unsigned char ctrl = *sp++;
704                 int                     ctrlc;
705
706                 for (ctrlc = 0; ctrlc < 8 && sp < srcend; ctrlc++)
707                 {
708                         if (ctrl & 1)
709                         {
710                                 /*
711                                  * Otherwise it contains the match length minus 3 and the
712                                  * upper 4 bits of the offset. The next following byte
713                                  * contains the lower 8 bits of the offset. If the length is
714                                  * coded as 18, another extension tag byte tells how much
715                                  * longer the match really was (0-255).
716                                  */
717                                 int32           len;
718                                 int32           off;
719
720                                 len = (sp[0] & 0x0f) + 3;
721                                 off = ((sp[0] & 0xf0) << 4) | sp[1];
722                                 sp += 2;
723                                 if (len == 18)
724                                         len += *sp++;
725
726                                 /*
727                                  * Check for output buffer overrun, to ensure we don't clobber
728                                  * memory in case of corrupt input.  Note: we must advance dp
729                                  * here to ensure the error is detected below the loop.  We
730                                  * don't simply put the elog inside the loop since that will
731                                  * probably interfere with optimization.
732                                  */
733                                 if (dp + len > destend)
734                                 {
735                                         dp += len;
736                                         break;
737                                 }
738
739                                 /*
740                                  * Now we copy the bytes specified by the tag from OUTPUT to
741                                  * OUTPUT. It is dangerous and platform dependent to use
742                                  * memcpy() here, because the copied areas could overlap
743                                  * extremely!
744                                  */
745                                 while (len--)
746                                 {
747                                         *dp = dp[-off];
748                                         dp++;
749                                 }
750                         }
751                         else
752                         {
753                                 /*
754                                  * An unset control bit means LITERAL BYTE. So we just copy
755                                  * one from INPUT to OUTPUT.
756                                  */
757                                 if (dp >= destend)              /* check for buffer overrun */
758                                         break;          /* do not clobber memory */
759
760                                 *dp++ = *sp++;
761                         }
762
763                         /*
764                          * Advance the control bit
765                          */
766                         ctrl >>= 1;
767                 }
768         }
769
770         /*
771          * Check we decompressed the right amount.
772          */
773         if (dp != destend || sp != srcend)
774                 elog(ERROR, "compressed data is corrupt");
775
776         /*
777          * That's it.
778          */
779 }