Compressed LZO File Format: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
mNo edit summary
m (Some wiki formatting)
Line 1: Line 1:
{{unsupported-doc}}
{{unsupported-doc}}
===LZO===
This is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/
This is LZO as defined by oberhumer


http://www.oberhumer.com/opensource/lzo/
there are 3 sources to the LZO code:


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)


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


<pre><nowiki>
== Source Code ==


<syntaxhighlight lang="cpp">
// some of the includes are for compression only (not listed here)
// some of the includes are for compression only (not listed here)


int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen)
int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)


// returns length of consumed input bytes ,or, negative status
// 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
// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled


// example call
// example call


byte Array=(byte)malloc(Outlen); // no zero clearing is necessary
byte Array = (byte)malloc(Outlen); // no zero clearing is necessary
int status_or_len=lzo->lzo1x_decompress_safe (input, Array,OutLen);#include "minilzo.h"  
int status_or_len = lzo->lzo1x_decompress_safe (input, Array, OutLen);#include "minilzo.h"


#include <limits.h>
#include <limits.h>
Line 32: Line 31:
#include <malloc.h>
#include <malloc.h>


#define assert(val) if (!(val)) return LZO_E_ERROR
#define assert(val) if (!(val)) return LZO_E_ERROR
#define M2_MAX_OFFSET   0x0800
#define M2_MAX_OFFSET 0x0800


#define NEED_OP(x) if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;
#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 TEST_LB() if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;


#define COPY4(dst,src)   * (unsigned *)(dst) = * (const unsigned *)(src)
#define COPY4(dst, src) * (unsigned *)(dst) = * (const unsigned *)(src)


int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen)
int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)
{
{
register byte* op;
register byte* op;
register const byte* ip;
register const byte* ip;
register size_t t;
register size_t t;
register const byte* m_pos;
register const byte* m_pos;


byte* const op_end = out + OutLen;
byte* const op_end = out + OutLen;


    OutLen = 0;
OutLen = 0;
    op = out;
op = out;
    ip = in;
ip = in;


    if (*ip > 17)
if (*ip > 17)
    {
{
        t = *ip++ - 17;
t = *ip++ - 17;
        if (t < 4) goto match_next;
if (t < 4) goto match_next;
        assert(t > 0);// return LZO_E_ERROR;
assert(t > 0);// return LZO_E_ERROR;
        NEED_OP(t);  
NEED_OP(t);
        do *op++ = *ip++; while (--t > 0);
do *op++ = *ip++; while (--t > 0);
        goto first_literal_run;
goto first_literal_run;
    }
}


    while (1 )
while (1)
    {
{
        t = *ip++;
t = *ip++;
        if (t >= 16)           goto match;
if (t >= 16) goto match;
        if (t == 0)
if (t == 0)
        {
{
            while (*ip == 0)
while (*ip == 0)
            {
{
                t += 255;
t += 255;
                ip++;
ip++;
            }
}
            t += 15 + *ip++;
t += 15 + *ip++;
        }
}
        assert(t > 0); NEED_OP(t+3);  
assert(t > 0); NEED_OP(t+3);


        COPY4(op,ip);
COPY4(op, ip);
        op += 4; ip += 4;
op += 4; ip += 4;
        if (--t > 0)
if (--t > 0)
        {
{
            if (t >= 4)
if (t >= 4)
            {
{
                do {
do {
                    COPY4(op,ip);
COPY4(op, ip);
                    op += 4; ip += 4; t -= 4;
op += 4; ip += 4; t -= 4;
                } while (t >= 4);
} while (t >= 4);
                if (t > 0) do *op++ = *ip++; while (--t > 0);
if (t > 0) do *op++ = *ip++; while (--t > 0);
            }
}
            else
else
                do *op++ = *ip++; while (--t > 0);
do *op++ = *ip++; while (--t > 0);
        }
}


first_literal_run:
first_literal_run:


        t = *ip++;
t = *ip++;
        if (t >= 16) goto match;
if (t >= 16) goto match;


        m_pos = op - (1 + M2_MAX_OFFSET);
m_pos = op - (1 + M2_MAX_OFFSET);
        m_pos -= t >> 2;
m_pos -= t >> 2;
        m_pos -= *ip++ << 2;
m_pos -= *ip++ << 2;


        TEST_LB();  
TEST_LB();
        NEED_OP(3);
NEED_OP(3);
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;


        goto match_done;
goto match_done;


        do {
do {
match:
match:
            if (t >= 64)
if (t >= 64)
            {
{


                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= (t >> 2) & 7;
m_pos -= (t >> 2) & 7;
                m_pos -= *ip++ << 3;
m_pos -= *ip++ << 3;
                t = (t >> 5) - 1;
t = (t >> 5) - 1;
                TEST_LB();     assert(t > 0); NEED_OP(t+3-1);
TEST_LB(); assert(t > 0); NEED_OP(t+3-1);
                goto copy_match;
goto copy_match;
            }
}
            else if (t >= 32)
else if (t >= 32)
            {
{
                t &= 31;
t &= 31;
                if (t == 0)
if (t == 0)
                {
{
                    while (*ip == 0)
while (*ip == 0)
                    {
{
                        t += 255;
t += 255;
                        ip++;
ip++;
                    }
}
                    t += 31 + *ip++;
t += 31 + *ip++;
                }
}


                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
m_pos -= (ip[0] >> 2) + (ip[1] << 6);


                ip += 2;
ip += 2;
            }
}
            else if (t >= 16)
else if (t >= 16)
            {
{


                m_pos = op;
m_pos = op;
                m_pos -= (t & 8) << 11;
m_pos -= (t & 8) << 11;


                t &= 7;
t &= 7;
                if (t == 0)
if (t == 0)
                {
{
                    while (*ip == 0)
while (*ip == 0)
                    {
{
                        t += 255;
t += 255;
                        ip++;
ip++;
                    }
}
                    t += 7 + *ip++;
t += 7 + *ip++;
                }
}


                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
m_pos -= (ip[0] >> 2) + (ip[1] << 6);


                ip += 2;
ip += 2;
                ////// done
////// done
                if (m_pos == op)
if (m_pos == op)
                {
{
                    assert(t==1);
assert(t == 1);
                    if (m_pos!=op_end)  
if (m_pos != op_end)
                        return LZO_E_LOOKBEHIND_UNDERRUN;
return LZO_E_LOOKBEHIND_UNDERRUN;
                    return ip-in;
return ip-in;
                }
}
                m_pos -= 0x4000;
m_pos -= 0x4000;
            }
}
            else
else
            {
{
                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= t >> 2;
m_pos -= t >> 2;
                m_pos -= *ip++ << 2;
m_pos -= *ip++ << 2;


                TEST_LB();  
TEST_LB();
                NEED_OP(2);
NEED_OP(2);
                *op++ = *m_pos++; *op++ = *m_pos;
*op++ = *m_pos++; *op++ = *m_pos;
                goto match_done;
goto match_done;
            }
}


            TEST_LB();  
TEST_LB();
            assert(t > 0);
assert(t > 0);
            NEED_OP(t+3-1);
NEED_OP(t+3-1);


            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
            {
{
                COPY4(op,m_pos);
COPY4(op, m_pos);
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
                do {
do {
                    COPY4(op,m_pos);
COPY4(op, m_pos);
                    op += 4; m_pos += 4; t -= 4;
op += 4; m_pos += 4; t -= 4;
                } while (t >= 4);
} while (t >= 4);
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
            }
}
            else
else
            {
{
copy_match:
copy_match:
              *op++ = *m_pos++; *op++ = *m_pos++;
*op++ = *m_pos++; *op++ = *m_pos++;


                do *op++ = *m_pos++; while (--t > 0);
do *op++ = *m_pos++; while (--t > 0);
}


            }
match_done:
match_done:
t = ip[-2] & 3;
if (t == 0) break;


            t = ip[-2] & 3;
            if (t == 0)  break;
match_next:
match_next:
            assert(t > 0); assert(t < 4); NEED_OP(t);  
assert(t > 0); assert(t < 4); NEED_OP(t);
            *op++ = *ip++;
*op++ = *ip++;
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }


            t = *ip++;
t = *ip++;
        } while (1 );
} while (1);
    }
}
//    return LZO_E_EOF_NOT_FOUND;/never gets here


// return LZO_E_EOF_NOT_FOUND; // never gets here
}
</syntaxhighlight>


}


== See Also ==


</nowiki></pre>
* [[BIS File Formats#3D Model File Formats|Model File Formats]]


=Related Page(s)=


[[BIS_File_Formats#3D_Model_File_Formats|Model File Formats]]
[[Category:BIS File Formats]]
[[Category:BIS_File_Formats]]
[[Category:ArmA: File Formats]]
[[Category:ArmA: File Formats]]

Revision as of 12:29, 1 June 2020

Template:unsupported-doc This is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/

there are 3 sources to the LZO code:


Source Code

// 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
}


See Also