Compressed LZO File Format

From Bohemia Interactive Community
Revision as of 11:14, 9 May 2010 by Mikero (talk | contribs)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Template:unsupported-doc

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