Blame src/lzo2a_9x.c

Packit 679830
/* lzo2a_9x.c -- implementation of the LZO2A-999 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
#include "config2a.h"
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
#define SWD_THRESHOLD       1           /* lower limit for match length */
Packit 679830
#define SWD_F            2048           /* upper limit for match length */
Packit 679830
Packit 679830
Packit 679830
#define LZO2A 1
Packit 679830
#define LZO_COMPRESS_T  lzo2a_999_t
Packit 679830
#define lzo_swd_t       lzo2a_999_swd_t
Packit 679830
#include "lzo_mchw.ch"
Packit 679830
Packit 679830
Packit 679830
#if (LZO_CC_BORLANDC && LZO_MM_FLAT)
Packit 679830
#  if ((__BORLANDC__) >= 0x0450 && (__BORLANDC__) < 0x0460)
Packit 679830
     /* avoid internal compiler error */
Packit 679830
#    pragma option -Od
Packit 679830
#  endif
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
#define putbyte(x)      *op++ = LZO_BYTE(x)
Packit 679830
Packit 679830
#define putbits(j,x) \
Packit 679830
    if (k == 0) bitp = op++; \
Packit 679830
    SETBITS(j,x); \
Packit 679830
    if (k >= 8) { *bitp = LZO_BYTE(MASKBITS(8)); DUMPBITS(8); \
Packit 679830
                    if (k > 0) bitp = op++; }
Packit 679830
Packit 679830
#define putbit(x)       putbits(1,x)
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
// this is a public function, but there is no prototype in a header file
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_EXTERN(int)
Packit 679830
lzo2a_999_compress_callback ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                                    lzo_callback_p cb,
Packit 679830
                                    lzo_uint max_chain );
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo2a_999_compress_callback ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                                    lzo_callback_p cb,
Packit 679830
                                    lzo_uint max_chain )
Packit 679830
{
Packit 679830
    lzo_bytep op;
Packit 679830
    lzo_bytep bitp = 0;
Packit 679830
    lzo_uint m_len, m_off;
Packit 679830
    LZO_COMPRESS_T cc;
Packit 679830
    LZO_COMPRESS_T * const c = &cc;
Packit 679830
    lzo_swd_p const swd = (lzo_swd_p) wrkmem;
Packit 679830
    int r;
Packit 679830
Packit 679830
    lzo_uint32_t b = 0;     /* bit buffer */
Packit 679830
    unsigned k = 0;         /* bits in bit buffer */
Packit 679830
Packit 679830
    /* sanity check */
Packit 679830
    LZO_COMPILE_TIME_ASSERT(LZO2A_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
Packit 679830
Packit 679830
    c->init = 0;
Packit 679830
    c->ip = c->in = in;
Packit 679830
    c->in_end = in + in_len;
Packit 679830
    c->cb = cb;
Packit 679830
    c->m1 = c->m2 = c->m3 = c->m4 = 0;
Packit 679830
Packit 679830
    op = out;
Packit 679830
Packit 679830
    r = init_match(c,swd,NULL,0,0);
Packit 679830
    if (r != 0)
Packit 679830
        return r;
Packit 679830
    if (max_chain > 0)
Packit 679830
        swd->max_chain = max_chain;
Packit 679830
Packit 679830
    r = find_match(c,swd,0,0);
Packit 679830
    if (r != 0)
Packit 679830
        return r;
Packit 679830
    while (c->look > 0)
Packit 679830
    {
Packit 679830
        lzo_uint lazy_match_min_gain = 0;
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
        lzo_uint extra1 = 0;
Packit 679830
#endif
Packit 679830
        lzo_uint extra2 = 0;
Packit 679830
        lzo_uint ahead = 0;
Packit 679830
Packit 679830
        m_len = c->m_len;
Packit 679830
        m_off = c->m_off;
Packit 679830
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
        if (m_off >= 8192)
Packit 679830
        {
Packit 679830
            if (m_len < M3_MIN_LEN)
Packit 679830
                m_len = 0;
Packit 679830
            else
Packit 679830
                lazy_match_min_gain = 1;
Packit 679830
        }
Packit 679830
        else
Packit 679830
#endif
Packit 679830
        if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256)
Packit 679830
        {
Packit 679830
            lazy_match_min_gain = 2;
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
            extra1 = 3;
Packit 679830
#endif
Packit 679830
            extra2 = 2;
Packit 679830
        }
Packit 679830
        else if (m_len >= 10)
Packit 679830
            lazy_match_min_gain = 1;
Packit 679830
        else if (m_len >= 3)
Packit 679830
        {
Packit 679830
            lazy_match_min_gain = 1;
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
            extra1 = 1;
Packit 679830
#endif
Packit 679830
        }
Packit 679830
        else
Packit 679830
            m_len = 0;
Packit 679830
Packit 679830
Packit 679830
        /* try a lazy match */
Packit 679830
        if (lazy_match_min_gain > 0 && c->look > m_len)
Packit 679830
        {
Packit 679830
            unsigned char lit = LZO_BYTE(swd->b_char);
Packit 679830
Packit 679830
            r = find_match(c,swd,1,0);
Packit 679830
            assert(r == 0); LZO_UNUSED(r);
Packit 679830
            assert(c->look > 0);
Packit 679830
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
            if (m_off < 8192 && c->m_off >= 8192)
Packit 679830
                lazy_match_min_gain += extra1;
Packit 679830
            else
Packit 679830
#endif
Packit 679830
            if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256)
Packit 679830
            {
Packit 679830
                if (!(c->m_len >= M1_MIN_LEN &&
Packit 679830
                      c->m_len <= M1_MAX_LEN && c->m_off <= 256))
Packit 679830
                    lazy_match_min_gain += extra2;
Packit 679830
            }
Packit 679830
            if (c->m_len >= M1_MIN_LEN &&
Packit 679830
                c->m_len <= M1_MAX_LEN && c->m_off <= 256)
Packit 679830
            {
Packit 679830
                    lazy_match_min_gain -= 1;
Packit 679830
            }
Packit 679830
Packit 679830
            if ((lzo_int) lazy_match_min_gain < 1)
Packit 679830
                lazy_match_min_gain = 1;
Packit 679830
Packit 679830
            if (c->m_len >= m_len + lazy_match_min_gain)
Packit 679830
            {
Packit 679830
                c->lazy++;
Packit 679830
#if !defined(NDEBUG)
Packit 679830
                m_len = c->m_len;
Packit 679830
                m_off = c->m_off;
Packit 679830
                assert(lzo_memcmp(c->ip - c->look, c->ip - c->look - m_off,
Packit 679830
                                  m_len) == 0);
Packit 679830
                assert(m_len >= 3 || (m_len >= 2 && m_off <= 256));
Packit 679830
#endif
Packit 679830
                /* code literal */
Packit 679830
                putbit(0);
Packit 679830
                putbyte(lit);
Packit 679830
                c->lit_bytes++;
Packit 679830
                continue;
Packit 679830
            }
Packit 679830
            else
Packit 679830
                ahead = 1;
Packit 679830
            assert(m_len > 0);
Packit 679830
        }
Packit 679830
Packit 679830
Packit 679830
        if (m_len == 0)
Packit 679830
        {
Packit 679830
            /* a literal */
Packit 679830
            putbit(0);
Packit 679830
            putbyte(swd->b_char);
Packit 679830
            c->lit_bytes++;
Packit 679830
            r = find_match(c,swd,1,0);
Packit 679830
            assert(r == 0); LZO_UNUSED(r);
Packit 679830
        }
Packit 679830
        else
Packit 679830
        {
Packit 679830
            assert(m_len >= M1_MIN_LEN);
Packit 679830
            assert(m_off > 0);
Packit 679830
            assert(m_off <= SWD_N);
Packit 679830
Packit 679830
            /* 2 - code match */
Packit 679830
            if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256)
Packit 679830
            {
Packit 679830
                putbit(1);
Packit 679830
                putbit(0);
Packit 679830
                putbits(2,m_len - M1_MIN_LEN);
Packit 679830
                putbyte(m_off - 1);
Packit 679830
                c->m1++;
Packit 679830
            }
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
            else if (m_off >= 8192)
Packit 679830
            {
Packit 679830
                unsigned len = m_len;
Packit 679830
                assert(m_len >= M3_MIN_LEN);
Packit 679830
                putbit(1);
Packit 679830
                putbit(1);
Packit 679830
                putbyte(m_off & 31);
Packit 679830
                putbyte(m_off >> 5);
Packit 679830
                putbit(1);
Packit 679830
                len -= M3_MIN_LEN - 1;
Packit 679830
                while (len > 255)
Packit 679830
                {
Packit 679830
                    len -= 255;
Packit 679830
                    putbyte(0);
Packit 679830
                }
Packit 679830
                putbyte(len);
Packit 679830
                c->m4++;
Packit 679830
            }
Packit 679830
#endif
Packit 679830
            else
Packit 679830
            {
Packit 679830
                assert(m_len >= 3);
Packit 679830
Packit 679830
                putbit(1);
Packit 679830
                putbit(1);
Packit 679830
                if (m_len <= 9)
Packit 679830
                {
Packit 679830
                    putbyte(((m_len - 2) << 5) | (m_off & 31));
Packit 679830
                    putbyte(m_off >> 5);
Packit 679830
                    c->m2++;
Packit 679830
                }
Packit 679830
                else
Packit 679830
                {
Packit 679830
                    lzo_uint len = m_len;
Packit 679830
                    putbyte(m_off & 31);
Packit 679830
                    putbyte(m_off >> 5);
Packit 679830
#if (SWD_N >= 8192)
Packit 679830
                    putbit(0);
Packit 679830
#endif
Packit 679830
                    len -= 10 - 1;
Packit 679830
                    while (len > 255)
Packit 679830
                    {
Packit 679830
                        len -= 255;
Packit 679830
                        putbyte(0);
Packit 679830
                    }
Packit 679830
                    putbyte(len);
Packit 679830
                    c->m3++;
Packit 679830
                }
Packit 679830
            }
Packit 679830
            r = find_match(c,swd,m_len,1+ahead);
Packit 679830
            assert(r == 0); LZO_UNUSED(r);
Packit 679830
        }
Packit 679830
Packit 679830
        c->codesize = pd(op, out);
Packit 679830
    }
Packit 679830
Packit 679830
#if defined(LZO_EOF_CODE)
Packit 679830
    /* code EOF code */
Packit 679830
    putbit(1);
Packit 679830
    putbit(1);
Packit 679830
    putbyte(1 << 5);
Packit 679830
    putbyte(0);
Packit 679830
#endif
Packit 679830
Packit 679830
    /* flush remaining bits */
Packit 679830
    assert(k < CHAR_BIT);
Packit 679830
    if (k > 0)
Packit 679830
    {
Packit 679830
        assert(b == MASKBITS(k));
Packit 679830
        assert(op - bitp > 1);
Packit 679830
        *bitp = LZO_BYTE(MASKBITS(k));
Packit 679830
        DUMPBITS(k);
Packit 679830
        assert(b == 0);
Packit 679830
        assert(k == 0);
Packit 679830
    }
Packit 679830
Packit 679830
    assert(c->textsize == in_len);
Packit 679830
    c->codesize = pd(op, out);
Packit 679830
Packit 679830
    *out_len = pd(op, out);
Packit 679830
Packit 679830
    if (c->cb && c->cb->nprogress)
Packit 679830
        (*c->cb->nprogress)(c->cb, c->textsize, c->codesize, 0);
Packit 679830
Packit 679830
#if 0
Packit 679830
    printf("%ld -> %ld: %ld %ld %ld %ld %ld %ld\n",
Packit 679830
        (long) c->textsize, (long) c->codesize,
Packit 679830
        c->lit_bytes, c->m1, c->m2, c->m3, c->m4, c->lazy);
Packit 679830
#endif
Packit 679830
    return LZO_E_OK;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo2a_999_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
    return lzo2a_999_compress_callback(in,in_len,out,out_len,wrkmem,
Packit 679830
                                       (lzo_callback_p) 0, 0);
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/*
Packit 679830
vi:ts=4:et
Packit 679830
*/
Packit 679830