Skip to content

Commit e6494de

Browse files
improving getbits implementation
This new implementation allowed us to remove the excess management thus simplifing the algorithm and allowed us to simplify the implementation of get_char_cbk. This also improved performances
1 parent 4cb650a commit e6494de

File tree

2 files changed

+36
-47
lines changed

2 files changed

+36
-47
lines changed

src/decompress/lzss.cpp

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ LZSSDecoder::LZSSDecoder(std::function<int()> getc_cbk, std::function<void(const
189189

190190

191191
LZSSDecoder::LZSSDecoder(std::function<void(const uint8_t)> putc_cbk)
192-
: put_char_cbk(putc_cbk), state(FSM_0), available_bits(0) {
192+
: put_char_cbk(putc_cbk), state(FSM_0), available(0) {
193193
for (int i = 0; i < N - F; i++) buffer[i] = ' ';
194194
r = N - F;
195195
}
@@ -242,62 +242,57 @@ LZSSDecoder::status LZSSDecoder::handle_state() {
242242
}
243243

244244
LZSSDecoder::status LZSSDecoder::decompress(const char* buffer, uint32_t size) {
245-
this->in_buffer = (uint8_t*)buffer;
245+
if(!get_char_cbk) {
246+
this->in_buffer = (uint8_t*)buffer;
247+
this->available += size;
248+
}
246249

247-
// I won't ever exceed the (2^32)-1 value, since It is impossible to have a buffer of 512MB on an embedded dev
248-
// thus this value fits a 32 bit uint
249-
this->available_bits += size*8;
250250
status res = IN_PROGRESS;
251251

252252
while((res = handle_state()) == IN_PROGRESS);
253253

254-
if(res == NOT_COMPLETED && this->available_bits > 0) {
255-
this->save_excess();
256-
}
257-
258254
return res;
259255
}
260256

261257
int LZSSDecoder::getbit(int n) { // get n bits from buffer
258+
static uint32_t buf, buf_size=0;
259+
int x=0, c;
260+
261+
// if the local bit buffer doesn't have enough bit get them
262+
while(buf_size < n) {
263+
switch(c=getc()) {
264+
case LZSS_EOF:
265+
case LZSS_BUFFER_EMPTY:
266+
return c;
267+
}
268+
buf <<= 8;
262269

263-
// check that we have all the available bits required
264-
if(in_buffer == nullptr || n > (available_bits+excess_len)) {
265-
return LZSS_BUFFER_EMPTY;
270+
buf |= (uint8_t)c;
271+
buf_size += sizeof(uint8_t)*8;
266272
}
267273

268-
// get the required bits
269-
static int buf, mask=0;
270-
int i, x=0;
274+
// the result is the content of the buffer starting from msb to n successive bits
275+
x = buf >> (buf_size-n);
276+
277+
// remove from the buffer the read bits with a mask
278+
buf &= (1<<(buf_size-n))-1;
279+
280+
buf_size-=n;
271281

272-
// TODO this function couls be improved by extracting bits>1 with a single mask
273-
for (i = 0; i < n; i++) {
274-
if (mask == 0) {
275-
if ((buf = getc()) == LZSS_EOF) return LZSS_EOF;// no need to decrement available_bits
276-
mask = 128;
277-
}
278-
x <<= 1;
279-
if (buf & mask) x++;
280-
mask >>= 1;
281-
}
282-
available_bits -= n;
283282
return x;
284283
}
285284

286285
int LZSSDecoder::getc() {
287286
int c;
288-
if(excess_len > 0) {
289-
c = excess_bits;
290-
excess_len -= 8;
287+
288+
if(get_char_cbk) {
289+
c = get_char_cbk();
290+
} else if(in_buffer == nullptr || available == 0) {
291+
c = LZSS_BUFFER_EMPTY;
291292
} else {
292293
c = *in_buffer;
293294
in_buffer++;
295+
available--;
294296
}
295297
return c;
296298
}
297-
298-
void LZSSDecoder::save_excess() { // TODO Explain that
299-
if(this->available_bits >= 8) {
300-
this->excess_bits = *this->in_buffer;
301-
this->excess_len = 8;
302-
}
303-
}

src/decompress/lzss.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,30 +56,24 @@ class LZSSDecoder {
5656
* decode the provided buffer until buffer ends, then pause the process
5757
* @return DONE if the decompression is completed, NOT_COMPLETED if not
5858
*/
59-
status decompress(const char* buffer, uint32_t size);
59+
status decompress(const char* buffer=nullptr, uint32_t size=0);
60+
61+
static const int LZSS_EOF = -1;
62+
static const int LZSS_BUFFER_EMPTY = -2;
6063
private:
6164
// TODO provide a way for the user to set these parameters
6265
static const int EI = 11; /* typically 10..13 */
6366
static const int EJ = 4; /* typically 4..5 */
6467
static const int N = (1 << EI); /* buffer size */
6568
static const int F = ((1 << EJ) + 1); /* lookahead buffer size */
6669

67-
static const int LZSS_EOF = -1;
68-
static const int LZSS_BUFFER_EMPTY = -2;
69-
7070
// alogirthm specific buffer used to store text that could be later referenced and copied
7171
uint8_t buffer[N * 2];
7272

73-
// it may happen that the buffer provided is not enough and there could be an
74-
// excess byte that cannot be handled by the current FSM cycle, we save it in excess_bits
75-
void save_excess();
76-
uint8_t excess_bits=0;
77-
uint8_t excess_len=0; // expressed in number of bits
78-
7973
// this function gets 1 single char from the input buffer
8074
int getc();
8175
uint8_t* in_buffer = nullptr;
82-
uint32_t available_bits = 0;
76+
uint32_t available = 0;
8377

8478
status handle_state();
8579

0 commit comments

Comments
 (0)