Compressed LZO File Format
Jump to navigation
Jump to search
LZO
This is LZO as defined by oberhumer
http://www.oberhumer.com/opensource/lzo/
there are 3 sources to the lzo code
minilzo (on above site) lzo version 2 (ditto) lzo version 1 http://sourceforge.net/project/showfiles.php?group_id=102072&package_id=110218&release_id=221836
// some of the includes are for compression only (not listed here) int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen) // returns length of consumed input bytes ,or, negative status // Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled // example call byte Array=(byte)malloc(Outlen); // no zero clearing is necessary int status_or_len=lzo->lzo1x_decompress_safe (input, Array,OutLen);#include "minilzo.h" #include <limits.h> #include <stddef.h> #include <limits.h> #include <stddef.h> #include <string.h> #include <malloc.h> #define assert(val) if (!(val)) return LZO_E_ERROR #define M2_MAX_OFFSET 0x0800 #define NEED_OP(x) if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN; #define TEST_LB() if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN; #define COPY4(dst,src) * (unsigned *)(dst) = * (const unsigned *)(src) int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen) { register byte* op; register const byte* ip; register size_t t; register const byte* m_pos; byte* const op_end = out + OutLen; OutLen = 0; op = out; ip = in; if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0);// return LZO_E_ERROR; NEED_OP(t); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } while (1 ) { t = *ip++; if (t >= 16) goto match; if (t == 0) { while (*ip == 0) { t += 255; ip++; } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } first_literal_run: t = *ip++; if (t >= 16) goto match; m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; TEST_LB(); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; goto match_done; do { match: if (t >= 64) { m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; TEST_LB(); assert(t > 0); NEED_OP(t+3-1); goto copy_match; } else if (t >= 32) { 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) { 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; ////// done if (m_pos == op) { assert(t==1); if (m_pos!=op_end) return LZO_E_LOOKBEHIND_UNDERRUN; return ip-in; } m_pos -= 0x4000; } else { m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; TEST_LB(); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; goto match_done; } TEST_LB(); assert(t > 0); NEED_OP(t+3-1); if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else { 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; match_next: assert(t > 0); assert(t < 4); NEED_OP(t); *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } t = *ip++; } while (1 ); } // return LZO_E_EOF_NOT_FOUND;/never gets here }