@@ -161,3 +161,136 @@ void lzss_decode(void)
161
161
}
162
162
}
163
163
}
164
+
165
+
166
+ /* *************************************************************************************
167
+ LZSS DECODER CLASS IMPLEMENTATION
168
+ **************************************************************************************/
169
+
170
+ // get the number of bits the algorithm will try to get given the state
171
+ int LZSSDecoder::bits_required (LZSSDecoder::FSM_STATES s) {
172
+ switch (s) {
173
+ case FSM_0:
174
+ return 1 ;
175
+ case FSM_1:
176
+ return 8 ;
177
+ case FSM_2:
178
+ return EI;
179
+ case FSM_3:
180
+ return EJ;
181
+ }
182
+ }
183
+
184
+ LZSSDecoder::LZSSDecoder (std::function<void (const uint8_t )> putc_cbk)
185
+ : put_char_cbk(putc_cbk), state(FSM_0), available_bits(0 ) {
186
+ for (int i = 0 ; i < N - F; i++) buffer[i] = ' ' ;
187
+ r = N - F;
188
+ }
189
+
190
+ LZSSDecoder::status LZSSDecoder::handle_state () {
191
+ LZSSDecoder::status res = IN_PROGRESS;
192
+
193
+ int c = getbit (bits_required (this ->state ));
194
+
195
+ if (c == LZSS_BUFFER_EMPTY) {
196
+ res = NOT_COMPLETED;
197
+ } else if (c == LZSS_EOF) {
198
+ res = DONE;
199
+ this ->state = FSM_EOF;
200
+ } else {
201
+ switch (this ->state ) {
202
+ case FSM_0:
203
+ if (c) {
204
+ this ->state = FSM_1;
205
+ } else {
206
+ this ->state = FSM_2;
207
+ }
208
+ break ;
209
+ case FSM_1:
210
+ putc (c);
211
+ buffer[r++] = c;
212
+ r &= (N - 1 ); // equivalent to r = r % N
213
+
214
+ this ->state = FSM_0;
215
+ break ;
216
+ case FSM_2:
217
+ this ->i = c;
218
+ this ->state = FSM_3;
219
+ break ;
220
+ case FSM_3: {
221
+ int j = c;
222
+ for (int k = 0 ; k <= j + 1 ; k++) { // TODO improve by using memcpy
223
+ c = buffer[(this ->i + k) & (N - 1 )]; // equivalent to buffer[(i+k) % N]
224
+ putc (c);
225
+ buffer[r++] = c; r &= (N - 1 ); // equivalent to r = r % N
226
+ }
227
+ this ->state = FSM_0;
228
+
229
+ break ;
230
+ }
231
+ }
232
+ }
233
+
234
+ return res;
235
+ }
236
+
237
+ LZSSDecoder::status LZSSDecoder::decompress (const char * buffer, uint32_t size) {
238
+ this ->in_buffer = (uint8_t *)buffer;
239
+
240
+ // I won't ever exceed the (2^32)-1 value, since It is impossible to have a buffer of 512MB on an embedded dev
241
+ // thus this value fits a 32 bit uint
242
+ this ->available_bits += size*8 ;
243
+ status res = IN_PROGRESS;
244
+
245
+ while ((res = handle_state ()) == IN_PROGRESS);
246
+
247
+ if (res == NOT_COMPLETED && this ->available_bits > 0 ) {
248
+ this ->save_excess ();
249
+ }
250
+
251
+ return res;
252
+ }
253
+
254
+ int LZSSDecoder::getbit (int n) { // get n bits from buffer
255
+
256
+ // check that we have all the available bits required
257
+ if (in_buffer == nullptr || n > (available_bits+excess_len)) {
258
+ return LZSS_BUFFER_EMPTY;
259
+ }
260
+
261
+ // get the required bits
262
+ static int buf, mask=0 ;
263
+ int i, x=0 ;
264
+
265
+ // TODO this function couls be improved by extracting bits>1 with a single mask
266
+ for (i = 0 ; i < n; i++) {
267
+ if (mask == 0 ) {
268
+ if ((buf = getc ()) == LZSS_EOF) return LZSS_EOF;// no need to decrement available_bits
269
+ mask = 128 ;
270
+ }
271
+ x <<= 1 ;
272
+ if (buf & mask) x++;
273
+ mask >>= 1 ;
274
+ }
275
+ available_bits -= n;
276
+ return x;
277
+ }
278
+
279
+ int LZSSDecoder::getc () {
280
+ int c;
281
+ if (excess_len > 0 ) {
282
+ c = excess_bits;
283
+ excess_len -= 8 ;
284
+ } else {
285
+ c = *in_buffer;
286
+ in_buffer++;
287
+ }
288
+ return c;
289
+ }
290
+
291
+ void LZSSDecoder::save_excess () { // TODO Explain that
292
+ if (this ->available_bits >= 8 ) {
293
+ this ->excess_bits = *this ->in_buffer ;
294
+ this ->excess_len = 8 ;
295
+ }
296
+ }
0 commit comments