1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
/* ----------
* pg_lzcompress.h -
*
* $Header: /cvsroot/pgsql/src/include/utils/pg_lzcompress.h,v 1.5 2000/04/12 17:16:55 momjian Exp $
*
* Definitions for the builtin LZ compressor
* ----------
*/
#ifndef _PG_LZCOMPRESS_H_
#define _PG_LZCOMPRESS_H_
/* ----------
* PGLZ_Header -
*
* The information at the top of the compressed data.
* The varsize must be kept the same data type as the value
* in front of all variable size data types in PostgreSQL.
* ----------
*/
typedef struct PGLZ_Header
{
int32 varsize;
int32 rawsize;
} PGLZ_Header;
/* ----------
* PGLZ_MAX_OUTPUT -
*
* Macro to compute the maximum buffer required for the
* compression output. It is larger than the input, because
* in the worst case, we cannot write out one single tag but
* need one control byte per 8 literal data bytes plus the
* EOF mark at the end.
* ----------
*/
#define PGLZ_MAX_OUTPUT(_dlen) ((_dlen) + (((_dlen) | 0x07) >> 3) \
+ sizeof(PGLZ_Header))
/* ----------
* PGLZ_RAW_SIZE -
*
* Macro to determine the uncompressed data size contained
* in the entry.
* ----------
*/
#define PGLZ_RAW_SIZE(_lzdata) (_lzdata->rawsize)
/* ----------
* PGLZ_IS_COMPRESSED -
*
* Macro to determine if the data itself is stored as raw
* uncompressed data.
* ----------
*/
#define PGLZ_IS_COMPRESSED(_lzdata) (_lzdata->varsize != \
_lzdata->rawsize + \
sizeof(PGLZ_Header))
/* ----------
* PGLZ_RAW_DATA -
*
* Macro to get access to the plain compressed or uncompressed
* data. Useful if PGLZ_IS_COMPRESSED returns false.
* ----------
*/
#define PGLZ_RAW_DATA(_lzdata) (((char *)(_lzdata)) + \
sizeof(PGLZ_Header))
/* ----------
* PGLZ_Strategy -
*
* Some values that control the compression algorithm.
*
* min_input_size Minimum input data size to start compression.
*
* force_input_size Input data size at which compressed storage is
* forced even if the compression rate drops below
* min_comp_rate (but not below 0).
*
* min_comp_rate Minimum compression rate (0-99%), the output
* must be smaller than the input. If that isn't
* the case, the compressor will throw away its
* output and copy the original, uncompressed data
* to the output buffer.
*
* match_size_good The initial GOOD match size when starting history
* lookup. When looking up the history to find a
* match that could be expressed as a tag, the
* algorithm does not allways walk back entirely.
* A good match fast is usually better than the
* best possible one very late. For each iteration
* in the lookup, this value is lowered so the
* longer the lookup takes, the smaller matches
* are considered good.
*
* match_size_drop The percentage, match_size_good is lowered
* at each history check. Allowed values are
* 0 (no change until end) to 100 (only check
* latest history entry at all).
* ----------
*/
typedef struct PGLZ_Strategy
{
int32 min_input_size;
int32 force_input_size;
int32 min_comp_rate;
int32 match_size_good;
int32 match_size_drop;
} PGLZ_Strategy;
/* ----------
* PGLZ_DecompState -
*
* Decompression state variable for byte-per-byte decompression
* using pglz_decomp_getchar() macro.
* ----------
*/
typedef struct PGLZ_DecompState
{
unsigned char *temp_buf;
unsigned char *cp_in;
unsigned char *cp_end;
unsigned char *cp_out;
unsigned char *cp_copy;
int (*next_char) (struct PGLZ_DecompState *dstate);
int tocopy;
int ctrl_count;
unsigned char ctrl;
} PGLZ_DecompState;
/* ----------
* The standard strategies
*
* PGLZ_strategy_default Starts compression only if input is
* at least 256 bytes large. Stores output
* uncompressed if compression does not
* gain at least 20% size reducture but
* input does not exceed 6K. Stops history
* lookup if at least a 128 byte long
* match has been found.
*
* This is the default strategy if none
* is given to pglz_compress().
*
* PGLZ_strategy_allways Starts compression on any infinitely
* small input and does fallback to
* uncompressed storage only if output
* would be larger than input.
*
* PGLZ_strategy_never Force pglz_compress to act as a custom
* interface for memcpy(). Only useful
* for generic interfacing.
* ----------
*/
extern PGLZ_Strategy *PGLZ_strategy_default;
extern PGLZ_Strategy *PGLZ_strategy_allways;
extern PGLZ_Strategy *PGLZ_strategy_never;
/* ----------
* pglz_decomp_getchar -
*
* Get next character (or EOF) from decompressor.
* The status variable must be initialized before and deinitialized
* after compression with the next two macros below.
* ----------
*/
#define pglz_decomp_getchar(_ds) \
((*((_ds)->next_char))((_ds)))
/* ----------
* pglz_decomp_init -
*
* Initialize a decomp state from a compressed input.
* ----------
*/
#define pglz_decomp_init(_ds,_lz) do { \
(_ds)->cp_in = ((unsigned char *)(_lz)) \
+ sizeof(PGLZ_Header); \
(_ds)->cp_end = (_ds)->cp_in + (_lz)->varsize \
- sizeof(PGLZ_Header); \
if (PGLZ_IS_COMPRESSED((_lz))) { \
(_ds)->temp_buf = (unsigned char *) \
palloc(PGLZ_RAW_SIZE((_lz))); \
(_ds)->cp_out = (_ds)->temp_buf; \
(_ds)->next_char = pglz_get_next_decomp_char_from_lzdata; \
(_ds)->tocopy = 0; \
(_ds)->ctrl_count = 0; \
} else { \
(_ds)->temp_buf = NULL; \
(_ds)->next_char = pglz_get_next_decomp_char_from_plain; \
} \
} while (0)
/* ----------
* pglz_decomp_end -
*
* Deallocate resources after decompression.
* ----------
*/
#define pglz_decomp_end(_ds) do { \
if ((_ds)->temp_buf != NULL) \
pfree((void *)((_ds)->temp_buf)); \
} while (0)
/* ----------
* Global function declarations
* ----------
*/
int pglz_compress(char *source, int32 slen, PGLZ_Header *dest,
PGLZ_Strategy *strategy);
int pglz_decompress(PGLZ_Header *source, char *dest);
/* ----------
* Functions used by pglz_decomp_getchar().
* Internal use only.
* ----------
*/
extern int pglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate);
extern int pglz_get_next_decomp_char_from_plain(PGLZ_DecompState *dstate);
#endif /* _PG_LZCOMPRESS_H_ */
|