summaryrefslogtreecommitdiff
path: root/source/kit/miniz/miniz_tdef.h
blob: f7adaa6ecaf939cd410047663621981adc2f0099 (plain)
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#ifndef KIT_MINIZ_MINIZ_TDEF_H
#define KIT_MINIZ_MINIZ_TDEF_H

#include "miniz_common.h"

#ifndef MINIZ_NO_DEFLATE_APIS

#  ifdef __cplusplus
extern "C" {
#  endif
/* ------------------- Low-level Compression API Definitions */

/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be
 * slightly slower, and raw/dynamic blocks will be output more
 * frequently). */
#  define TDEFL_LESS_MEMORY 0

/* tdefl_init() compression flags logically OR'd together (low 12 bits
 * contain the max. number of probes per dictionary search): */
/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary
 * probes per dictionary search. 0=Huffman only, 1=Huffman+LZ
 * (fastest/crap compression), 4095=Huffman+LZ (slowest/best
 * compression). */
enum {
  TDEFL_HUFFMAN_ONLY       = 0,
  TDEFL_DEFAULT_MAX_PROBES = 128,
  TDEFL_MAX_PROBES_MASK    = 0xFFF
};

/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib
 * header before the deflate data, and the Adler-32 of the source data
 * at the end. Otherwise, you'll get raw deflate data. */
/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input
 * data (even when not writing zlib headers). */
/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing,
 * instead of more efficient lazy parsing. */
/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the
 * compressor's initialization time to the minimum, but the output may
 * vary from run to run given the same input (depending on the
 * contents of memory). */
/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a
 * distance of 1) */
/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */
/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman
 * tables. */
/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate
 * blocks. */
/* The low 12 bits are reserved to control the max # of hash probes
 * per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */
enum {
  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
  TDEFL_COMPUTE_ADLER32               = 0x02000,
  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
  TDEFL_RLE_MATCHES                   = 0x10000,
  TDEFL_FILTER_MATCHES                = 0x20000,
  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
};

/* High level compression functions: */
/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap
 * block allocated via malloc(). */
/* On entry: */
/*  pSrc_buf, src_buf_len: Pointer and size of source block to
 * compress. */
/*  flags: The max match finder probes (default is 128) logically OR'd
 * against the above flags. Higher probes are slower but improve
 * compression. */
/* On return: */
/*  Function returns a pointer to the compressed data, or NULL on
 * failure. */
/*  *pOut_len will be set to the compressed data's size, which could
 * be larger than src_buf_len on uncompressible data. */
/*  The caller must free() the returned block when it's no longer
 * needed. */
void *tdefl_compress_mem_to_heap(const void *pSrc_buf,
                                 size_t src_buf_len, size_t *pOut_len,
                                 int flags);

/* tdefl_compress_mem_to_mem() compresses a block in memory to another
 * block in memory. */
/* Returns 0 on failure. */
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
                                 const void *pSrc_buf,
                                 size_t src_buf_len, int flags);

/* Compresses an image to a compressed PNG file in memory. */
/* On entry: */
/*  pImage, w, h, and num_chans describe the image to compress.
 * num_chans may be 1, 2, 3, or 4. */
/*  The image pitch in bytes per scanline will be w*num_chans. The
 * leftmost pixel on the top scanline is stored first in memory. */
/*  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
 * MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
 */
/*  If flip is true, the image will be flipped on the Y axis (useful
 * for OpenGL apps). */
/* On return: */
/*  Function returns a pointer to the compressed data, or NULL on
 * failure. */
/*  *pLen_out will be set to the size of the PNG image file. */
/*  The caller must mz_free() the returned heap block (which will
 * typically be larger than *pLen_out) when it's no longer needed. */
void *tdefl_write_image_to_png_file_in_memory_ex(
    const void *pImage, int w, int h, int num_chans, size_t *pLen_out,
    mz_uint level, mz_bool flip);
void *tdefl_write_image_to_png_file_in_memory(const void *pImage,
                                              int w, int h,
                                              int     num_chans,
                                              size_t *pLen_out);

/* Output stream interface. The compressor uses this interface to
 * write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE
 * at a time. */
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
                                          void *pUser);

/* tdefl_compress_mem_to_output() compresses a block to an output
 * stream. The above helpers use this function internally. */
mz_bool tdefl_compress_mem_to_output(
    const void *pBuf, size_t buf_len,
    tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user,
    int flags);

enum {
  TDEFL_MAX_HUFF_TABLES    = 3,
  TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
  TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
  TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
  TDEFL_LZ_DICT_SIZE       = 32768,
  TDEFL_LZ_DICT_SIZE_MASK  = TDEFL_LZ_DICT_SIZE - 1,
  TDEFL_MIN_MATCH_LEN      = 3,
  TDEFL_MAX_MATCH_LEN      = 258
};

/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire
 * compressed output block (using static/fixed Huffman codes). */
#  if TDEFL_LESS_MEMORY
enum {
  TDEFL_LZ_CODE_BUF_SIZE      = 24 * 1024,
  TDEFL_OUT_BUF_SIZE          = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
  TDEFL_MAX_HUFF_SYMBOLS      = 288,
  TDEFL_LZ_HASH_BITS          = 12,
  TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
  TDEFL_LZ_HASH_SHIFT         = (TDEFL_LZ_HASH_BITS + 2) / 3,
  TDEFL_LZ_HASH_SIZE          = 1 << TDEFL_LZ_HASH_BITS
};
#  else
enum {
  TDEFL_LZ_CODE_BUF_SIZE      = 64 * 1024,
  TDEFL_OUT_BUF_SIZE          = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
  TDEFL_MAX_HUFF_SYMBOLS      = 288,
  TDEFL_LZ_HASH_BITS          = 15,
  TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
  TDEFL_LZ_HASH_SHIFT         = (TDEFL_LZ_HASH_BITS + 2) / 3,
  TDEFL_LZ_HASH_SIZE          = 1 << TDEFL_LZ_HASH_BITS
};
#  endif

/* The low-level tdefl functions below may be used directly if the
 * above helper functions aren't flexible enough. The low-level
 * functions don't make any heap allocations, unlike the above helper
 * functions. */
typedef enum {
  TDEFL_STATUS_BAD_PARAM      = -2,
  TDEFL_STATUS_PUT_BUF_FAILED = -1,
  TDEFL_STATUS_OKAY           = 0,
  TDEFL_STATUS_DONE           = 1
} tdefl_status;

/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */
typedef enum {
  TDEFL_NO_FLUSH   = 0,
  TDEFL_SYNC_FLUSH = 2,
  TDEFL_FULL_FLUSH = 3,
  TDEFL_FINISH     = 4
} tdefl_flush;

/* tdefl's compression state structure. */
typedef struct {
  tdefl_put_buf_func_ptr m_pPut_buf_func;
  void                  *m_pPut_buf_user;
  mz_uint                m_flags, m_max_probes[2];
  int                    m_greedy_parsing;
  mz_uint   m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf,
      *m_pOutput_buf_end;
  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos,
      m_bits_in, m_bit_buffer;
  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
      m_output_flush_ofs, m_output_flush_remaining, m_finished,
      m_block_index, m_wants_to_finish;
  tdefl_status    m_prev_return_status;
  const void     *m_pIn_buf;
  void           *m_pOut_buf;
  size_t         *m_pIn_buf_size, *m_pOut_buf_size;
  tdefl_flush     m_flush;
  const mz_uint8 *m_pSrc;
  size_t          m_src_buf_left, m_out_buf_ofs;
  mz_uint8  m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES]
                        [TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES]
                        [TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES]
                            [TDEFL_MAX_HUFF_SYMBOLS];
  mz_uint8  m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
  mz_uint8  m_output_buf[TDEFL_OUT_BUF_SIZE];
} tdefl_compressor;

/* Initializes the compressor. */
/* There is no corresponding deinit() function because the tdefl API's
 * do not dynamically allocate memory. */
/* pBut_buf_func: If NULL, output data will be supplied to the
 * specified callback. In this case, the user should call the
 * tdefl_compress_buffer() API for compression. */
/* If pBut_buf_func is NULL the user should always call the
 * tdefl_compress() API. */
/* flags: See the above enums (TDEFL_HUFFMAN_ONLY,
 * TDEFL_WRITE_ZLIB_HEADER, etc.) */
tdefl_status tdefl_init(tdefl_compressor      *d,
                        tdefl_put_buf_func_ptr pPut_buf_func,
                        void *pPut_buf_user, int flags);

/* Compresses a block of data, consuming as much of the specified
 * input buffer as possible, and writing as much compressed data to
 * the specified output buffer as possible. */
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
                            size_t *pIn_buf_size, void *pOut_buf,
                            size_t *pOut_buf_size, tdefl_flush flush);

/* tdefl_compress_buffer() is only usable when the tdefl_init() is
 * called with a non-NULL tdefl_put_buf_func_ptr. */
/* tdefl_compress_buffer() always consumes the entire input buffer. */
tdefl_status tdefl_compress_buffer(tdefl_compressor *d,
                                   const void       *pIn_buf,
                                   size_t            in_buf_size,
                                   tdefl_flush       flush);

tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
mz_uint32    tdefl_get_adler32(tdefl_compressor *d);

/* Create tdefl_compress() flags given zlib-style compression
 * parameters. */
/* level may range from [0,10] (where 10 is absolute max compression,
 * but may be much slower on some files) */
/* window_bits may be -15 (raw deflate) or 15 (zlib) */
/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED,
 * MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */
mz_uint tdefl_create_comp_flags_from_zip_params(int level,
                                                int window_bits,
                                                int strategy);

#  ifndef MINIZ_NO_MALLOC
/* Allocate the tdefl_compressor structure in C so that */
/* non-C language bindings to tdefl_ API don't need to worry about */
/* structure size and allocation mechanism. */
tdefl_compressor *tdefl_compressor_alloc(void);
void              tdefl_compressor_free(tdefl_compressor *pComp);
#  endif

#  ifdef __cplusplus
}
#  endif

#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/

#endif