Skip to content

Instantly share code, notes, and snippets.

@robert-nix
Created March 2, 2015 15:56
Show Gist options
  • Select an option

  • Save robert-nix/c045e192c9123f71220e to your computer and use it in GitHub Desktop.

Select an option

Save robert-nix/c045e192c9123f71220e to your computer and use it in GitHub Desktop.
lzo decompressor (lzo1x) with the crap stripped out ("crap" includes sanity checks, so this will crash on invalid bitstream)
#ifndef assert
#define assert(x) ((void)0);
#endif
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
static int lzo1x_decompress(u8 *in, u32 in_len, u8 *out, u32 *out_len) {
u8 *op;
u8 *ip;
u32 t;
u8 *m_pos;
u8 *ip_end = in + in_len;
u8 *op_end = out + *out_len;
*out_len = 0;
op = out;
ip = in;
if (*ip > 17) {
t = *ip++ - 17;
if (t < 4)
goto match_next;
assert(t > 0);
do
*op++ = *ip++;
while (--t > 0);
goto first_literal_run;
}
while (ip < ip_end && op < op_end) {
t = *ip++;
if (t >= 16)
goto match;
/* a literal run */
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 15 + *ip++;
}
/* copy literals */
assert(t > 0);
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
do
*op++ = *ip++;
while (--t > 0);
first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + 0x0800);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
/* handle matches */
do {
match:
if (t >= 64) /* a M2 match */
{
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
assert(t > 0);
goto copy_match;
} else if (t >= 32) /* a M3 match */
{
t &= 31;
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
} else if (t >= 16) /* a M4 match */
{
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 7 + *ip++;
}
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
} else /* a M1 match */
{
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}
/* copy match */
assert(t > 0);
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do
*op++ = *m_pos++;
while (--t > 0);
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
/* copy literals */
match_next:
assert(t > 0);
assert(t < 4);
*op++ = *ip++;
if (t > 1) {
*op++ = *ip++;
if (t > 2) {
*op++ = *ip++;
}
}
t = *ip++;
} while (ip < ip_end && op < op_end);
}
/* no EOF code was found */
*out_len = (u32)(op - out);
return LZO_E_EOF_NOT_FOUND;
eof_found:
assert(t == 1);
*out_len = (u32)(op - out);
return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED
: LZO_E_INPUT_OVERRUN));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment