Compressed LZO File Format

From Bohemia Interactive Community
Revision as of 10:12, 9 May 2010 by Mikero (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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


 }


Related Page(s)

Model File Formats