Blame src/lzo1x_c.ch

Packit 679830
/* lzo1x_c.ch -- implementation of the LZO1[XY]-1 compression algorithm
Packit 679830
Packit 679830
   This file is part of the LZO real-time data compression library.
Packit 679830
Packit 679830
   Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
Packit 679830
   All Rights Reserved.
Packit 679830
Packit 679830
   The LZO library is free software; you can redistribute it and/or
Packit 679830
   modify it under the terms of the GNU General Public License as
Packit 679830
   published by the Free Software Foundation; either version 2 of
Packit 679830
   the License, or (at your option) any later version.
Packit 679830
Packit 679830
   The LZO library is distributed in the hope that it will be useful,
Packit 679830
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 679830
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 679830
   GNU General Public License for more details.
Packit 679830
Packit 679830
   You should have received a copy of the GNU General Public License
Packit 679830
   along with the LZO library; see the file COPYING.
Packit 679830
   If not, write to the Free Software Foundation, Inc.,
Packit 679830
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 679830
Packit 679830
   Markus F.X.J. Oberhumer
Packit 679830
   <markus@oberhumer.com>
Packit 679830
   http://www.oberhumer.com/opensource/lzo/
Packit 679830
 */
Packit 679830
Packit 679830
Packit 679830
Packit 679830
#if 1 && defined(DO_COMPRESS) && !defined(do_compress)
Packit 679830
   /* choose a unique name to better help PGO optimizations */
Packit 679830
#  define do_compress       LZO_PP_ECONCAT2(DO_COMPRESS,_core)
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
// compress a block of data.
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
static __lzo_noinline lzo_uint
Packit 679830
do_compress ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                    lzo_uint  ti,  lzo_voidp wrkmem)
Packit 679830
{
Packit 679830
    const lzo_bytep ip;
Packit 679830
    lzo_bytep op;
Packit 679830
    const lzo_bytep const in_end = in + in_len;
Packit 679830
    const lzo_bytep const ip_end = in + in_len - 20;
Packit 679830
    const lzo_bytep ii;
Packit 679830
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
Packit 679830
Packit 679830
    op = out;
Packit 679830
    ip = in;
Packit 679830
    ii = ip;
Packit 679830
Packit 679830
    ip += ti < 4 ? 4 - ti : 0;
Packit 679830
    for (;;)
Packit 679830
    {
Packit 679830
        const lzo_bytep m_pos;
Packit 679830
#if !(LZO_DETERMINISTIC)
Packit 679830
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
Packit 679830
        lzo_uint m_len;
Packit 679830
        lzo_uint dindex;
Packit 679830
next:
Packit 679830
        if __lzo_unlikely(ip >= ip_end)
Packit 679830
            break;
Packit 679830
        DINDEX1(dindex,ip);
Packit 679830
        GINDEX(m_pos,m_off,dict,dindex,in);
Packit 679830
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
Packit 679830
            goto literal;
Packit 679830
#if 1
Packit 679830
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
Packit 679830
            goto try_match;
Packit 679830
        DINDEX2(dindex,ip);
Packit 679830
#endif
Packit 679830
        GINDEX(m_pos,m_off,dict,dindex,in);
Packit 679830
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
Packit 679830
            goto literal;
Packit 679830
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
Packit 679830
            goto try_match;
Packit 679830
        goto literal;
Packit 679830
Packit 679830
try_match:
Packit 679830
#if (LZO_OPT_UNALIGNED32)
Packit 679830
        if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip))
Packit 679830
#else
Packit 679830
        if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
Packit 679830
#endif
Packit 679830
        {
Packit 679830
            /* a literal */
Packit 679830
literal:
Packit 679830
            UPDATE_I(dict,0,dindex,ip,in);
Packit 679830
            ip += 1 + ((ip - ii) >> 5);
Packit 679830
            continue;
Packit 679830
        }
Packit 679830
/*match:*/
Packit 679830
        UPDATE_I(dict,0,dindex,ip,in);
Packit 679830
#else
Packit 679830
        lzo_uint m_off;
Packit 679830
        lzo_uint m_len;
Packit 679830
        {
Packit 679830
        lzo_uint32_t dv;
Packit 679830
        lzo_uint dindex;
Packit 679830
literal:
Packit 679830
        ip += 1 + ((ip - ii) >> 5);
Packit 679830
next:
Packit 679830
        if __lzo_unlikely(ip >= ip_end)
Packit 679830
            break;
Packit 679830
        dv = UA_GET_LE32(ip);
Packit 679830
        dindex = DINDEX(dv,ip);
Packit 679830
        GINDEX(m_off,m_pos,in+dict,dindex,in);
Packit 679830
        UPDATE_I(dict,0,dindex,ip,in);
Packit 679830
        if __lzo_unlikely(dv != UA_GET_LE32(m_pos))
Packit 679830
            goto literal;
Packit 679830
        }
Packit 679830
#endif
Packit 679830
Packit 679830
    /* a match */
Packit 679830
Packit 679830
        ii -= ti; ti = 0;
Packit 679830
        {
Packit 679830
        lzo_uint t = pd(ip,ii);
Packit 679830
        if (t != 0)
Packit 679830
        {
Packit 679830
            if (t <= 3)
Packit 679830
            {
Packit 679830
                op[-2] = LZO_BYTE(op[-2] | t);
Packit 679830
#if (LZO_OPT_UNALIGNED32)
Packit 679830
                UA_COPY4(op, ii);
Packit 679830
                op += t;
Packit 679830
#else
Packit 679830
                { do *op++ = *ii++; while (--t > 0); }
Packit 679830
#endif
Packit 679830
            }
Packit 679830
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
Packit 679830
            else if (t <= 16)
Packit 679830
            {
Packit 679830
                *op++ = LZO_BYTE(t - 3);
Packit 679830
                UA_COPY8(op, ii);
Packit 679830
                UA_COPY8(op+8, ii+8);
Packit 679830
                op += t;
Packit 679830
            }
Packit 679830
#endif
Packit 679830
            else
Packit 679830
            {
Packit 679830
                if (t <= 18)
Packit 679830
                    *op++ = LZO_BYTE(t - 3);
Packit 679830
                else
Packit 679830
                {
Packit 679830
                    lzo_uint tt = t - 18;
Packit 679830
                    *op++ = 0;
Packit 679830
                    while __lzo_unlikely(tt > 255)
Packit 679830
                    {
Packit 679830
                        tt -= 255;
Packit 679830
                        UA_SET1(op, 0);
Packit 679830
                        op++;
Packit 679830
                    }
Packit 679830
                    assert(tt > 0);
Packit 679830
                    *op++ = LZO_BYTE(tt);
Packit 679830
                }
Packit 679830
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
Packit 679830
                do {
Packit 679830
                    UA_COPY8(op, ii);
Packit 679830
                    UA_COPY8(op+8, ii+8);
Packit 679830
                    op += 16; ii += 16; t -= 16;
Packit 679830
                } while (t >= 16); if (t > 0)
Packit 679830
#endif
Packit 679830
                { do *op++ = *ii++; while (--t > 0); }
Packit 679830
            }
Packit 679830
        }
Packit 679830
        }
Packit 679830
        m_len = 4;
Packit 679830
        {
Packit 679830
#if (LZO_OPT_UNALIGNED64)
Packit 679830
        lzo_uint64_t v;
Packit 679830
        v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
Packit 679830
        if __lzo_unlikely(v == 0) {
Packit 679830
            do {
Packit 679830
                m_len += 8;
Packit 679830
                v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
Packit 679830
                if __lzo_unlikely(ip + m_len >= ip_end)
Packit 679830
                    goto m_len_done;
Packit 679830
            } while (v == 0);
Packit 679830
        }
Packit 679830
#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64)
Packit 679830
        m_len += lzo_bitops_ctlz64(v) / CHAR_BIT;
Packit 679830
#elif (LZO_ABI_BIG_ENDIAN)
Packit 679830
        if ((v >> (64 - CHAR_BIT)) == 0) do {
Packit 679830
            v <<= CHAR_BIT;
Packit 679830
            m_len += 1;
Packit 679830
        } while ((v >> (64 - CHAR_BIT)) == 0);
Packit 679830
#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64)
Packit 679830
        m_len += lzo_bitops_cttz64(v) / CHAR_BIT;
Packit 679830
#elif (LZO_ABI_LITTLE_ENDIAN)
Packit 679830
        if ((v & UCHAR_MAX) == 0) do {
Packit 679830
            v >>= CHAR_BIT;
Packit 679830
            m_len += 1;
Packit 679830
        } while ((v & UCHAR_MAX) == 0);
Packit 679830
#else
Packit 679830
        if (ip[m_len] == m_pos[m_len]) do {
Packit 679830
            m_len += 1;
Packit 679830
        } while (ip[m_len] == m_pos[m_len]);
Packit 679830
#endif
Packit 679830
#elif (LZO_OPT_UNALIGNED32)
Packit 679830
        lzo_uint32_t v;
Packit 679830
        v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
Packit 679830
        if __lzo_unlikely(v == 0) {
Packit 679830
            do {
Packit 679830
                m_len += 4;
Packit 679830
                v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
Packit 679830
                if (v != 0)
Packit 679830
                    break;
Packit 679830
                m_len += 4;
Packit 679830
                v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
Packit 679830
                if __lzo_unlikely(ip + m_len >= ip_end)
Packit 679830
                    goto m_len_done;
Packit 679830
            } while (v == 0);
Packit 679830
        }
Packit 679830
#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32)
Packit 679830
        m_len += lzo_bitops_ctlz32(v) / CHAR_BIT;
Packit 679830
#elif (LZO_ABI_BIG_ENDIAN)
Packit 679830
        if ((v >> (32 - CHAR_BIT)) == 0) do {
Packit 679830
            v <<= CHAR_BIT;
Packit 679830
            m_len += 1;
Packit 679830
        } while ((v >> (32 - CHAR_BIT)) == 0);
Packit 679830
#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32)
Packit 679830
        m_len += lzo_bitops_cttz32(v) / CHAR_BIT;
Packit 679830
#elif (LZO_ABI_LITTLE_ENDIAN)
Packit 679830
        if ((v & UCHAR_MAX) == 0) do {
Packit 679830
            v >>= CHAR_BIT;
Packit 679830
            m_len += 1;
Packit 679830
        } while ((v & UCHAR_MAX) == 0);
Packit 679830
#else
Packit 679830
        if (ip[m_len] == m_pos[m_len]) do {
Packit 679830
            m_len += 1;
Packit 679830
        } while (ip[m_len] == m_pos[m_len]);
Packit 679830
#endif
Packit 679830
#else
Packit 679830
        if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
Packit 679830
            do {
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if (ip[m_len] != m_pos[m_len])
Packit 679830
                    break;
Packit 679830
                m_len += 1;
Packit 679830
                if __lzo_unlikely(ip + m_len >= ip_end)
Packit 679830
                    goto m_len_done;
Packit 679830
            } while (ip[m_len] == m_pos[m_len]);
Packit 679830
        }
Packit 679830
#endif
Packit 679830
        }
Packit 679830
m_len_done:
Packit 679830
        m_off = pd(ip,m_pos);
Packit 679830
        ip += m_len;
Packit 679830
        ii = ip;
Packit 679830
        if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
Packit 679830
        {
Packit 679830
            m_off -= 1;
Packit 679830
#if defined(LZO1X)
Packit 679830
            *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
Packit 679830
            *op++ = LZO_BYTE(m_off >> 3);
Packit 679830
#elif defined(LZO1Y)
Packit 679830
            *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
Packit 679830
            *op++ = LZO_BYTE(m_off >> 2);
Packit 679830
#endif
Packit 679830
        }
Packit 679830
        else if (m_off <= M3_MAX_OFFSET)
Packit 679830
        {
Packit 679830
            m_off -= 1;
Packit 679830
            if (m_len <= M3_MAX_LEN)
Packit 679830
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
Packit 679830
            else
Packit 679830
            {
Packit 679830
                m_len -= M3_MAX_LEN;
Packit 679830
                *op++ = M3_MARKER | 0;
Packit 679830
                while __lzo_unlikely(m_len > 255)
Packit 679830
                {
Packit 679830
                    m_len -= 255;
Packit 679830
                    UA_SET1(op, 0);
Packit 679830
                    op++;
Packit 679830
                }
Packit 679830
                *op++ = LZO_BYTE(m_len);
Packit 679830
            }
Packit 679830
            *op++ = LZO_BYTE(m_off << 2);
Packit 679830
            *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
        }
Packit 679830
        else
Packit 679830
        {
Packit 679830
            m_off -= 0x4000;
Packit 679830
            if (m_len <= M4_MAX_LEN)
Packit 679830
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
Packit 679830
            else
Packit 679830
            {
Packit 679830
                m_len -= M4_MAX_LEN;
Packit 679830
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
Packit 679830
                while __lzo_unlikely(m_len > 255)
Packit 679830
                {
Packit 679830
                    m_len -= 255;
Packit 679830
                    UA_SET1(op, 0);
Packit 679830
                    op++;
Packit 679830
                }
Packit 679830
                *op++ = LZO_BYTE(m_len);
Packit 679830
            }
Packit 679830
            *op++ = LZO_BYTE(m_off << 2);
Packit 679830
            *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
        }
Packit 679830
        goto next;
Packit 679830
    }
Packit 679830
Packit 679830
    *out_len = pd(op, out);
Packit 679830
    return pd(in_end,ii-ti);
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
// public entry point
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
DO_COMPRESS      ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                         lzo_bytep out, lzo_uintp out_len,
Packit 679830
                         lzo_voidp wrkmem )
Packit 679830
{
Packit 679830
    const lzo_bytep ip = in;
Packit 679830
    lzo_bytep op = out;
Packit 679830
    lzo_uint l = in_len;
Packit 679830
    lzo_uint t = 0;
Packit 679830
Packit 679830
    while (l > 20)
Packit 679830
    {
Packit 679830
        lzo_uint ll = l;
Packit 679830
        lzo_uintptr_t ll_end;
Packit 679830
#if 0 || (LZO_DETERMINISTIC)
Packit 679830
        ll = LZO_MIN(ll, 49152);
Packit 679830
#endif
Packit 679830
        ll_end = (lzo_uintptr_t)ip + ll;
Packit 679830
        if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
Packit 679830
            break;
Packit 679830
#if (LZO_DETERMINISTIC)
Packit 679830
        lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
Packit 679830
#endif
Packit 679830
        t = do_compress(ip,ll,op,out_len,t,wrkmem);
Packit 679830
        ip += ll;
Packit 679830
        op += *out_len;
Packit 679830
        l  -= ll;
Packit 679830
    }
Packit 679830
    t += l;
Packit 679830
Packit 679830
    if (t > 0)
Packit 679830
    {
Packit 679830
        const lzo_bytep ii = in + in_len - t;
Packit 679830
Packit 679830
        if (op == out && t <= 238)
Packit 679830
            *op++ = LZO_BYTE(17 + t);
Packit 679830
        else if (t <= 3)
Packit 679830
            op[-2] = LZO_BYTE(op[-2] | t);
Packit 679830
        else if (t <= 18)
Packit 679830
            *op++ = LZO_BYTE(t - 3);
Packit 679830
        else
Packit 679830
        {
Packit 679830
            lzo_uint tt = t - 18;
Packit 679830
Packit 679830
            *op++ = 0;
Packit 679830
            while (tt > 255)
Packit 679830
            {
Packit 679830
                tt -= 255;
Packit 679830
                UA_SET1(op, 0);
Packit 679830
                op++;
Packit 679830
            }
Packit 679830
            assert(tt > 0);
Packit 679830
            *op++ = LZO_BYTE(tt);
Packit 679830
        }
Packit 679830
        UA_COPYN(op, ii, t);
Packit 679830
        op += t;
Packit 679830
    }
Packit 679830
Packit 679830
    *op++ = M4_MARKER | 1;
Packit 679830
    *op++ = 0;
Packit 679830
    *op++ = 0;
Packit 679830
Packit 679830
    *out_len = pd(op, out);
Packit 679830
    return LZO_E_OK;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/*
Packit 679830
vi:ts=4:et
Packit 679830
*/