Beispiel #1
0
static
#if LZO_ARCH_AVR
__lzo_noinline
#endif
lzo_bytep
store_run(lzo_bytep op, const lzo_bytep ii, lzo_uint r_len)
{
    assert(r_len > 0);

    /* code a long R0 run */
    if (r_len >= 512)
    {
        unsigned r_bits = 7;        /* 256 << 7 == 32768 */
        do {
            while (r_len >= (256u << r_bits))
            {
                r_len -= (256u << r_bits);
                *op++ = 0; *op++ = LZO_BYTE((R0FAST - R0MIN) + r_bits);
                MEMCPY8_DS(op, ii, (256u << r_bits));
            }
        } while (--r_bits > 0);
    }
    while (r_len >= R0FAST)
    {
        r_len -= R0FAST;
        *op++ = 0; *op++ = R0FAST - R0MIN;
        MEMCPY8_DS(op, ii, R0FAST);
    }

    if (r_len >= R0MIN)
    {
        /* code a short R0 run */
        *op++ = 0; *op++ = LZO_BYTE(r_len - R0MIN);
        MEMCPY_DS(op, ii, r_len);
    }
    else if (r_len > 0)
    {
        /* code a 'normal' run */
        *op++ = LZO_BYTE(r_len);
        MEMCPY_DS(op, ii, r_len);
    }

    assert(r_len == 0);
    return op;
}
Beispiel #2
0
lzo1a_decompress ( const lzo_byte *in , lzo_uint  in_len,
                         lzo_byte *out, lzo_uint *out_len,
                         lzo_voidp wrkmem )
{
#if defined(LZO_OPTIMIZE_GNUC_i386)
	register lzo_byte *op __asm__("%edi");
	register const lzo_byte *ip __asm__("%esi");
	register lzo_uint t __asm__("%ecx");
	register const lzo_byte *m_pos __asm__("%ebx");
#else
	register lzo_byte *op;
	register const lzo_byte *ip;
	register lzo_uint t;
	register const lzo_byte *m_pos;
#endif
	const lzo_byte * const ip_end = in + in_len;

	LZO_UNUSED(wrkmem);

#if defined(__LZO_QUERY_DECOMPRESS)
	if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
		return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0);
#endif

	op = out;
	ip = in;
	while (ip < ip_end)
	{
		t = *ip++;		/* get marker */
		LZO_STATS(lzo_stats->marker[t]++);

		if (t == 0)				/* a R0 literal run */
		{
			t = *ip++;
			if (t >= R0FAST - R0MIN)			/* a long R0 run */
			{
				t -= R0FAST - R0MIN;
				if (t == 0)
					t = R0FAST;
				else
				{
#if 0
					t = 256u << ((unsigned) t);
#else
					/* help the optimizer */
					lzo_uint tt = 256;
					do tt <<= 1; while (--t > 0);
					t = tt;
#endif
				}
				MEMCPY8_DS(op,ip,t);
				continue;
			}
			t += R0MIN;
			goto literal;
		}
		else if (t < R0MIN)		/* a short literal run */
		{
literal:
			MEMCPY_DS(op,ip,t);

		/* after a literal a match must follow */
			while (ip < ip_end)
			{
				t = *ip++;			/* get R1 marker */
				if (t >= R0MIN)
					goto match;

			/* R1 match - a context sensitive 3 byte match + 1 byte literal */
				assert((t & OMASK) == t);
				m_pos = op - MIN_OFFSET;
				m_pos -= t | (((lzo_uint) *ip++) << OBITS);
				assert(m_pos >= out); assert(m_pos < op);
				*op++ = *m_pos++;
				*op++ = *m_pos++;
				*op++ = *m_pos++;
				*op++ = *ip++;
			}
		}
		else					/* a match */
		{
match:
			/* get match offset */
			m_pos = op - MIN_OFFSET;
			m_pos -= (t & OMASK) | (((lzo_uint) *ip++) << OBITS);
			assert(m_pos >= out); assert(m_pos < op);

			/* get match len */
			if (t < ((MSIZE - 1) << OBITS))			/* a short match */
			{
				t >>= OBITS;
				*op++ = *m_pos++;
				*op++ = *m_pos++;
				MEMMOVE_DS(op,m_pos,t);
			}
			else									 /* a long match */
			{
#if (LBITS < 8)
				t = (MIN_MATCH_LONG - THRESHOLD) + ((lzo_uint)(*ip++) & LMASK);
#else
				t = (MIN_MATCH_LONG - THRESHOLD) + (lzo_uint)(*ip++);
#endif
				*op++ = *m_pos++;
				*op++ = *m_pos++;
				MEMMOVE_DS(op,m_pos,t);
#if (LBITS < 8)
				/* a very short literal following a long match */
				t = ip[-1] >> LBITS;
				if (t) do
					*op++ = *ip++;
				while (--t);
#endif
			}
		}
Beispiel #3
0
lzo1a_decompress ( const lzo_bytep in , lzo_uint  in_len,
                         lzo_bytep out, lzo_uintp out_len,
                         lzo_voidp wrkmem )
{
    register lzo_bytep op;
    register const lzo_bytep ip;
    register lzo_uint t;
    register const lzo_bytep m_pos;
    const lzo_bytep const ip_end = in + in_len;

    LZO_UNUSED(wrkmem);

    op = out;
    ip = in;
    while (ip < ip_end)
    {
        t = *ip++;      /* get marker */
        LZO_STATS(lzo_stats->marker[t]++);

        if (t == 0)             /* a R0 literal run */
        {
            t = *ip++;
            if (t >= R0FAST - R0MIN)            /* a long R0 run */
            {
                t -= R0FAST - R0MIN;
                if (t == 0)
                    t = R0FAST;
                else
                {
#if 0
                    t = 256u << ((unsigned) t);
#else
                    /* help the optimizer */
                    lzo_uint tt = 256;
                    do tt <<= 1; while (--t > 0);
                    t = tt;
#endif
                }
                MEMCPY8_DS(op,ip,t);
                continue;
            }
            t += R0MIN;
            goto literal;
        }
        else if (t < R0MIN)     /* a short literal run */
        {
literal:
            MEMCPY_DS(op,ip,t);

        /* after a literal a match must follow */
            while (ip < ip_end)
            {
                t = *ip++;          /* get R1 marker */
                if (t >= R0MIN)
                    goto match;

            /* R1 match - a context sensitive 3 byte match + 1 byte literal */
                assert((t & OMASK) == t);
                m_pos = op - MIN_OFFSET;
                m_pos -= t | (((lzo_uint) *ip++) << OBITS);
                assert(m_pos >= out); assert(m_pos < op);
                *op++ = m_pos[0];
                *op++ = m_pos[1];
                *op++ = m_pos[2];
                *op++ = *ip++;
            }
        }
        else                    /* a match */
        {
match:
            /* get match offset */
            m_pos = op - MIN_OFFSET;
            m_pos -= (t & OMASK) | (((lzo_uint) *ip++) << OBITS);
            assert(m_pos >= out); assert(m_pos < op);

            /* get match len */
            if (t < ((MSIZE - 1) << OBITS))         /* a short match */
            {
                t >>= OBITS;
                *op++ = *m_pos++;
                *op++ = *m_pos++;
                MEMCPY_DS(op,m_pos,t);
            }
            else                                     /* a long match */
            {
#if (LBITS < 8)
                t = (MIN_MATCH_LONG - THRESHOLD) + ((lzo_uint)(*ip++) & LMASK);
#else
                t = (MIN_MATCH_LONG - THRESHOLD) + (lzo_uint)(*ip++);
#endif
                *op++ = *m_pos++;
                *op++ = *m_pos++;
                MEMCPY_DS(op,m_pos,t);
#if (LBITS < 8)
                /* a very short literal following a long match */
                t = ip[-1] >> LBITS;
                if (t) do
                    *op++ = *ip++;
                while (--t);
#endif
            }
        }
Beispiel #4
0
static int
do_compress    ( const lzo_bytep in , lzo_uint  in_len,
                       lzo_bytep out, lzo_uintp out_len,
                       lzo_voidp wrkmem )
{
    const lzo_bytep ip;
#if defined(__LZO_HASH_INCREMENTAL)
    lzo_xint dv;
#endif
    lzo_bytep op;
    const lzo_bytep m_pos;
    const lzo_bytep const ip_end = in+in_len - DVAL_LEN - MIN_MATCH_LONG;
    const lzo_bytep const in_end = in+in_len - DVAL_LEN;
    const lzo_bytep ii;
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;

#if !defined(NDEBUG)
    const lzo_bytep m_pos_sav;
#endif

    op = out;
    ip = in;
    ii = ip;                /* point to start of literal run */
    if (in_len <= MIN_MATCH_LONG + DVAL_LEN + 1)
        goto the_end;

    /* init dictionary */
#if (LZO_DETERMINISTIC)
    BZERO8_PTR(wrkmem,sizeof(lzo_dict_t),D_SIZE);
#endif

    DVAL_FIRST(dv,ip);
    UPDATE_D(dict,0,dv,ip,in);
    ip++;
    DVAL_NEXT(dv,ip);

    do {
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
        lzo_uint dindex;

        DINDEX1(dindex,ip);
        GINDEX(m_pos,m_off,dict,dindex,in);
        if (LZO_CHECK_MPOS(m_pos,m_off,in,ip,MAX_OFFSET))
            goto literal;
        if (m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2])
            goto match;
        DINDEX2(dindex,ip);
        GINDEX(m_pos,m_off,dict,dindex,in);
        if (LZO_CHECK_MPOS(m_pos,m_off,in,ip,MAX_OFFSET))
            goto literal;
        if (m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2])
            goto match;
        goto literal;


literal:
        UPDATE_I(dict,0,dindex,ip,in);
        if (++ip >= ip_end)
            break;
        continue;

match:
        UPDATE_I(dict,0,dindex,ip,in);
#if !defined(NDEBUG) && (LZO_DICT_USE_PTR)
        m_pos_sav = m_pos;
#endif
        m_pos += 3;
        {
    /* we have found a match (of at least length 3) */
#if !defined(NDEBUG) && !(LZO_DICT_USE_PTR)
            assert((m_pos_sav = ip - m_off) == (m_pos - 3));
#endif
            /* 1) store the current literal run */
            if (pd(ip,ii) > 0)
            {
                lzo_uint t = pd(ip,ii);
#if 1
                /* OPTIMIZED: inline the copying of a short run */
                if (t < R0MIN)
                {
                    *op++ = LZO_BYTE(t);
                    MEMCPY_DS(op, ii, t);
                }
                else
#endif
                    op = store_run(op,ii,t);
            }

            /* 2a) compute match len */
            ii = ip;        /* point to start of current match */

            /* we already matched MIN_MATCH bytes,
             * m_pos also already advanced MIN_MATCH bytes */
            ip += MIN_MATCH;
            assert(m_pos < ip);

            /* try to match another MIN_MATCH_LONG - MIN_MATCH bytes
             * to see if we get a long match */

#define PS  *m_pos++ != *ip++

#if (MIN_MATCH_LONG - MIN_MATCH == 2)                   /* MBITS == 2 */
            if (PS || PS)
#elif (MIN_MATCH_LONG - MIN_MATCH == 6)                 /* MBITS == 3 */
            if (PS || PS || PS || PS || PS || PS)
#elif (MIN_MATCH_LONG - MIN_MATCH == 14)                /* MBITS == 4 */
            if (PS || PS || PS || PS || PS || PS || PS ||
                PS || PS || PS || PS || PS || PS || PS)
#elif (MIN_MATCH_LONG - MIN_MATCH == 30)                /* MBITS == 5 */
            if (PS || PS || PS || PS || PS || PS || PS || PS ||
                PS || PS || PS || PS || PS || PS || PS || PS ||
                PS || PS || PS || PS || PS || PS || PS || PS ||
                PS || PS || PS || PS || PS || PS)
#else
#  error "MBITS not yet implemented"
#endif
            {
                lzo_uint m_len;

            /* 2b) code a short match */
                    assert(pd(ip,m_pos) == m_off);
                --ip;   /* ran one too far, point back to non-match */
                m_len = pd(ip, ii);
                    assert(m_len >= MIN_MATCH_SHORT);
                    assert(m_len <= MAX_MATCH_SHORT);
                    assert(m_off > 0);
                    assert(m_off <= MAX_OFFSET);
                    assert(ii-m_off == m_pos_sav);
                    assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
                --m_off;
                /* code short match len + low offset bits */
                *op++ = LZO_BYTE(((m_len - THRESHOLD) << OBITS) |
                                 (m_off & OMASK));
                /* code high offset bits */
                *op++ = LZO_BYTE(m_off >> OBITS);


            /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */

#define SI      /* nothing */
#define DI      ++ii; DVAL_NEXT(dv,ii); UPDATE_D(dict,0,dv,ii,in);
#define XI      assert(ii < ip); ii = ip; DVAL_FIRST(dv,(ip));

#if (CLEVEL == 9) || (CLEVEL >= 7 && MBITS <= 4) || (CLEVEL >= 5 && MBITS <= 3)
            /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
                ++ii;
                do {
                    DVAL_NEXT(dv,ii);
                    UPDATE_D(dict,0,dv,ii,in);
                } while (++ii < ip);
                DVAL_NEXT(dv,ii);
                assert(ii == ip);
                DVAL_ASSERT(dv,ip);
#elif (CLEVEL >= 3)
                SI   DI DI   XI
#elif (CLEVEL >= 2)
                SI   DI      XI
#else
                             XI
#endif

            }
            else
            {
            /* we've found a long match - see how far we can still go */
                const lzo_bytep end;
                lzo_uint m_len;

                assert(ip <= in_end);
                assert(ii == ip - MIN_MATCH_LONG);

                if (pd(in_end,ip) <= (MAX_MATCH_LONG - MIN_MATCH_LONG))
                    end = in_end;
                else
                {
                    end = ip + (MAX_MATCH_LONG - MIN_MATCH_LONG);
                    assert(end < in_end);
                }

                while (ip < end  &&  *m_pos == *ip)
                    m_pos++, ip++;
                assert(ip <= in_end);

            /* 2b) code the long match */
                m_len = pd(ip, ii);
                    assert(m_len >= MIN_MATCH_LONG);
                    assert(m_len <= MAX_MATCH_LONG);
                    assert(m_off > 0);
                    assert(m_off <= MAX_OFFSET);
                    assert(ii-m_off == m_pos_sav);
                    assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
                    assert(pd(ip,m_pos) == m_off);
                --m_off;
                /* code long match flag + low offset bits */
                *op++ = LZO_BYTE(((MSIZE - 1) << OBITS) | (m_off & OMASK));
                /* code high offset bits */
                *op++ = LZO_BYTE(m_off >> OBITS);
                /* code match len */
                *op++ = LZO_BYTE(m_len - MIN_MATCH_LONG);


            /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
#if (CLEVEL == 9)
            /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
            /* This is not recommended because it is slow. */
                ++ii;
                do {
                    DVAL_NEXT(dv,ii);
                    UPDATE_D(dict,0,dv,ii,in);
                } while (++ii < ip);
                DVAL_NEXT(dv,ii);
                assert(ii == ip);
                DVAL_ASSERT(dv,ip);
#elif (CLEVEL >= 8)
                SI   DI DI DI DI DI DI DI DI   XI
#elif (CLEVEL >= 7)
                SI   DI DI DI DI DI DI DI      XI
#elif (CLEVEL >= 6)
                SI   DI DI DI DI DI DI         XI
#elif (CLEVEL >= 5)
                SI   DI DI DI DI               XI
#elif (CLEVEL >= 4)
                SI   DI DI DI                  XI
#elif (CLEVEL >= 3)
                SI   DI DI                     XI
#elif (CLEVEL >= 2)
                SI   DI                        XI
#else
                                               XI
#endif
            }

            /* ii now points to the start of next literal run */
            assert(ii == ip);
        }
Beispiel #5
0
lzo1_decompress  ( const lzo_bytep in , lzo_uint  in_len,
                         lzo_bytep out, lzo_uintp out_len,
                         lzo_voidp wrkmem )
{
    lzo_bytep op;
    const lzo_bytep ip;
    const lzo_bytep const ip_end = in + in_len;
    lzo_uint t;

    LZO_UNUSED(wrkmem);

    op = out;
    ip = in;
    while (ip < ip_end)
    {
        t = *ip++;  /* get marker */

        if (t < R0MIN)          /* a literal run */
        {
            if (t == 0)             /* a R0 literal run */
            {
                t = *ip++;
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
                {
                    t -= R0FAST - R0MIN;
                    if (t == 0)
                        t = R0FAST;
                    else
                    {
#if 0
                        t = 256u << ((unsigned) t);
#else
                        /* help the optimizer */
                        lzo_uint tt = 256;
                        do tt <<= 1; while (--t > 0);
                        t = tt;
#endif
                    }
                    MEMCPY8_DS(op,ip,t);
                    continue;
                }
                t += R0MIN;
            }
            MEMCPY_DS(op,ip,t);
        }
        else                    /* a match */
        {
            lzo_uint tt;
            /* get match offset */
            const lzo_bytep m_pos = op - 1;
            m_pos -= (lzo_uint)(t & OMASK) | (((lzo_uint) *ip++) << OBITS);

            /* get match len */
            if (t >= ((MSIZE - 1) << OBITS))                /* all m-bits set */
                tt = (MIN_MATCH_LONG - THRESHOLD) + *ip++;  /* a long match */
            else
                tt = t >> OBITS;                            /* a short match */

            assert(m_pos >= out);
            assert(m_pos <  op);
            /* a half unrolled loop */
            *op++ = *m_pos++;
            *op++ = *m_pos++;
            MEMCPY_DS(op,m_pos,tt);
        }
    }

    *out_len = pd(op, out);

    /* the next line is the only check in the decompressor ! */
    return (ip == ip_end ? LZO_E_OK :
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
}