extlzham 0.0.1.PROTOTYPE3-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +27 -0
  3. data/README.md +74 -0
  4. data/Rakefile +152 -0
  5. data/contrib/lzham/LICENSE +22 -0
  6. data/contrib/lzham/README.md +209 -0
  7. data/contrib/lzham/include/lzham.h +781 -0
  8. data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
  9. data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
  10. data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
  11. data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
  12. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
  13. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
  14. data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
  15. data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
  16. data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
  17. data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
  18. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
  19. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
  20. data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
  21. data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
  22. data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
  23. data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
  24. data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
  25. data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
  26. data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
  27. data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
  28. data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
  29. data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
  30. data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
  31. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
  32. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
  33. data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
  34. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
  35. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
  36. data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
  37. data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
  38. data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
  39. data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
  40. data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
  41. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
  42. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
  43. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
  44. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
  45. data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
  46. data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
  47. data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
  48. data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
  49. data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
  50. data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
  51. data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
  52. data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
  53. data/examples/basic.rb +48 -0
  54. data/ext/constants.c +64 -0
  55. data/ext/decoder.c +313 -0
  56. data/ext/depend +5 -0
  57. data/ext/encoder.c +372 -0
  58. data/ext/error.c +80 -0
  59. data/ext/extconf.rb +29 -0
  60. data/ext/extlzham.c +34 -0
  61. data/ext/extlzham.h +62 -0
  62. data/gemstub.rb +22 -0
  63. data/lib/2.0/extlzham.so +0 -0
  64. data/lib/2.1/extlzham.so +0 -0
  65. data/lib/2.2/extlzham.so +0 -0
  66. data/lib/extlzham.rb +158 -0
  67. data/lib/extlzham/version.rb +5 -0
  68. data/test/test_extlzham.rb +35 -0
  69. metadata +156 -0
@@ -0,0 +1,37 @@
1
+ // File: lzham_decomp.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+ #include "lzham.h"
5
+
6
+ namespace lzham
7
+ {
8
+ void LZHAM_CDECL lzham_lib_set_memory_callbacks(lzham_realloc_func pRealloc, lzham_msize_func pMSize, void* pUser_data);
9
+
10
+ lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_init(const lzham_decompress_params *pParams);
11
+
12
+ lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_reinit(lzham_decompress_state_ptr pState, const lzham_decompress_params *pParams);
13
+
14
+ lzham_uint32 LZHAM_CDECL lzham_lib_decompress_deinit(lzham_decompress_state_ptr pState);
15
+
16
+ lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress(
17
+ lzham_decompress_state_ptr pState,
18
+ const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
19
+ lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
20
+ lzham_bool no_more_input_bytes_flag);
21
+
22
+ lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress_memory(const lzham_decompress_params *pParams,
23
+ lzham_uint8* pDst_buf, size_t *pDst_len,
24
+ const lzham_uint8* pSrc_buf, size_t src_len, lzham_uint32 *pAdler32);
25
+
26
+ int LZHAM_CDECL lzham_lib_z_inflateInit2(lzham_z_streamp pStream, int window_bits);
27
+ int LZHAM_CDECL lzham_lib_z_inflateInit(lzham_z_streamp pStream);
28
+ int LZHAM_CDECL lzham_lib_z_inflateReset(lzham_z_streamp pStream);
29
+ int LZHAM_CDECL lzham_lib_z_inflate(lzham_z_streamp pStream, int flush);
30
+ int LZHAM_CDECL lzham_lib_z_inflateEnd(lzham_z_streamp pStream);
31
+ int LZHAM_CDECL lzham_lib_z_uncompress(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len);
32
+
33
+ const char * LZHAM_CDECL lzham_lib_z_error(int err);
34
+ lzham_z_ulong lzham_lib_z_adler32(lzham_z_ulong adler, const unsigned char *ptr, size_t buf_len);
35
+ lzham_z_ulong LZHAM_CDECL lzham_lib_z_crc32(lzham_z_ulong crc, const lzham_uint8 *ptr, size_t buf_len);
36
+
37
+ } // namespace lzham
@@ -0,0 +1,54 @@
1
+ // File: lzham_helpers.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+
5
+ #define LZHAM_NO_COPY_OR_ASSIGNMENT_OP(c) c(const c&); c& operator= (const c&);
6
+
7
+ namespace lzham
8
+ {
9
+ namespace helpers
10
+ {
11
+ template<typename T> struct rel_ops
12
+ {
13
+ friend inline bool operator!=(const T& x, const T& y) { return (!(x == y)); }
14
+ friend inline bool operator> (const T& x, const T& y) { return (y < x); }
15
+ friend inline bool operator<=(const T& x, const T& y) { return (!(y < x)); }
16
+ friend inline bool operator>=(const T& x, const T& y) { return (!(x < y)); }
17
+ };
18
+
19
+ template <typename T>
20
+ inline T* construct(T* p)
21
+ {
22
+ return new (static_cast<void*>(p)) T;
23
+ }
24
+
25
+ template <typename T, typename U>
26
+ inline T* construct(T* p, const U& init)
27
+ {
28
+ return new (static_cast<void*>(p)) T(init);
29
+ }
30
+
31
+ template <typename T>
32
+ inline void construct_array(T* p, uint n);
33
+
34
+ template <typename T, typename U>
35
+ inline void construct_array(T* p, uint n, const U& init)
36
+ {
37
+ T* q = p + n;
38
+ for ( ; p != q; ++p)
39
+ new (static_cast<void*>(p)) T(init);
40
+ }
41
+
42
+ template <typename T>
43
+ inline void destruct(T* p)
44
+ {
45
+ LZHAM_NOTE_UNUSED(p);
46
+ p->~T();
47
+ }
48
+
49
+ template <typename T>
50
+ inline void destruct_array(T* p, uint n);
51
+
52
+ } // namespace helpers
53
+
54
+ } // namespace lzham
@@ -0,0 +1,262 @@
1
+ // File: huffman_codes.cpp
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #include "lzham_core.h"
4
+ #include "lzham_huffman_codes.h"
5
+
6
+ namespace lzham
7
+ {
8
+ struct sym_freq
9
+ {
10
+ uint m_freq;
11
+ uint16 m_left;
12
+ uint16 m_right;
13
+
14
+ inline bool operator< (const sym_freq& other) const
15
+ {
16
+ return m_freq > other.m_freq;
17
+ }
18
+ };
19
+
20
+ static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* syms0, sym_freq* syms1)
21
+ {
22
+ const uint cMaxPasses = 2;
23
+ uint hist[256 * cMaxPasses];
24
+
25
+ memset(hist, 0, sizeof(hist[0]) * 256 * cMaxPasses);
26
+
27
+ {
28
+ sym_freq* p = syms0;
29
+ sym_freq* q = syms0 + (num_syms >> 1) * 2;
30
+
31
+ for ( ; p != q; p += 2)
32
+ {
33
+ const uint freq0 = p[0].m_freq;
34
+ const uint freq1 = p[1].m_freq;
35
+
36
+ hist[ freq0 & 0xFF]++;
37
+ hist[256 + ((freq0 >> 8) & 0xFF)]++;
38
+
39
+ hist[ freq1 & 0xFF]++;
40
+ hist[256 + ((freq1 >> 8) & 0xFF)]++;
41
+ }
42
+
43
+ if (num_syms & 1)
44
+ {
45
+ const uint freq = p->m_freq;
46
+
47
+ hist[ freq & 0xFF]++;
48
+ hist[256 + ((freq >> 8) & 0xFF)]++;
49
+ }
50
+ }
51
+
52
+ sym_freq* pCur_syms = syms0;
53
+ sym_freq* pNew_syms = syms1;
54
+
55
+ const uint total_passes = (hist[256] == num_syms) ? 1 : cMaxPasses;
56
+
57
+ for (uint pass = 0; pass < total_passes; pass++)
58
+ {
59
+ const uint* pHist = &hist[pass << 8];
60
+
61
+ uint offsets[256];
62
+
63
+ uint cur_ofs = 0;
64
+ for (uint i = 0; i < 256; i += 2)
65
+ {
66
+ offsets[i] = cur_ofs;
67
+ cur_ofs += pHist[i];
68
+
69
+ offsets[i+1] = cur_ofs;
70
+ cur_ofs += pHist[i+1];
71
+ }
72
+
73
+ const uint pass_shift = pass << 3;
74
+
75
+ sym_freq* p = pCur_syms;
76
+ sym_freq* q = pCur_syms + (num_syms >> 1) * 2;
77
+
78
+ for ( ; p != q; p += 2)
79
+ {
80
+ uint c0 = p[0].m_freq;
81
+ uint c1 = p[1].m_freq;
82
+
83
+ if (pass)
84
+ {
85
+ c0 >>= 8;
86
+ c1 >>= 8;
87
+ }
88
+
89
+ c0 &= 0xFF;
90
+ c1 &= 0xFF;
91
+
92
+ if (c0 == c1)
93
+ {
94
+ uint dst_offset0 = offsets[c0];
95
+
96
+ offsets[c0] = dst_offset0 + 2;
97
+
98
+ pNew_syms[dst_offset0] = p[0];
99
+ pNew_syms[dst_offset0 + 1] = p[1];
100
+ }
101
+ else
102
+ {
103
+ uint dst_offset0 = offsets[c0]++;
104
+ uint dst_offset1 = offsets[c1]++;
105
+
106
+ pNew_syms[dst_offset0] = p[0];
107
+ pNew_syms[dst_offset1] = p[1];
108
+ }
109
+ }
110
+
111
+ if (num_syms & 1)
112
+ {
113
+ uint c = ((p->m_freq) >> pass_shift) & 0xFF;
114
+
115
+ uint dst_offset = offsets[c];
116
+ offsets[c] = dst_offset + 1;
117
+
118
+ pNew_syms[dst_offset] = *p;
119
+ }
120
+
121
+ sym_freq* t = pCur_syms;
122
+ pCur_syms = pNew_syms;
123
+ pNew_syms = t;
124
+ }
125
+
126
+ #if LZHAM_ASSERTS_ENABLED
127
+ uint prev_freq = 0;
128
+ for (uint i = 0; i < num_syms; i++)
129
+ {
130
+ LZHAM_ASSERT(!(pCur_syms[i].m_freq < prev_freq));
131
+ prev_freq = pCur_syms[i].m_freq;
132
+ }
133
+ #endif
134
+
135
+ return pCur_syms;
136
+ }
137
+
138
+ struct huffman_work_tables
139
+ {
140
+ enum { cMaxInternalNodes = cHuffmanMaxSupportedSyms };
141
+
142
+ sym_freq syms0[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
143
+ sym_freq syms1[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
144
+
145
+ #if !USE_CALCULATE_MINIMUM_REDUNDANCY
146
+ uint16 queue[cMaxInternalNodes];
147
+ #endif
148
+ };
149
+
150
+ uint get_generate_huffman_codes_table_size()
151
+ {
152
+ return sizeof(huffman_work_tables);
153
+ }
154
+
155
+ // calculate_minimum_redundancy() written by Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk November 1996.
156
+ static void calculate_minimum_redundancy(int A[], int n)
157
+ {
158
+ int root; /* next root node to be used */
159
+ int leaf; /* next leaf to be used */
160
+ int next; /* next value to be assigned */
161
+ int avbl; /* number of available nodes */
162
+ int used; /* number of internal nodes */
163
+ int dpth; /* current depth of leaves */
164
+
165
+ /* check for pathological cases */
166
+ if (n==0) { return; }
167
+ if (n==1) { A[0] = 0; return; }
168
+
169
+ /* first pass, left to right, setting parent pointers */
170
+ A[0] += A[1]; root = 0; leaf = 2;
171
+ for (next=1; next < n-1; next++) {
172
+ /* select first item for a pairing */
173
+ if (leaf>=n || A[root]<A[leaf]) {
174
+ A[next] = A[root]; A[root++] = next;
175
+ } else
176
+ A[next] = A[leaf++];
177
+
178
+ /* add on the second item */
179
+ if (leaf>=n || (root<next && A[root]<A[leaf])) {
180
+ A[next] += A[root]; A[root++] = next;
181
+ } else
182
+ A[next] += A[leaf++];
183
+ }
184
+
185
+ /* second pass, right to left, setting internal depths */
186
+ A[n-2] = 0;
187
+ for (next=n-3; next>=0; next--)
188
+ A[next] = A[A[next]]+1;
189
+
190
+ /* third pass, right to left, setting leaf depths */
191
+ avbl = 1; used = dpth = 0; root = n-2; next = n-1;
192
+ while (avbl>0) {
193
+ while (root>=0 && A[root]==dpth) {
194
+ used++; root--;
195
+ }
196
+ while (avbl>used) {
197
+ A[next--] = dpth; avbl--;
198
+ }
199
+ avbl = 2*used; dpth++; used = 0;
200
+ }
201
+ }
202
+
203
+ bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
204
+ {
205
+ if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
206
+ return false;
207
+
208
+ huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
209
+
210
+ uint max_freq = 0;
211
+ uint total_freq = 0;
212
+
213
+ uint num_used_syms = 0;
214
+ for (uint i = 0; i < num_syms; i++)
215
+ {
216
+ uint freq = pFreq[i];
217
+
218
+ if (!freq)
219
+ pCodesizes[i] = 0;
220
+ else
221
+ {
222
+ total_freq += freq;
223
+ max_freq = math::maximum(max_freq, freq);
224
+
225
+ sym_freq& sf = state.syms0[num_used_syms];
226
+ sf.m_left = (uint16)i;
227
+ sf.m_right = UINT16_MAX;
228
+ sf.m_freq = freq;
229
+ num_used_syms++;
230
+ }
231
+ }
232
+
233
+ total_freq_ret = total_freq;
234
+
235
+ if (num_used_syms == 1)
236
+ {
237
+ pCodesizes[state.syms0[0].m_left] = 1;
238
+ return true;
239
+ }
240
+
241
+ sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
242
+
243
+ int x[cHuffmanMaxSupportedSyms];
244
+ for (uint i = 0; i < num_used_syms; i++)
245
+ x[i] = syms[i].m_freq;
246
+
247
+ calculate_minimum_redundancy(x, num_used_syms);
248
+
249
+ uint max_len = 0;
250
+ for (uint i = 0; i < num_used_syms; i++)
251
+ {
252
+ uint len = x[i];
253
+ max_len = math::maximum(len, max_len);
254
+ pCodesizes[syms[i].m_left] = static_cast<uint8>(len);
255
+ }
256
+ max_code_size = max_len;
257
+
258
+ return true;
259
+ }
260
+
261
+ } // namespace lzham
262
+
@@ -0,0 +1,14 @@
1
+ // File: lzham_huffman_codes.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+
5
+ namespace lzham
6
+ {
7
+ //const uint cHuffmanMaxSupportedSyms = 600;
8
+ const uint cHuffmanMaxSupportedSyms = 1024;
9
+
10
+ uint get_generate_huffman_codes_table_size();
11
+
12
+ bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret);
13
+
14
+ } // namespace lzham
@@ -0,0 +1,1527 @@
1
+ // File: lzham_lzdecomp.cpp
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ //
4
+ // See "Coroutines in C":
5
+ // http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
6
+ // Also see "Protothreads - Lightweight, Stackless Threads in C":
7
+ // http://www.sics.se/~adam/pt/
8
+ #include "lzham_core.h"
9
+ #include "lzham_decomp.h"
10
+ #include "lzham_symbol_codec.h"
11
+ #include "lzham_checksum.h"
12
+ #include "lzham_lzdecompbase.h"
13
+
14
+ using namespace lzham;
15
+
16
+ namespace lzham
17
+ {
18
+ static const uint8 s_literal_next_state[24] =
19
+ {
20
+ 0, 0, 0, 0, 1, 2, 3, // 0-6: literal states
21
+ 4, 5, 6, 4, 5, // 7-11: match states
22
+ 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 // 12-23: unused
23
+ };
24
+
25
+ static const uint s_huge_match_base_len[4] = { CLZDecompBase::cMaxMatchLen + 1, CLZDecompBase::cMaxMatchLen + 1 + 256, CLZDecompBase::cMaxMatchLen + 1 + 256 + 1024, CLZDecompBase::cMaxMatchLen + 1 + 256 + 1024 + 4096 };
26
+ static const uint8 s_huge_match_code_len[4] = { 8, 10, 12, 16 };
27
+
28
+ struct lzham_decompressor
29
+ {
30
+ void init();
31
+
32
+ template<bool unbuffered> lzham_decompress_status_t decompress();
33
+
34
+ void reset_huff_tables();
35
+ void reset_arith_tables();
36
+ void reset_all_tables();
37
+ void reset_huffman_table_update_rates();
38
+
39
+ int m_state;
40
+
41
+ CLZDecompBase m_lzBase;
42
+ symbol_codec m_codec;
43
+
44
+ uint32 m_raw_decomp_buf_size;
45
+ uint8 *m_pRaw_decomp_buf;
46
+ uint8 *m_pDecomp_buf;
47
+ uint32 m_decomp_adler32;
48
+
49
+ const uint8 *m_pIn_buf;
50
+ size_t *m_pIn_buf_size;
51
+ uint8 *m_pOut_buf;
52
+ size_t *m_pOut_buf_size;
53
+ bool m_no_more_input_bytes_flag;
54
+
55
+ uint8 *m_pOrig_out_buf;
56
+ size_t m_orig_out_buf_size;
57
+
58
+ lzham_decompress_params m_params;
59
+
60
+ lzham_decompress_status_t m_status;
61
+
62
+ quasi_adaptive_huffman_data_model m_lit_table;
63
+ quasi_adaptive_huffman_data_model m_delta_lit_table;
64
+ quasi_adaptive_huffman_data_model m_main_table;
65
+ quasi_adaptive_huffman_data_model m_rep_len_table[2];
66
+ quasi_adaptive_huffman_data_model m_large_len_table[2];
67
+ quasi_adaptive_huffman_data_model m_dist_lsb_table;
68
+
69
+ adaptive_bit_model m_is_match_model[CLZDecompBase::cNumStates];
70
+ adaptive_bit_model m_is_rep_model[CLZDecompBase::cNumStates];
71
+ adaptive_bit_model m_is_rep0_model[CLZDecompBase::cNumStates];
72
+ adaptive_bit_model m_is_rep0_single_byte_model[CLZDecompBase::cNumStates];
73
+ adaptive_bit_model m_is_rep1_model[CLZDecompBase::cNumStates];
74
+ adaptive_bit_model m_is_rep2_model[CLZDecompBase::cNumStates];
75
+
76
+ uint m_dst_ofs;
77
+ uint m_dst_highwater_ofs;
78
+
79
+ uint m_step;
80
+ uint m_block_step;
81
+ uint m_initial_step;
82
+
83
+ uint m_block_index;
84
+
85
+ int m_match_hist0;
86
+ int m_match_hist1;
87
+ int m_match_hist2;
88
+ int m_match_hist3;
89
+ uint m_cur_state;
90
+
91
+ uint m_start_block_dst_ofs;
92
+
93
+ uint m_block_type;
94
+
95
+ const uint8 *m_pFlush_src;
96
+ size_t m_flush_num_bytes_remaining;
97
+ size_t m_flush_n;
98
+
99
+ uint m_seed_bytes_to_ignore_when_flushing;
100
+
101
+ uint m_file_src_file_adler32;
102
+
103
+ uint m_rep_lit0;
104
+ uint m_match_len;
105
+ uint m_match_slot;
106
+ uint m_extra_bits;
107
+ uint m_num_extra_bits;
108
+
109
+ uint m_src_ofs;
110
+ const uint8* m_pCopy_src;
111
+ uint m_num_raw_bytes_remaining;
112
+
113
+ uint m_debug_is_match;
114
+ uint m_debug_match_len;
115
+ uint m_debug_match_dist;
116
+ uint m_debug_lit;
117
+
118
+ lzham_decompress_status_t m_z_last_status;
119
+ uint m_z_first_call;
120
+ uint m_z_has_flushed;
121
+ uint m_z_cmf;
122
+ uint m_z_flg;
123
+ uint m_z_dict_adler32;
124
+
125
+ uint m_tmp;
126
+ };
127
+
128
+ // Ordinarily I dislike macros like this, but in this case I think using them makes the decompression function easier to follow.
129
+
130
+ // Coroutine helpers.
131
+ #define LZHAM_CR_INITIAL_STATE 0
132
+ #define LZHAM_CR_BEGIN(state) switch( state ) { case LZHAM_CR_INITIAL_STATE:
133
+ #define LZHAM_CR_RETURN(state, result) do { state = __LINE__; return (result); case __LINE__:; } while (0)
134
+ #define LZHAM_CR_FINISH }
135
+
136
+ // Helpers to save/restore local variables (hopefully CPU registers) to memory.
137
+ #define LZHAM_RESTORE_STATE LZHAM_RESTORE_LOCAL_STATE \
138
+ match_hist0 = m_match_hist0; match_hist1 = m_match_hist1; match_hist2 = m_match_hist2; match_hist3 = m_match_hist3; \
139
+ cur_state = m_cur_state; dst_ofs = m_dst_ofs;
140
+
141
+ #define LZHAM_SAVE_STATE LZHAM_SAVE_LOCAL_STATE \
142
+ m_match_hist0 = match_hist0; m_match_hist1 = match_hist1; m_match_hist2 = match_hist2; m_match_hist3 = match_hist3; \
143
+ m_cur_state = cur_state; m_dst_ofs = dst_ofs;
144
+
145
+ // Helper that coroutine returns to the caller with a request for more input bytes.
146
+ #define LZHAM_DECODE_NEEDS_BYTES \
147
+ LZHAM_SAVE_STATE \
148
+ for ( ; ; ) \
149
+ { \
150
+ *m_pIn_buf_size = static_cast<size_t>(m_codec.decode_get_bytes_consumed()); \
151
+ *m_pOut_buf_size = 0; \
152
+ LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT); \
153
+ m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag); \
154
+ if ((m_codec.m_decode_buf_eof) || (m_codec.m_decode_buf_size)) break; \
155
+ } \
156
+ LZHAM_RESTORE_STATE
157
+
158
+ #if LZHAM_PLATFORM_X360
159
+ #define LZHAM_BULK_MEMCPY XMemCpy
160
+ #define LZHAM_MEMCPY memcpy
161
+ #else
162
+ #define LZHAM_BULK_MEMCPY memcpy
163
+ #define LZHAM_MEMCPY memcpy
164
+ #endif
165
+
166
+ // Flush the output buffer/dictionary by doing a coroutine return to the caller.
167
+ // Buffered mode only.
168
+ #define LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_ofs) \
169
+ LZHAM_SAVE_STATE \
170
+ m_pFlush_src = m_pDecomp_buf + m_seed_bytes_to_ignore_when_flushing + m_dst_highwater_ofs; \
171
+ m_flush_num_bytes_remaining = dict_ofs - m_seed_bytes_to_ignore_when_flushing - m_dst_highwater_ofs; \
172
+ m_seed_bytes_to_ignore_when_flushing = 0; \
173
+ m_dst_highwater_ofs = dict_ofs & dict_size_mask; \
174
+ while (m_flush_num_bytes_remaining) \
175
+ { \
176
+ m_flush_n = LZHAM_MIN(m_flush_num_bytes_remaining, *m_pOut_buf_size); \
177
+ if (0 == (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_COMPUTE_ADLER32)) \
178
+ { \
179
+ LZHAM_BULK_MEMCPY(m_pOut_buf, m_pFlush_src, m_flush_n); \
180
+ } \
181
+ else \
182
+ { \
183
+ size_t copy_ofs = 0; \
184
+ while (copy_ofs < m_flush_n) \
185
+ { \
186
+ const uint cBytesToMemCpyPerIteration = 8192U; \
187
+ size_t bytes_to_copy = LZHAM_MIN((size_t)(m_flush_n - copy_ofs), cBytesToMemCpyPerIteration); \
188
+ LZHAM_MEMCPY(m_pOut_buf + copy_ofs, m_pFlush_src + copy_ofs, bytes_to_copy); \
189
+ m_decomp_adler32 = adler32(m_pFlush_src + copy_ofs, bytes_to_copy, m_decomp_adler32); \
190
+ copy_ofs += bytes_to_copy; \
191
+ } \
192
+ } \
193
+ *m_pIn_buf_size = static_cast<size_t>(m_codec.decode_get_bytes_consumed()); \
194
+ *m_pOut_buf_size = m_flush_n; \
195
+ LZHAM_CR_RETURN(m_state, m_flush_n ? LZHAM_DECOMP_STATUS_NOT_FINISHED : LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT); \
196
+ m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag); \
197
+ m_pFlush_src += m_flush_n; \
198
+ m_flush_num_bytes_remaining -= m_flush_n; \
199
+ } \
200
+ LZHAM_RESTORE_STATE
201
+
202
+ #define LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, result, model) LZHAM_SYMBOL_CODEC_DECODE_ADAPTIVE_HUFFMAN(codec, result, model)
203
+
204
+ //------------------------------------------------------------------------------------------------------------------
205
+ void lzham_decompressor::init()
206
+ {
207
+ m_lzBase.init_position_slots(m_params.m_dict_size_log2);
208
+
209
+ #ifdef LZHAM_LZDEBUG
210
+ if (m_pDecomp_buf)
211
+ memset(m_pDecomp_buf, 0xCE, 1U << m_params.m_dict_size_log2);
212
+ #endif
213
+
214
+ m_state = LZHAM_CR_INITIAL_STATE;
215
+ m_step = 0;
216
+ m_block_step = 0;
217
+ m_block_index = 0;
218
+ m_initial_step = 0;
219
+
220
+ m_dst_ofs = 0;
221
+ m_dst_highwater_ofs = 0;
222
+
223
+ m_pIn_buf = NULL;
224
+ m_pIn_buf_size = NULL;
225
+ m_pOut_buf = NULL;
226
+ m_pOut_buf_size = NULL;
227
+ m_no_more_input_bytes_flag = false;
228
+ m_status = LZHAM_DECOMP_STATUS_NOT_FINISHED;
229
+ m_pOrig_out_buf = NULL;
230
+ m_orig_out_buf_size = 0;
231
+ m_decomp_adler32 = cInitAdler32;
232
+ m_seed_bytes_to_ignore_when_flushing = 0;
233
+
234
+ m_z_last_status = LZHAM_DECOMP_STATUS_NOT_FINISHED;
235
+ m_z_first_call = 1;
236
+ m_z_has_flushed = 0;
237
+ m_z_cmf = 0;
238
+ m_z_flg = 0;
239
+ m_z_dict_adler32 = 0;
240
+
241
+ m_tmp = 0;
242
+
243
+ m_match_hist0 = 0;
244
+ m_match_hist1 = 0;
245
+ m_match_hist2 = 0;
246
+ m_match_hist3 = 0;
247
+ m_cur_state = 0;
248
+
249
+ m_start_block_dst_ofs = 0;
250
+ m_block_type = 0;
251
+ m_flush_num_bytes_remaining = 0;
252
+ m_flush_n = 0;
253
+ m_file_src_file_adler32 = 0;
254
+ m_rep_lit0 = 0;
255
+ m_match_len = 0;
256
+ m_match_slot = 0;
257
+ m_extra_bits = 0;
258
+ m_num_extra_bits = 0;
259
+ m_src_ofs = 0;
260
+ m_pCopy_src = NULL;
261
+ m_num_raw_bytes_remaining = 0;
262
+
263
+ m_codec.clear();
264
+ }
265
+
266
+ void lzham_decompressor::reset_huff_tables()
267
+ {
268
+ m_lit_table.reset();
269
+ m_delta_lit_table.reset();
270
+
271
+ m_main_table.reset();
272
+
273
+ for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
274
+ m_rep_len_table[i].reset();
275
+
276
+ for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
277
+ m_large_len_table[i].reset();
278
+
279
+ m_dist_lsb_table.reset();
280
+ }
281
+
282
+ void lzham_decompressor::reset_arith_tables()
283
+ {
284
+ for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_match_model); i++)
285
+ m_is_match_model[i].clear();
286
+
287
+ for (uint i = 0; i < CLZDecompBase::cNumStates; i++)
288
+ {
289
+ m_is_rep_model[i].clear();
290
+ m_is_rep0_model[i].clear();
291
+ m_is_rep0_single_byte_model[i].clear();
292
+ m_is_rep1_model[i].clear();
293
+ m_is_rep2_model[i].clear();
294
+ }
295
+ }
296
+
297
+ void lzham_decompressor::reset_all_tables()
298
+ {
299
+ reset_huff_tables();
300
+
301
+ reset_arith_tables();
302
+ }
303
+
304
+ void lzham_decompressor::reset_huffman_table_update_rates()
305
+ {
306
+ m_lit_table.reset_update_rate();
307
+ m_delta_lit_table.reset_update_rate();
308
+
309
+ m_main_table.reset_update_rate();
310
+
311
+ for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
312
+ m_rep_len_table[i].reset_update_rate();
313
+
314
+ for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
315
+ m_large_len_table[i].reset_update_rate();
316
+
317
+ m_dist_lsb_table.reset_update_rate();
318
+ }
319
+
320
+ //------------------------------------------------------------------------------------------------------------------
321
+ // Decompression method. Implemented as a coroutine so it can be paused and resumed to support streaming.
322
+ //------------------------------------------------------------------------------------------------------------------
323
+ template<bool unbuffered>
324
+ lzham_decompress_status_t lzham_decompressor::decompress()
325
+ {
326
+ // Important: This function is a coroutine. ANY locals variables that need to be preserved across coroutine
327
+ // returns must be either be a member variable, or a local which is saved/restored to a member variable at
328
+ // the right times. (This makes this function difficult to follow and freaking ugly due to the macros of doom - but hey it works.)
329
+ // The most often used variables are in locals so the compiler hopefully puts them into CPU registers.
330
+ symbol_codec &codec = m_codec;
331
+ const uint dict_size = 1U << m_params.m_dict_size_log2;
332
+ const uint dict_size_mask = unbuffered ? UINT_MAX : (dict_size - 1);
333
+
334
+ int match_hist0 = 0, match_hist1 = 0, match_hist2 = 0, match_hist3 = 0;
335
+ uint cur_state = 0, dst_ofs = 0;
336
+
337
+ const size_t out_buf_size = *m_pOut_buf_size;
338
+
339
+ uint8* pDst = unbuffered ? reinterpret_cast<uint8*>(m_pOut_buf) : reinterpret_cast<uint8*>(m_pDecomp_buf);
340
+ uint8* pDst_end = unbuffered ? (reinterpret_cast<uint8*>(m_pOut_buf) + out_buf_size) : (reinterpret_cast<uint8*>(m_pDecomp_buf) + dict_size);
341
+
342
+ LZHAM_SYMBOL_CODEC_DECODE_DECLARE(codec);
343
+
344
+ #define LZHAM_SAVE_LOCAL_STATE
345
+ #define LZHAM_RESTORE_LOCAL_STATE
346
+
347
+ // Important: Do not use any switch() statements below here.
348
+ LZHAM_CR_BEGIN(m_state)
349
+
350
+ if ((!unbuffered) && (m_params.m_num_seed_bytes))
351
+ {
352
+ LZHAM_BULK_MEMCPY(pDst, m_params.m_pSeed_bytes, m_params.m_num_seed_bytes);
353
+ dst_ofs += m_params.m_num_seed_bytes;
354
+ if (dst_ofs >= dict_size)
355
+ dst_ofs = 0;
356
+ else
357
+ m_seed_bytes_to_ignore_when_flushing = dst_ofs;
358
+ }
359
+
360
+ if (!m_codec.start_decoding(m_pIn_buf, *m_pIn_buf_size, m_no_more_input_bytes_flag, NULL, NULL))
361
+ return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
362
+
363
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
364
+
365
+ {
366
+ if (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM)
367
+ {
368
+ uint check;
369
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_z_cmf, 8);
370
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_z_flg, 8);
371
+ check = ((m_z_cmf << 8) + m_z_flg) % 31;
372
+ if ((check != 0) || ((m_z_cmf & 15) != LZHAM_Z_LZHAM))
373
+ return LZHAM_DECOMP_STATUS_FAILED_BAD_ZLIB_HEADER;
374
+ if (m_z_flg & 32)
375
+ {
376
+ if ((!m_params.m_pSeed_bytes) || (unbuffered))
377
+ return LZHAM_DECOMP_STATUS_FAILED_NEED_SEED_BYTES;
378
+ m_z_dict_adler32 = 0;
379
+ for (m_tmp = 0; m_tmp < 4; ++m_tmp)
380
+ {
381
+ uint n; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 8);
382
+ m_z_dict_adler32 = (m_z_dict_adler32 << 8) | n;
383
+ }
384
+ if (adler32(m_params.m_pSeed_bytes, m_params.m_num_seed_bytes) != m_z_dict_adler32)
385
+ return LZHAM_DECOMP_STATUS_FAILED_BAD_SEED_BYTES;
386
+ }
387
+ }
388
+
389
+ {
390
+ // Was written by lzcompressor::send_configuration().
391
+ //uint tmp;
392
+ //LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, tmp, 2);
393
+ }
394
+
395
+ uint max_update_interval = m_params.m_table_max_update_interval, update_interval_slow_rate = m_params.m_table_update_interval_slow_rate;
396
+ if (!max_update_interval && !update_interval_slow_rate)
397
+ {
398
+ uint rate = m_params.m_table_update_rate;
399
+ if (!rate)
400
+ rate = LZHAM_DEFAULT_TABLE_UPDATE_RATE;
401
+ rate = math::clamp<uint>(rate, 1, LZHAM_FASTEST_TABLE_UPDATE_RATE) - 1;
402
+ max_update_interval = g_table_update_settings[rate].m_max_update_interval;
403
+ update_interval_slow_rate = g_table_update_settings[rate].m_slow_rate;
404
+ }
405
+
406
+ bool succeeded = m_lit_table.init2(false, 256, max_update_interval, update_interval_slow_rate, NULL);
407
+ succeeded = succeeded && m_delta_lit_table.assign(m_lit_table);
408
+
409
+ succeeded = succeeded && m_main_table.init2(false, CLZDecompBase::cLZXNumSpecialLengths + (m_lzBase.m_num_lzx_slots - CLZDecompBase::cLZXLowestUsableMatchSlot) * 8, max_update_interval, update_interval_slow_rate, NULL);
410
+
411
+ succeeded = succeeded && m_rep_len_table[0].init2(false, CLZDecompBase::cNumHugeMatchCodes + (CLZDecompBase::cMaxMatchLen - CLZDecompBase::cMinMatchLen + 1), max_update_interval, update_interval_slow_rate, NULL);
412
+ succeeded = succeeded && m_rep_len_table[1].assign(m_rep_len_table[0]);
413
+
414
+ succeeded = succeeded && m_large_len_table[0].init2(false, CLZDecompBase::cNumHugeMatchCodes + CLZDecompBase::cLZXNumSecondaryLengths, max_update_interval, update_interval_slow_rate, NULL);
415
+ succeeded = succeeded && m_large_len_table[1].assign(m_large_len_table[0]);
416
+
417
+ succeeded = succeeded && m_dist_lsb_table.init2(false, 16, max_update_interval, update_interval_slow_rate, NULL);
418
+ if (!succeeded)
419
+ return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
420
+ }
421
+
422
+ // Output block loop.
423
+ do
424
+ {
425
+ #ifdef LZHAM_LZDEBUG
426
+ uint outer_sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, 12);
427
+ LZHAM_VERIFY(outer_sync_marker == 166);
428
+ #endif
429
+
430
+ // Decode block type.
431
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_block_type, CLZDecompBase::cBlockHeaderBits);
432
+
433
+ if (m_block_type == CLZDecompBase::cSyncBlock)
434
+ {
435
+ // Sync block
436
+ // Reset either the symbol table update rates, or all statistics, then force a coroutine return to give the caller a chance to handle the output right now.
437
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_tmp, CLZDecompBase::cBlockFlushTypeBits);
438
+
439
+ // See lzcompressor::send_sync_block() (TODO: make these an enum)
440
+ if (m_tmp == 1)
441
+ reset_huffman_table_update_rates();
442
+ else if (m_tmp == 2)
443
+ reset_all_tables();
444
+
445
+ LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
446
+
447
+ uint n; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 16);
448
+ if (n != 0)
449
+ {
450
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
451
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
452
+ *m_pOut_buf_size = 0;
453
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_SYNC_BLOCK); }
454
+ }
455
+
456
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 16);
457
+ if (n != 0xFFFF)
458
+ {
459
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
460
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
461
+ *m_pOut_buf_size = 0;
462
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_SYNC_BLOCK); }
463
+ }
464
+
465
+ // See lzcompressor::send_sync_block() (TODO: make these an enum)
466
+ if ((m_tmp == 2) || (m_tmp == 3))
467
+ {
468
+ // It's a sync or full flush, so immediately give caller whatever output we have. Also gives the caller a chance to reposition the input stream ptr somewhere else before continuing.
469
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
470
+
471
+ if ((!unbuffered) && (dst_ofs))
472
+ {
473
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dst_ofs);
474
+ }
475
+ else
476
+ {
477
+ if (unbuffered)
478
+ {
479
+ LZHAM_ASSERT(dst_ofs >= m_dst_highwater_ofs);
480
+ }
481
+ else
482
+ {
483
+ LZHAM_ASSERT(!m_dst_highwater_ofs);
484
+ }
485
+
486
+ // unbuffered, or dst_ofs==0
487
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
488
+ *m_pOut_buf_size = dst_ofs - m_dst_highwater_ofs;
489
+
490
+ // Partial/sync flushes in unbuffered mode details:
491
+ // We assume the caller doesn't move the output buffer between calls AND the pointer to the output buffer input parameter won't change between calls (i.e.
492
+ // it *always* points to the beginning of the decompressed stream). The caller will need to track the current output buffer offset.
493
+ m_dst_highwater_ofs = dst_ofs;
494
+
495
+ LZHAM_SAVE_STATE
496
+ LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NOT_FINISHED);
497
+ LZHAM_RESTORE_STATE
498
+
499
+ m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag);
500
+ }
501
+
502
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
503
+ }
504
+ }
505
+ else if (m_block_type == CLZDecompBase::cRawBlock)
506
+ {
507
+ // Raw block handling is complex because we ultimately want to (safely) handle as many bytes as possible using a small number of memcpy()'s.
508
+ uint num_raw_bytes_remaining;
509
+ num_raw_bytes_remaining = 0;
510
+
511
+ #undef LZHAM_SAVE_LOCAL_STATE
512
+ #undef LZHAM_RESTORE_LOCAL_STATE
513
+ #define LZHAM_SAVE_LOCAL_STATE m_num_raw_bytes_remaining = num_raw_bytes_remaining;
514
+ #define LZHAM_RESTORE_LOCAL_STATE num_raw_bytes_remaining = m_num_raw_bytes_remaining;
515
+
516
+ // Determine how large this raw block is.
517
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, num_raw_bytes_remaining, 24);
518
+
519
+ // Get and verify raw block length check bits.
520
+ uint num_raw_bytes_check_bits; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, num_raw_bytes_check_bits, 8);
521
+ uint raw_bytes_remaining0, raw_bytes_remaining1, raw_bytes_remaining2;
522
+ raw_bytes_remaining0 = num_raw_bytes_remaining & 0xFF;
523
+ raw_bytes_remaining1 = (num_raw_bytes_remaining >> 8) & 0xFF;
524
+ raw_bytes_remaining2 = (num_raw_bytes_remaining >> 16) & 0xFF;
525
+ if (num_raw_bytes_check_bits != ((raw_bytes_remaining0 ^ raw_bytes_remaining1) ^ raw_bytes_remaining2))
526
+ {
527
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
528
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
529
+ *m_pOut_buf_size = 0;
530
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_RAW_BLOCK); }
531
+ }
532
+
533
+ num_raw_bytes_remaining++;
534
+
535
+ // Discard any partial bytes from the bit buffer (align up to the next byte).
536
+ LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
537
+
538
+ // Flush any full bytes from the bit buffer.
539
+ do
540
+ {
541
+ int b;
542
+ LZHAM_SYMBOL_CODEC_DECODE_REMOVE_BYTE_FROM_BIT_BUF(codec, b);
543
+ if (b < 0)
544
+ break;
545
+
546
+ if ((unbuffered) && (dst_ofs >= out_buf_size))
547
+ {
548
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
549
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
550
+ *m_pOut_buf_size = 0;
551
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
552
+ }
553
+
554
+ pDst[dst_ofs++] = static_cast<uint8>(b);
555
+
556
+ if ((!unbuffered) && (dst_ofs > dict_size_mask))
557
+ {
558
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
559
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
560
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
561
+ dst_ofs = 0;
562
+ }
563
+
564
+ num_raw_bytes_remaining--;
565
+ } while (num_raw_bytes_remaining);
566
+
567
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
568
+
569
+ // Now handle the bulk of the raw data with memcpy().
570
+ while (num_raw_bytes_remaining)
571
+ {
572
+ uint64 in_buf_ofs, in_buf_remaining;
573
+ in_buf_ofs = codec.decode_get_bytes_consumed();
574
+ in_buf_remaining = *m_pIn_buf_size - in_buf_ofs;
575
+
576
+ while (!in_buf_remaining)
577
+ {
578
+ // We need more bytes from the caller.
579
+ *m_pIn_buf_size = static_cast<size_t>(in_buf_ofs);
580
+ *m_pOut_buf_size = 0;
581
+
582
+ if (m_no_more_input_bytes_flag)
583
+ {
584
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_EXPECTED_MORE_RAW_BYTES); }
585
+ }
586
+
587
+ LZHAM_SAVE_STATE
588
+ LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT);
589
+ LZHAM_RESTORE_STATE
590
+
591
+ m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag);
592
+
593
+ in_buf_ofs = 0;
594
+ in_buf_remaining = *m_pIn_buf_size;
595
+ }
596
+
597
+ // Determine how many bytes we can safely memcpy() in a single call.
598
+ uint num_bytes_to_copy;
599
+ num_bytes_to_copy = static_cast<uint>(LZHAM_MIN(num_raw_bytes_remaining, in_buf_remaining));
600
+ if (!unbuffered)
601
+ num_bytes_to_copy = LZHAM_MIN(num_bytes_to_copy, dict_size - dst_ofs);
602
+
603
+ if ((unbuffered) && ((dst_ofs + num_bytes_to_copy) > out_buf_size))
604
+ {
605
+ // Output buffer is not large enough.
606
+ *m_pIn_buf_size = static_cast<size_t>(in_buf_ofs);
607
+ *m_pOut_buf_size = 0;
608
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
609
+ }
610
+
611
+ // Copy the raw bytes.
612
+ LZHAM_BULK_MEMCPY(pDst + dst_ofs, m_pIn_buf + in_buf_ofs, num_bytes_to_copy);
613
+
614
+ in_buf_ofs += num_bytes_to_copy;
615
+ num_raw_bytes_remaining -= num_bytes_to_copy;
616
+
617
+ codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf + in_buf_ofs, m_no_more_input_bytes_flag);
618
+
619
+ dst_ofs += num_bytes_to_copy;
620
+
621
+ if ((!unbuffered) && (dst_ofs > dict_size_mask))
622
+ {
623
+ LZHAM_ASSERT(dst_ofs == dict_size);
624
+
625
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
626
+
627
+ dst_ofs = 0;
628
+ }
629
+ }
630
+
631
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
632
+
633
+ #undef LZHAM_SAVE_LOCAL_STATE
634
+ #undef LZHAM_RESTORE_LOCAL_STATE
635
+ #define LZHAM_SAVE_LOCAL_STATE
636
+ #define LZHAM_RESTORE_LOCAL_STATE
637
+ }
638
+ else if (m_block_type == CLZDecompBase::cCompBlock)
639
+ {
640
+ LZHAM_SYMBOL_CODEC_DECODE_ARITH_START(codec)
641
+
642
+ match_hist0 = 1;
643
+ match_hist1 = 1;
644
+ match_hist2 = 1;
645
+ match_hist3 = 1;
646
+ cur_state = 0;
647
+
648
+ m_start_block_dst_ofs = dst_ofs;
649
+
650
+ {
651
+ uint block_flush_type; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, block_flush_type, CLZDecompBase::cBlockFlushTypeBits);
652
+ if (block_flush_type == 1)
653
+ reset_huffman_table_update_rates();
654
+ else if (block_flush_type == 2)
655
+ reset_all_tables();
656
+ }
657
+
658
+ #ifdef LZHAM_LZDEBUG
659
+ m_initial_step = m_step;
660
+ m_block_step = 0;
661
+ for ( ; ; m_step++, m_block_step++)
662
+ #else
663
+ for ( ; ; )
664
+ #endif
665
+ {
666
+ #ifdef LZHAM_LZDEBUG
667
+ uint sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, x, CLZDecompBase::cLZHAMDebugSyncMarkerBits);
668
+ LZHAM_VERIFY(sync_marker == CLZDecompBase::cLZHAMDebugSyncMarkerValue);
669
+
670
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_is_match, 1);
671
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_match_len, 17);
672
+
673
+ uint debug_cur_state; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, debug_cur_state, 4);
674
+ LZHAM_VERIFY(cur_state == debug_cur_state);
675
+ #endif
676
+
677
+ // Read "is match" bit.
678
+ uint match_model_index;
679
+ match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(cur_state);
680
+ LZHAM_ASSERT(match_model_index < LZHAM_ARRAY_SIZE(m_is_match_model));
681
+
682
+ uint is_match_bit; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_match_bit, m_is_match_model[match_model_index]);
683
+
684
+ #ifdef LZHAM_LZDEBUG
685
+ LZHAM_VERIFY(is_match_bit == m_debug_is_match);
686
+ #endif
687
+
688
+ if (LZHAM_BUILTIN_EXPECT(!is_match_bit, 0))
689
+ {
690
+ // Handle literal.
691
+
692
+ #ifdef LZHAM_LZDEBUG
693
+ LZHAM_VERIFY(m_debug_match_len == 1);
694
+ #endif
695
+
696
+ #ifdef LZHAM_LZDEBUG
697
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_lit, 8);
698
+ #endif
699
+
700
+ if ((unbuffered) && (LZHAM_BUILTIN_EXPECT(dst_ofs >= out_buf_size, 0)))
701
+ {
702
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
703
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
704
+ *m_pOut_buf_size = 0;
705
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
706
+ }
707
+
708
+ if (LZHAM_BUILTIN_EXPECT(cur_state < CLZDecompBase::cNumLitStates, 1))
709
+ {
710
+ // Regular literal
711
+ uint r; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, r, m_lit_table);
712
+ pDst[dst_ofs] = static_cast<uint8>(r);
713
+
714
+ #ifdef LZHAM_LZDEBUG
715
+ LZHAM_VERIFY(pDst[dst_ofs] == m_debug_lit);
716
+ #endif
717
+ }
718
+ else
719
+ {
720
+ // Delta literal
721
+ uint match_hist0_ofs, rep_lit0;
722
+
723
+ // Determine delta literal's partial context.
724
+ match_hist0_ofs = dst_ofs - match_hist0;
725
+ rep_lit0 = pDst[match_hist0_ofs & dict_size_mask];
726
+
727
+ #undef LZHAM_SAVE_LOCAL_STATE
728
+ #undef LZHAM_RESTORE_LOCAL_STATE
729
+ #define LZHAM_SAVE_LOCAL_STATE m_rep_lit0 = rep_lit0;
730
+ #define LZHAM_RESTORE_LOCAL_STATE rep_lit0 = m_rep_lit0;
731
+
732
+ #ifdef LZHAM_LZDEBUG
733
+ uint debug_rep_lit0; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, debug_rep_lit0, 8);
734
+ LZHAM_VERIFY(debug_rep_lit0 == rep_lit0);
735
+ #endif
736
+
737
+ uint r; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, r, m_delta_lit_table);
738
+ r ^= rep_lit0;
739
+ pDst[dst_ofs] = static_cast<uint8>(r);
740
+
741
+ #ifdef LZHAM_LZDEBUG
742
+ LZHAM_VERIFY(pDst[dst_ofs] == m_debug_lit);
743
+ #endif
744
+
745
+ #undef LZHAM_SAVE_LOCAL_STATE
746
+ #undef LZHAM_RESTORE_LOCAL_STATE
747
+ #define LZHAM_SAVE_LOCAL_STATE
748
+ #define LZHAM_RESTORE_LOCAL_STATE
749
+ }
750
+
751
+ cur_state = s_literal_next_state[cur_state];
752
+
753
+ dst_ofs++;
754
+ if ((!unbuffered) && (LZHAM_BUILTIN_EXPECT(dst_ofs > dict_size_mask, 0)))
755
+ {
756
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
757
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
758
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
759
+ dst_ofs = 0;
760
+ }
761
+ }
762
+ else
763
+ {
764
+ // Handle match.
765
+ uint match_len;
766
+ match_len = 1;
767
+
768
+ #undef LZHAM_SAVE_LOCAL_STATE
769
+ #undef LZHAM_RESTORE_LOCAL_STATE
770
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len;
771
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len;
772
+
773
+ // Determine if match is a rep_match, and if so what type.
774
+ uint is_rep; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep, m_is_rep_model[cur_state]);
775
+ if (LZHAM_BUILTIN_EXPECT(is_rep, 1))
776
+ {
777
+ uint is_rep0; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep0, m_is_rep0_model[cur_state]);
778
+ if (LZHAM_BUILTIN_EXPECT(is_rep0, 1))
779
+ {
780
+ uint is_rep0_len1; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep0_len1, m_is_rep0_single_byte_model[cur_state]);
781
+ if (LZHAM_BUILTIN_EXPECT(is_rep0_len1, 1))
782
+ {
783
+ cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 9 : 11;
784
+ }
785
+ else
786
+ {
787
+ LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, match_len, m_rep_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
788
+ match_len += CLZDecompBase::cMinMatchLen;
789
+
790
+ if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
791
+ {
792
+ // Decode "huge" match length.
793
+ match_len = 0;
794
+ do
795
+ {
796
+ uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
797
+ if (!b)
798
+ break;
799
+ match_len++;
800
+ } while (match_len < 3);
801
+ uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
802
+ match_len = s_huge_match_base_len[match_len] + k;
803
+ }
804
+
805
+ cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 8 : 11;
806
+ }
807
+ }
808
+ else
809
+ {
810
+ LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, match_len, m_rep_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
811
+ match_len += CLZDecompBase::cMinMatchLen;
812
+
813
+ if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
814
+ {
815
+ // Decode "huge" match length.
816
+ match_len = 0;
817
+ do
818
+ {
819
+ uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
820
+ if (!b)
821
+ break;
822
+ match_len++;
823
+ } while (match_len < 3);
824
+ uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
825
+ match_len = s_huge_match_base_len[match_len] + k;
826
+ }
827
+
828
+ uint is_rep1; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep1, m_is_rep1_model[cur_state]);
829
+ if (LZHAM_BUILTIN_EXPECT(is_rep1, 1))
830
+ {
831
+ uint temp = match_hist1;
832
+ match_hist1 = match_hist0;
833
+ match_hist0 = temp;
834
+ }
835
+ else
836
+ {
837
+ uint is_rep2; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep2, m_is_rep2_model[cur_state]);
838
+
839
+ if (LZHAM_BUILTIN_EXPECT(is_rep2, 1))
840
+ {
841
+ // rep2
842
+ uint temp = match_hist2;
843
+ match_hist2 = match_hist1;
844
+ match_hist1 = match_hist0;
845
+ match_hist0 = temp;
846
+ }
847
+ else
848
+ {
849
+ // rep3
850
+ uint temp = match_hist3;
851
+ match_hist3 = match_hist2;
852
+ match_hist2 = match_hist1;
853
+ match_hist1 = match_hist0;
854
+ match_hist0 = temp;
855
+ }
856
+ }
857
+
858
+ cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 8 : 11;
859
+ }
860
+ }
861
+ else
862
+ {
863
+ // Handle normal/full match.
864
+ uint sym; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, sym, m_main_table);
865
+ sym -= CLZDecompBase::cLZXNumSpecialLengths;
866
+
867
+ if (LZHAM_BUILTIN_EXPECT(static_cast<int>(sym) < 0, 0))
868
+ {
869
+ // Handle special symbols.
870
+ if (static_cast<int>(sym) == (CLZDecompBase::cLZXSpecialCodeEndOfBlockCode - CLZDecompBase::cLZXNumSpecialLengths))
871
+ break;
872
+ else
873
+ {
874
+ // Must be cLZXSpecialCodePartialStateReset.
875
+ match_hist0 = 1;
876
+ match_hist1 = 1;
877
+ match_hist2 = 1;
878
+ match_hist3 = 1;
879
+ cur_state = 0;
880
+ continue;
881
+ }
882
+ }
883
+
884
+ // Low 3 bits of symbol = match length category, higher bits = distance category.
885
+ match_len = (sym & 7) + 2;
886
+
887
+ uint match_slot;
888
+ match_slot = (sym >> 3) + CLZDecompBase::cLZXLowestUsableMatchSlot;
889
+
890
+ #undef LZHAM_SAVE_LOCAL_STATE
891
+ #undef LZHAM_RESTORE_LOCAL_STATE
892
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot;
893
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot;
894
+
895
+ if (LZHAM_BUILTIN_EXPECT(match_len == 9, 0))
896
+ {
897
+ // Match is >= 9 bytes, decode the actual length.
898
+ uint e; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, e, m_large_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
899
+ match_len += e;
900
+
901
+ if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
902
+ {
903
+ // Decode "huge" match length.
904
+ match_len = 0;
905
+ do
906
+ {
907
+ uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
908
+ if (!b)
909
+ break;
910
+ match_len++;
911
+ } while (match_len < 3);
912
+ uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
913
+ match_len = s_huge_match_base_len[match_len] + k;
914
+ }
915
+ }
916
+
917
+ uint num_extra_bits;
918
+ num_extra_bits = m_lzBase.m_lzx_position_extra_bits[match_slot];
919
+
920
+ uint extra_bits;
921
+
922
+ #undef LZHAM_SAVE_LOCAL_STATE
923
+ #undef LZHAM_RESTORE_LOCAL_STATE
924
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot; m_num_extra_bits = num_extra_bits;
925
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot; num_extra_bits = m_num_extra_bits;
926
+
927
+ if (LZHAM_BUILTIN_EXPECT(num_extra_bits < 3, 0))
928
+ {
929
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, extra_bits, num_extra_bits);
930
+ }
931
+ else
932
+ {
933
+ extra_bits = 0;
934
+ if (LZHAM_BUILTIN_EXPECT(num_extra_bits > 4, 1))
935
+ {
936
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, extra_bits, num_extra_bits - 4);
937
+ extra_bits <<= 4;
938
+ }
939
+
940
+ #undef LZHAM_SAVE_LOCAL_STATE
941
+ #undef LZHAM_RESTORE_LOCAL_STATE
942
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot; m_extra_bits = extra_bits;
943
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot; extra_bits = m_extra_bits;
944
+
945
+ uint j; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, j, m_dist_lsb_table);
946
+ extra_bits += j;
947
+ }
948
+
949
+ match_hist3 = match_hist2;
950
+ match_hist2 = match_hist1;
951
+ match_hist1 = match_hist0;
952
+ match_hist0 = m_lzBase.m_lzx_position_base[match_slot] + extra_bits;
953
+
954
+ cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? CLZDecompBase::cNumLitStates : CLZDecompBase::cNumLitStates + 3;
955
+
956
+ #undef LZHAM_SAVE_LOCAL_STATE
957
+ #undef LZHAM_RESTORE_LOCAL_STATE
958
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len;
959
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len;
960
+ }
961
+
962
+ // We have the match's length and distance, now do the copy.
963
+
964
+ #ifdef LZHAM_LZDEBUG
965
+ LZHAM_VERIFY(match_len == m_debug_match_len);
966
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_match_dist, 25);
967
+ uint d; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, d, 4);
968
+ m_debug_match_dist = (m_debug_match_dist << 4) | d;
969
+ LZHAM_VERIFY((uint)match_hist0 == m_debug_match_dist);
970
+ #endif
971
+ if ( (unbuffered) && LZHAM_BUILTIN_EXPECT((((size_t)match_hist0 > dst_ofs) || ((dst_ofs + match_len) > out_buf_size)), 0) )
972
+ {
973
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
974
+ *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
975
+ *m_pOut_buf_size = 0;
976
+ for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_CODE); }
977
+ }
978
+
979
+ uint src_ofs;
980
+ const uint8* pCopy_src;
981
+ src_ofs = (dst_ofs - match_hist0) & dict_size_mask;
982
+ pCopy_src = pDst + src_ofs;
983
+
984
+ #undef LZHAM_SAVE_LOCAL_STATE
985
+ #undef LZHAM_RESTORE_LOCAL_STATE
986
+ #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_src_ofs = src_ofs; m_pCopy_src = pCopy_src;
987
+ #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; src_ofs = m_src_ofs; pCopy_src = m_pCopy_src;
988
+
989
+ if ( (!unbuffered) && LZHAM_BUILTIN_EXPECT( ((LZHAM_MAX(src_ofs, dst_ofs) + match_len) > dict_size_mask), 0) )
990
+ {
991
+ // Match source or destination wraps around the end of the dictionary to the beginning, so handle the copy one byte at a time.
992
+ do
993
+ {
994
+ pDst[dst_ofs++] = *pCopy_src++;
995
+
996
+ if (LZHAM_BUILTIN_EXPECT(pCopy_src == pDst_end, 0))
997
+ pCopy_src = pDst;
998
+
999
+ if (LZHAM_BUILTIN_EXPECT(dst_ofs > dict_size_mask, 0))
1000
+ {
1001
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
1002
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
1003
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
1004
+ dst_ofs = 0;
1005
+ }
1006
+
1007
+ match_len--;
1008
+ } while (LZHAM_BUILTIN_EXPECT(match_len > 0, 1));
1009
+ }
1010
+ else
1011
+ {
1012
+ uint8* pCopy_dst = pDst + dst_ofs;
1013
+ if (LZHAM_BUILTIN_EXPECT(match_hist0 == 1, 0))
1014
+ {
1015
+ // Handle byte runs.
1016
+ uint8 c = *pCopy_src;
1017
+ if (LZHAM_BUILTIN_EXPECT(match_len < 8, 1))
1018
+ {
1019
+ for (int i = match_len; i > 0; i--)
1020
+ *pCopy_dst++ = c;
1021
+ }
1022
+ else
1023
+ {
1024
+ memset(pCopy_dst, c, match_len);
1025
+ }
1026
+ }
1027
+ else
1028
+ {
1029
+ // Handle matches of length 2 or higher.
1030
+ if (LZHAM_BUILTIN_EXPECT(((match_len < 8) || ((int)match_len > match_hist0)), 1))
1031
+ {
1032
+ for (int i = match_len; i > 0; i--)
1033
+ *pCopy_dst++ = *pCopy_src++;
1034
+ }
1035
+ else
1036
+ {
1037
+ LZHAM_MEMCPY(pCopy_dst, pCopy_src, match_len);
1038
+ }
1039
+ }
1040
+ dst_ofs += match_len;
1041
+ }
1042
+ } // lit or match
1043
+
1044
+ #undef LZHAM_SAVE_LOCAL_STATE
1045
+ #undef LZHAM_RESTORE_LOCAL_STATE
1046
+ #define LZHAM_SAVE_LOCAL_STATE
1047
+ #define LZHAM_RESTORE_LOCAL_STATE
1048
+ } // for ( ; ; )
1049
+
1050
+ #ifdef LZHAM_LZDEBUG
1051
+ uint end_sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, end_sync_marker, 12);
1052
+ LZHAM_VERIFY(end_sync_marker == 366);
1053
+ #endif
1054
+ LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
1055
+ }
1056
+ else if (m_block_type == CLZDecompBase::cEOFBlock)
1057
+ {
1058
+ // Received EOF.
1059
+ m_status = LZHAM_DECOMP_STATUS_SUCCESS;
1060
+ }
1061
+ else
1062
+ {
1063
+ // This block type is currently undefined.
1064
+ m_status = LZHAM_DECOMP_STATUS_FAILED_BAD_CODE;
1065
+ }
1066
+
1067
+ m_block_index++;
1068
+
1069
+ } while (m_status == LZHAM_DECOMP_STATUS_NOT_FINISHED);
1070
+
1071
+ if ((!unbuffered) && (dst_ofs))
1072
+ {
1073
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
1074
+ LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dst_ofs);
1075
+ LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
1076
+ }
1077
+
1078
+ if (m_status == LZHAM_DECOMP_STATUS_SUCCESS)
1079
+ {
1080
+ LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
1081
+
1082
+ LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_file_src_file_adler32, 16);
1083
+ uint l; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, l, 16);
1084
+ m_file_src_file_adler32 = (m_file_src_file_adler32 << 16) | l;
1085
+
1086
+ if (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_COMPUTE_ADLER32)
1087
+ {
1088
+ if (unbuffered)
1089
+ {
1090
+ m_decomp_adler32 = adler32(pDst, dst_ofs, cInitAdler32);
1091
+ }
1092
+
1093
+ if (m_file_src_file_adler32 != m_decomp_adler32)
1094
+ {
1095
+ m_status = LZHAM_DECOMP_STATUS_FAILED_ADLER32;
1096
+ }
1097
+ }
1098
+ else
1099
+ {
1100
+ m_decomp_adler32 = m_file_src_file_adler32;
1101
+ }
1102
+ }
1103
+
1104
+ LZHAM_SYMBOL_CODEC_DECODE_END(codec);
1105
+
1106
+ *m_pIn_buf_size = static_cast<size_t>(codec.stop_decoding());
1107
+ *m_pOut_buf_size = unbuffered ? (dst_ofs - m_dst_highwater_ofs) : 0;
1108
+ m_dst_highwater_ofs = dst_ofs;
1109
+
1110
+ LZHAM_CR_RETURN(m_state, m_status);
1111
+
1112
+ for ( ; ; )
1113
+ {
1114
+ *m_pIn_buf_size = 0;
1115
+ *m_pOut_buf_size = 0;
1116
+ LZHAM_CR_RETURN(m_state, m_status);
1117
+ }
1118
+
1119
+ LZHAM_CR_FINISH
1120
+
1121
+ return m_status;
1122
+ }
1123
+
1124
+ static bool check_params(const lzham_decompress_params *pParams)
1125
+ {
1126
+ if ((!pParams) || (pParams->m_struct_size != sizeof(lzham_decompress_params)))
1127
+ return false;
1128
+
1129
+ if ((pParams->m_dict_size_log2 < CLZDecompBase::cMinDictSizeLog2) || (pParams->m_dict_size_log2 > CLZDecompBase::cMaxDictSizeLog2))
1130
+ return false;
1131
+
1132
+ if (pParams->m_num_seed_bytes)
1133
+ {
1134
+ if (((pParams->m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED) != 0) || (!pParams->m_pSeed_bytes))
1135
+ return false;
1136
+ if (pParams->m_num_seed_bytes > (1U << pParams->m_dict_size_log2))
1137
+ return false;
1138
+ }
1139
+ return true;
1140
+ }
1141
+
1142
+ lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_init(const lzham_decompress_params *pParams)
1143
+ {
1144
+ LZHAM_ASSUME(CLZDecompBase::cMinDictSizeLog2 == LZHAM_MIN_DICT_SIZE_LOG2);
1145
+ LZHAM_ASSUME(CLZDecompBase::cMaxDictSizeLog2 == LZHAM_MAX_DICT_SIZE_LOG2_X64);
1146
+
1147
+ if (!check_params(pParams))
1148
+ return NULL;
1149
+
1150
+ lzham_decompressor *pState = lzham_new<lzham_decompressor>();
1151
+ if (!pState)
1152
+ return NULL;
1153
+
1154
+ pState->m_params = *pParams;
1155
+
1156
+ if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
1157
+ {
1158
+ pState->m_pRaw_decomp_buf = NULL;
1159
+ pState->m_raw_decomp_buf_size = 0;
1160
+ pState->m_pDecomp_buf = NULL;
1161
+ }
1162
+ else
1163
+ {
1164
+ uint32 decomp_buf_size = 1U << pState->m_params.m_dict_size_log2;
1165
+ pState->m_pRaw_decomp_buf = static_cast<uint8*>(lzham_malloc(decomp_buf_size + 15));
1166
+ if (!pState->m_pRaw_decomp_buf)
1167
+ {
1168
+ lzham_delete(pState);
1169
+ return NULL;
1170
+ }
1171
+ pState->m_raw_decomp_buf_size = decomp_buf_size;
1172
+ pState->m_pDecomp_buf = math::align_up_pointer(pState->m_pRaw_decomp_buf, 16);
1173
+ }
1174
+
1175
+ pState->init();
1176
+
1177
+ return pState;
1178
+ }
1179
+
1180
+ lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_reinit(lzham_decompress_state_ptr p, const lzham_decompress_params *pParams)
1181
+ {
1182
+ if (!p)
1183
+ return lzham_lib_decompress_init(pParams);
1184
+
1185
+ lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
1186
+
1187
+ if (!check_params(pParams))
1188
+ return NULL;
1189
+
1190
+ if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
1191
+ {
1192
+ lzham_free(pState->m_pRaw_decomp_buf);
1193
+ pState->m_pRaw_decomp_buf = NULL;
1194
+ pState->m_raw_decomp_buf_size = 0;
1195
+ pState->m_pDecomp_buf = NULL;
1196
+ }
1197
+ else
1198
+ {
1199
+ uint32 new_dict_size = 1U << pState->m_params.m_dict_size_log2;
1200
+ if ((!pState->m_pRaw_decomp_buf) || (pState->m_raw_decomp_buf_size < new_dict_size))
1201
+ {
1202
+ uint8 *pNew_dict = static_cast<uint8*>(lzham_realloc(pState->m_pRaw_decomp_buf, new_dict_size + 15));
1203
+ if (!pNew_dict)
1204
+ return NULL;
1205
+ pState->m_pRaw_decomp_buf = pNew_dict;
1206
+ pState->m_raw_decomp_buf_size = new_dict_size;
1207
+ pState->m_pDecomp_buf = math::align_up_pointer(pState->m_pRaw_decomp_buf, 16);
1208
+ }
1209
+ }
1210
+
1211
+ pState->m_params = *pParams;
1212
+
1213
+ pState->init();
1214
+
1215
+ pState->reset_arith_tables();
1216
+ return pState;
1217
+ }
1218
+
1219
+ uint32 LZHAM_CDECL lzham_lib_decompress_deinit(lzham_decompress_state_ptr p)
1220
+ {
1221
+ lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
1222
+ if (!pState)
1223
+ return 0;
1224
+
1225
+ uint32 adler32 = pState->m_decomp_adler32;
1226
+
1227
+ lzham_free(pState->m_pRaw_decomp_buf);
1228
+ lzham_delete(pState);
1229
+
1230
+ return adler32;
1231
+ }
1232
+
1233
+ lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress(
1234
+ lzham_decompress_state_ptr p,
1235
+ const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
1236
+ lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
1237
+ lzham_bool no_more_input_bytes_flag)
1238
+ {
1239
+ lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
1240
+
1241
+ if ((!pState) || (!pState->m_params.m_dict_size_log2) || (!pIn_buf_size) || (!pOut_buf_size))
1242
+ {
1243
+ return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
1244
+ }
1245
+
1246
+ if ((*pIn_buf_size) && (!pIn_buf))
1247
+ {
1248
+ return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
1249
+ }
1250
+
1251
+ if ((*pOut_buf_size) && (!pOut_buf))
1252
+ {
1253
+ return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
1254
+ }
1255
+
1256
+ pState->m_pIn_buf = pIn_buf;
1257
+ pState->m_pIn_buf_size = pIn_buf_size;
1258
+ pState->m_pOut_buf = pOut_buf;
1259
+ pState->m_pOut_buf_size = pOut_buf_size;
1260
+ pState->m_no_more_input_bytes_flag = (no_more_input_bytes_flag != 0);
1261
+
1262
+ if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
1263
+ {
1264
+ if (!pState->m_pOrig_out_buf)
1265
+ {
1266
+ pState->m_pOrig_out_buf = pOut_buf;
1267
+ pState->m_orig_out_buf_size = *pOut_buf_size;
1268
+ }
1269
+ else
1270
+ {
1271
+ // In unbuffered mode, the caller is not allowed to move the output buffer and the output pointer MUST always point to the beginning of the output buffer.
1272
+ // Also, the output buffer size must indicate the full size of the output buffer. The decompressor will track the current output offset, and during partial/sync
1273
+ // flushes it'll report how many bytes it has written since the call.
1274
+ if ((pState->m_pOrig_out_buf != pOut_buf) || (pState->m_orig_out_buf_size != *pOut_buf_size))
1275
+ {
1276
+ return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
1277
+ }
1278
+ }
1279
+ }
1280
+
1281
+ lzham_decompress_status_t status;
1282
+
1283
+ if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
1284
+ status = pState->decompress<true>();
1285
+ else
1286
+ status = pState->decompress<false>();
1287
+
1288
+ return status;
1289
+ }
1290
+
1291
+ lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress_memory(const lzham_decompress_params *pParams, lzham_uint8* pDst_buf, size_t *pDst_len, const lzham_uint8* pSrc_buf, size_t src_len, lzham_uint32 *pAdler32)
1292
+ {
1293
+ if (!pParams)
1294
+ return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
1295
+
1296
+ lzham_decompress_params params(*pParams);
1297
+ params.m_decompress_flags |= LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED;
1298
+
1299
+ lzham_decompress_state_ptr pState = lzham_lib_decompress_init(&params);
1300
+ if (!pState)
1301
+ return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
1302
+
1303
+ lzham_decompress_status_t status = lzham_lib_decompress(pState, pSrc_buf, &src_len, pDst_buf, pDst_len, true);
1304
+
1305
+ uint32 adler32 = lzham_lib_decompress_deinit(pState);
1306
+ if (pAdler32)
1307
+ *pAdler32 = adler32;
1308
+
1309
+ return status;
1310
+ }
1311
+
1312
+ // ----------------- zlib-style API's
1313
+
1314
+ int LZHAM_CDECL lzham_lib_z_inflateInit(lzham_z_streamp pStream)
1315
+ {
1316
+ return lzham_lib_z_inflateInit2(pStream, LZHAM_Z_DEFAULT_WINDOW_BITS);
1317
+ }
1318
+
1319
+ int LZHAM_CDECL lzham_lib_z_inflateInit2(lzham_z_streamp pStream, int window_bits)
1320
+ {
1321
+ if (!pStream)
1322
+ return LZHAM_Z_STREAM_ERROR;
1323
+
1324
+ #ifdef LZHAM_Z_API_FORCE_WINDOW_BITS
1325
+ window_bits = LZHAM_Z_API_FORCE_WINDOW_BITS;
1326
+ #endif
1327
+
1328
+ int max_window_bits = LZHAM_64BIT_POINTERS ? LZHAM_MAX_DICT_SIZE_LOG2_X64 : LZHAM_MAX_DICT_SIZE_LOG2_X86;
1329
+ if (labs(window_bits) > max_window_bits)
1330
+ return LZHAM_Z_PARAM_ERROR;
1331
+
1332
+ if (labs(window_bits) < LZHAM_MIN_DICT_SIZE_LOG2)
1333
+ window_bits = (window_bits < 0) ? -LZHAM_MIN_DICT_SIZE_LOG2 : LZHAM_MIN_DICT_SIZE_LOG2;
1334
+
1335
+ lzham_decompress_params params;
1336
+ utils::zero_object(params);
1337
+ params.m_struct_size = sizeof(lzham_decompress_params);
1338
+ params.m_dict_size_log2 = static_cast<lzham_uint32>(labs(window_bits));
1339
+
1340
+ params.m_decompress_flags = LZHAM_DECOMP_FLAG_COMPUTE_ADLER32;
1341
+ if (window_bits > 0)
1342
+ params.m_decompress_flags |= LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM;
1343
+
1344
+ lzham_decompress_state_ptr pState = lzham_lib_decompress_init(&params);
1345
+ if (!pState)
1346
+ return LZHAM_Z_MEM_ERROR;
1347
+ pStream->state = static_cast<lzham_z_internal_state *>(pState);
1348
+
1349
+ pStream->data_type = 0;
1350
+ pStream->adler = LZHAM_Z_ADLER32_INIT;
1351
+ pStream->msg = NULL;
1352
+ pStream->total_in = 0;
1353
+ pStream->total_out = 0;
1354
+ pStream->reserved = 0;
1355
+
1356
+ return LZHAM_Z_OK;
1357
+ }
1358
+
1359
+ int LZHAM_CDECL lzham_lib_z_inflateReset(lzham_z_streamp pStream)
1360
+ {
1361
+ if ((!pStream) || (!pStream->state))
1362
+ return LZHAM_Z_STREAM_ERROR;
1363
+
1364
+ lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
1365
+ lzham_decompressor *pDecomp = static_cast<lzham_decompressor *>(pState);
1366
+
1367
+ lzham_decompress_params params(pDecomp->m_params);
1368
+
1369
+ if (!lzham_lib_decompress_reinit(pState, &params))
1370
+ return LZHAM_Z_STREAM_ERROR;
1371
+
1372
+ return LZHAM_Z_OK;
1373
+ }
1374
+
1375
+ int LZHAM_CDECL lzham_lib_z_inflate(lzham_z_streamp pStream, int flush)
1376
+ {
1377
+ if ((!pStream) || (!pStream->state))
1378
+ return LZHAM_Z_STREAM_ERROR;
1379
+
1380
+ if ((flush == LZHAM_Z_PARTIAL_FLUSH) || (flush == LZHAM_Z_FULL_FLUSH))
1381
+ flush = LZHAM_Z_SYNC_FLUSH;
1382
+ if (flush)
1383
+ {
1384
+ if ((flush != LZHAM_Z_SYNC_FLUSH) && (flush != LZHAM_Z_FINISH))
1385
+ return LZHAM_Z_STREAM_ERROR;
1386
+ }
1387
+
1388
+ size_t orig_avail_in = pStream->avail_in;
1389
+
1390
+ lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
1391
+ lzham_decompressor *pDecomp = static_cast<lzham_decompressor *>(pState);
1392
+ if (pDecomp->m_z_last_status >= LZHAM_DECOMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE)
1393
+ return LZHAM_Z_DATA_ERROR;
1394
+
1395
+ if (pDecomp->m_z_has_flushed && (flush != LZHAM_Z_FINISH))
1396
+ return LZHAM_Z_STREAM_ERROR;
1397
+ pDecomp->m_z_has_flushed |= (flush == LZHAM_Z_FINISH);
1398
+
1399
+ lzham_decompress_status_t status;
1400
+ for ( ; ; )
1401
+ {
1402
+ size_t in_bytes = pStream->avail_in;
1403
+ size_t out_bytes = pStream->avail_out;
1404
+ lzham_bool no_more_input_bytes_flag = (flush == LZHAM_Z_FINISH);
1405
+ status = lzham_lib_decompress(pState, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, no_more_input_bytes_flag);
1406
+
1407
+ pDecomp->m_z_last_status = status;
1408
+
1409
+ pStream->next_in += (uint)in_bytes;
1410
+ pStream->avail_in -= (uint)in_bytes;
1411
+ pStream->total_in += (uint)in_bytes;
1412
+ pStream->adler = pDecomp->m_decomp_adler32;
1413
+
1414
+ pStream->next_out += (uint)out_bytes;
1415
+ pStream->avail_out -= (uint)out_bytes;
1416
+ pStream->total_out += (uint)out_bytes;
1417
+
1418
+ if (status >= LZHAM_DECOMP_STATUS_FIRST_FAILURE_CODE)
1419
+ {
1420
+ if (status == LZHAM_DECOMP_STATUS_FAILED_NEED_SEED_BYTES)
1421
+ return LZHAM_Z_NEED_DICT;
1422
+ else
1423
+ return LZHAM_Z_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
1424
+ }
1425
+
1426
+ if ((status == LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
1427
+ return LZHAM_Z_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input, or by setting flush to LZHAM_Z_FINISH.
1428
+ else if (flush == LZHAM_Z_FINISH)
1429
+ {
1430
+ // Caller has indicated that all remaining input was at next_in, and all remaining output will fit entirely in next_out.
1431
+ // (The output buffer at next_out MUST be large to hold the remaining uncompressed data when flush==LZHAM_Z_FINISH).
1432
+ if (status == LZHAM_DECOMP_STATUS_SUCCESS)
1433
+ return LZHAM_Z_STREAM_END;
1434
+ // If status is LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT, there must be at least 1 more byte on the way but the caller to lzham_decompress() supplied an empty output buffer.
1435
+ // Something is wrong because the caller's output buffer should be large enough to hold the entire decompressed stream when flush==LZHAM_Z_FINISH.
1436
+ else if (status == LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT)
1437
+ return LZHAM_Z_BUF_ERROR;
1438
+ }
1439
+ else if ((status == LZHAM_DECOMP_STATUS_SUCCESS) || (!pStream->avail_in) || (!pStream->avail_out))
1440
+ break;
1441
+ }
1442
+
1443
+ return (status == LZHAM_DECOMP_STATUS_SUCCESS) ? LZHAM_Z_STREAM_END : LZHAM_Z_OK;
1444
+ }
1445
+
1446
+ int LZHAM_CDECL lzham_lib_z_inflateEnd(lzham_z_streamp pStream)
1447
+ {
1448
+ if (!pStream)
1449
+ return LZHAM_Z_STREAM_ERROR;
1450
+
1451
+ lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
1452
+ if (pState)
1453
+ {
1454
+ pStream->adler = lzham_lib_decompress_deinit(pState);
1455
+ pStream->state = NULL;
1456
+ }
1457
+
1458
+ return LZHAM_Z_OK;
1459
+ }
1460
+
1461
+ int LZHAM_CDECL lzham_lib_z_uncompress(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len)
1462
+ {
1463
+ lzham_z_stream stream;
1464
+ int status;
1465
+ memset(&stream, 0, sizeof(stream));
1466
+
1467
+ // In case lzham_z_ulong is 64-bits (argh I hate longs).
1468
+ if ((source_len | *pDest_len) > 0xFFFFFFFFU)
1469
+ return LZHAM_Z_PARAM_ERROR;
1470
+
1471
+ stream.next_in = pSource;
1472
+ stream.avail_in = (uint)source_len;
1473
+ stream.next_out = pDest;
1474
+ stream.avail_out = (uint)*pDest_len;
1475
+
1476
+ status = lzham_lib_z_inflateInit(&stream);
1477
+ if (status != LZHAM_Z_OK)
1478
+ return status;
1479
+
1480
+ status = lzham_lib_z_inflate(&stream, LZHAM_Z_FINISH);
1481
+ if (status != LZHAM_Z_STREAM_END)
1482
+ {
1483
+ lzham_lib_z_inflateEnd(&stream);
1484
+ return ((status == LZHAM_Z_BUF_ERROR) && (!stream.avail_in)) ? LZHAM_Z_DATA_ERROR : status;
1485
+ }
1486
+ *pDest_len = stream.total_out;
1487
+
1488
+ return lzham_lib_z_inflateEnd(&stream);
1489
+ }
1490
+
1491
+ const char * LZHAM_CDECL lzham_lib_z_error(int err)
1492
+ {
1493
+ static struct
1494
+ {
1495
+ int m_err;
1496
+ const char *m_pDesc;
1497
+ }
1498
+ s_error_descs[] =
1499
+ {
1500
+ { LZHAM_Z_OK, "" },
1501
+ { LZHAM_Z_STREAM_END, "stream end" },
1502
+ { LZHAM_Z_NEED_DICT, "need dictionary" },
1503
+ { LZHAM_Z_ERRNO, "file error" },
1504
+ { LZHAM_Z_STREAM_ERROR, "stream error" },
1505
+ { LZHAM_Z_DATA_ERROR, "data error" },
1506
+ { LZHAM_Z_MEM_ERROR, "out of memory" },
1507
+ { LZHAM_Z_BUF_ERROR, "buf error" },
1508
+ { LZHAM_Z_VERSION_ERROR, "version error" },
1509
+ { LZHAM_Z_PARAM_ERROR, "parameter error" }
1510
+ };
1511
+ for (uint i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
1512
+ if (s_error_descs[i].m_err == err)
1513
+ return s_error_descs[i].m_pDesc;
1514
+ return NULL;
1515
+ }
1516
+
1517
+ lzham_z_ulong lzham_lib_z_adler32(lzham_z_ulong adler, const unsigned char *ptr, size_t buf_len)
1518
+ {
1519
+ return adler32(ptr, buf_len, static_cast<uint>(adler));
1520
+ }
1521
+
1522
+ lzham_z_ulong LZHAM_CDECL lzham_lib_z_crc32(lzham_z_ulong crc, const lzham_uint8 *ptr, size_t buf_len)
1523
+ {
1524
+ return crc32(static_cast<uint>(crc), ptr, buf_len);
1525
+ }
1526
+
1527
+ } // namespace lzham