extlzham 0.0.1.PROTOTYPE3-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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