Blame src/lzo1x_9x.c

Packit 679830
/* lzo1x_9x.c -- implementation of the LZO1X-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
#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
Packit 679830
#  define LZO1X 1
Packit 679830
#endif
Packit 679830
Packit 679830
#if defined(LZO1X)
Packit 679830
#  include "config1x.h"
Packit 679830
#elif defined(LZO1Y)
Packit 679830
#  include "config1y.h"
Packit 679830
#elif defined(LZO1Z)
Packit 679830
#  include "config1z.h"
Packit 679830
#else
Packit 679830
#  error
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
#define SWD_N           M4_MAX_OFFSET   /* size of ring buffer */
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
#define SWD_BEST_OFF    (LZO_MAX3( M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN ) + 1)
Packit 679830
Packit 679830
#if defined(LZO1X)
Packit 679830
#  define LZO_COMPRESS_T                lzo1x_999_t
Packit 679830
#  define lzo_swd_t                     lzo1x_999_swd_t
Packit 679830
#elif defined(LZO1Y)
Packit 679830
#  define LZO_COMPRESS_T                lzo1y_999_t
Packit 679830
#  define lzo_swd_t                     lzo1y_999_swd_t
Packit 679830
#  define lzo1x_999_compress_internal   lzo1y_999_compress_internal
Packit 679830
#  define lzo1x_999_compress_dict       lzo1y_999_compress_dict
Packit 679830
#  define lzo1x_999_compress_level      lzo1y_999_compress_level
Packit 679830
#  define lzo1x_999_compress            lzo1y_999_compress
Packit 679830
#elif defined(LZO1Z)
Packit 679830
#  define LZO_COMPRESS_T                lzo1z_999_t
Packit 679830
#  define lzo_swd_t                     lzo1z_999_swd_t
Packit 679830
#  define lzo1x_999_compress_internal   lzo1z_999_compress_internal
Packit 679830
#  define lzo1x_999_compress_dict       lzo1z_999_compress_dict
Packit 679830
#  define lzo1x_999_compress_level      lzo1z_999_compress_level
Packit 679830
#  define lzo1x_999_compress            lzo1z_999_compress
Packit 679830
#else
Packit 679830
#  error
Packit 679830
#endif
Packit 679830
Packit 679830
#if 0
Packit 679830
#  define HEAD3(b,p) \
Packit 679830
    ((((((lzo_xint)b[p]<<3)^b[p+1])<<3)^b[p+2]) & (SWD_HSIZE-1))
Packit 679830
#endif
Packit 679830
#if 0 && (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN)
Packit 679830
#  define HEAD3(b,p) \
Packit 679830
    (((* (lzo_uint32_tp) &b[p]) ^ ((* (lzo_uint32_tp) &b[p])>>10)) & (SWD_HSIZE-1))
Packit 679830
#endif
Packit 679830
Packit 679830
#include "lzo_mchw.ch"
Packit 679830
Packit 679830
Packit 679830
/* this is a public functions, but there is no prototype in a header file */
Packit 679830
LZO_EXTERN(int)
Packit 679830
lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                              const lzo_bytep dict, lzo_uint dict_len,
Packit 679830
                                    lzo_callback_p cb,
Packit 679830
                                    int try_lazy_parm,
Packit 679830
                                    lzo_uint good_length,
Packit 679830
                                    lzo_uint max_lazy,
Packit 679830
                                    lzo_uint nice_length,
Packit 679830
                                    lzo_uint max_chain,
Packit 679830
                                    lzo_uint32_t flags );
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
static lzo_bytep
Packit 679830
code_match ( LZO_COMPRESS_T *c, lzo_bytep op, lzo_uint m_len, lzo_uint m_off )
Packit 679830
{
Packit 679830
    lzo_uint x_len = m_len;
Packit 679830
    lzo_uint x_off = m_off;
Packit 679830
Packit 679830
    c->match_bytes += (unsigned long) m_len;
Packit 679830
Packit 679830
#if 0
Packit 679830
/*
Packit 679830
    static lzo_uint last_m_len = 0, last_m_off = 0;
Packit 679830
    static lzo_uint prev_m_off[4];
Packit 679830
    static unsigned prev_m_off_ptr = 0;
Packit 679830
    unsigned i;
Packit 679830
Packit 679830
    //if (m_len >= 3 && m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
Packit 679830
    if (m_len >= 3 && m_len <= M2_MAX_LEN)
Packit 679830
    {
Packit 679830
    //if (m_len == last_m_len && m_off == last_m_off)
Packit 679830
        //printf("last_m_len + last_m_off\n");
Packit 679830
    //else
Packit 679830
    if (m_off == last_m_off)
Packit 679830
        printf("last_m_off\n");
Packit 679830
    else
Packit 679830
    {
Packit 679830
        for (i = 0; i < 4; i++)
Packit 679830
            if (m_off == prev_m_off[i])
Packit 679830
                printf("prev_m_off %u: %5ld\n",i,(long)m_off);
Packit 679830
    }
Packit 679830
    }
Packit 679830
    last_m_len = m_len;
Packit 679830
    last_m_off = prev_m_off[prev_m_off_ptr] = m_off;
Packit 679830
    prev_m_off_ptr = (prev_m_off_ptr + 1) & 3;
Packit 679830
*/
Packit 679830
#endif
Packit 679830
Packit 679830
    assert(op > c->out);
Packit 679830
    if (m_len == 2)
Packit 679830
    {
Packit 679830
        assert(m_off <= M1_MAX_OFFSET);
Packit 679830
        assert(c->r1_lit > 0); assert(c->r1_lit < 4);
Packit 679830
        m_off -= 1;
Packit 679830
#if defined(LZO1Z)
Packit 679830
        *op++ = LZO_BYTE(M1_MARKER | (m_off >> 6));
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
#else
Packit 679830
        *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
Packit 679830
        *op++ = LZO_BYTE(m_off >> 2);
Packit 679830
#endif
Packit 679830
        c->m1a_m++;
Packit 679830
    }
Packit 679830
#if defined(LZO1Z)
Packit 679830
    else if (m_len <= M2_MAX_LEN && (m_off <= M2_MAX_OFFSET || m_off == c->last_m_off))
Packit 679830
#else
Packit 679830
    else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
Packit 679830
#endif
Packit 679830
    {
Packit 679830
        assert(m_len >= 3);
Packit 679830
#if defined(LZO1X)
Packit 679830
        m_off -= 1;
Packit 679830
        *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
Packit 679830
        *op++ = LZO_BYTE(m_off >> 3);
Packit 679830
        assert(op[-2] >= M2_MARKER);
Packit 679830
#elif defined(LZO1Y)
Packit 679830
        m_off -= 1;
Packit 679830
        *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
Packit 679830
        *op++ = LZO_BYTE(m_off >> 2);
Packit 679830
        assert(op[-2] >= M2_MARKER);
Packit 679830
#elif defined(LZO1Z)
Packit 679830
        if (m_off == c->last_m_off)
Packit 679830
            *op++ = LZO_BYTE(((m_len - 1) << 5) | (0x700 >> 6));
Packit 679830
        else
Packit 679830
        {
Packit 679830
            m_off -= 1;
Packit 679830
            *op++ = LZO_BYTE(((m_len - 1) << 5) | (m_off >> 6));
Packit 679830
            *op++ = LZO_BYTE(m_off << 2);
Packit 679830
        }
Packit 679830
#endif
Packit 679830
        c->m2_m++;
Packit 679830
    }
Packit 679830
    else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && c->r1_lit >= 4)
Packit 679830
    {
Packit 679830
        assert(m_len == 3);
Packit 679830
        assert(m_off > M2_MAX_OFFSET);
Packit 679830
        m_off -= 1 + M2_MAX_OFFSET;
Packit 679830
#if defined(LZO1Z)
Packit 679830
        *op++ = LZO_BYTE(M1_MARKER | (m_off >> 6));
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
#else
Packit 679830
        *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
Packit 679830
        *op++ = LZO_BYTE(m_off >> 2);
Packit 679830
#endif
Packit 679830
        c->m1b_m++;
Packit 679830
    }
Packit 679830
    else if (m_off <= M3_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        assert(m_len >= 3);
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 (m_len > 255)
Packit 679830
            {
Packit 679830
                m_len -= 255;
Packit 679830
                *op++ = 0;
Packit 679830
            }
Packit 679830
            assert(m_len > 0);
Packit 679830
            *op++ = LZO_BYTE(m_len);
Packit 679830
        }
Packit 679830
#if defined(LZO1Z)
Packit 679830
        *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
#else
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
        *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
#endif
Packit 679830
        c->m3_m++;
Packit 679830
    }
Packit 679830
    else
Packit 679830
    {
Packit 679830
        lzo_uint k;
Packit 679830
Packit 679830
        assert(m_len >= 3);
Packit 679830
        assert(m_off > 0x4000); assert(m_off <= 0xbfff);
Packit 679830
        m_off -= 0x4000;
Packit 679830
        k = (m_off & 0x4000) >> 11;
Packit 679830
        if (m_len <= M4_MAX_LEN)
Packit 679830
            *op++ = LZO_BYTE(M4_MARKER | k | (m_len - 2));
Packit 679830
        else
Packit 679830
        {
Packit 679830
            m_len -= M4_MAX_LEN;
Packit 679830
            *op++ = LZO_BYTE(M4_MARKER | k | 0);
Packit 679830
            while (m_len > 255)
Packit 679830
            {
Packit 679830
                m_len -= 255;
Packit 679830
                *op++ = 0;
Packit 679830
            }
Packit 679830
            assert(m_len > 0);
Packit 679830
            *op++ = LZO_BYTE(m_len);
Packit 679830
        }
Packit 679830
#if defined(LZO1Z)
Packit 679830
        *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
#else
Packit 679830
        *op++ = LZO_BYTE(m_off << 2);
Packit 679830
        *op++ = LZO_BYTE(m_off >> 6);
Packit 679830
#endif
Packit 679830
        c->m4_m++;
Packit 679830
    }
Packit 679830
Packit 679830
    c->last_m_len = x_len;
Packit 679830
    c->last_m_off = x_off;
Packit 679830
    return op;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
static lzo_bytep
Packit 679830
STORE_RUN ( LZO_COMPRESS_T *c, lzo_bytep op, const lzo_bytep ii, lzo_uint t )
Packit 679830
{
Packit 679830
    c->lit_bytes += (unsigned long) t;
Packit 679830
Packit 679830
    if (op == c->out && t <= 238)
Packit 679830
    {
Packit 679830
        *op++ = LZO_BYTE(17 + t);
Packit 679830
    }
Packit 679830
    else if (t <= 3)
Packit 679830
    {
Packit 679830
#if defined(LZO1Z)
Packit 679830
        op[-1] = LZO_BYTE(op[-1] | t);
Packit 679830
#else
Packit 679830
        op[-2] = LZO_BYTE(op[-2] | t);
Packit 679830
#endif
Packit 679830
        c->lit1_r++;
Packit 679830
    }
Packit 679830
    else if (t <= 18)
Packit 679830
    {
Packit 679830
        *op++ = LZO_BYTE(t - 3);
Packit 679830
        c->lit2_r++;
Packit 679830
    }
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
            *op++ = 0;
Packit 679830
        }
Packit 679830
        assert(tt > 0);
Packit 679830
        *op++ = LZO_BYTE(tt);
Packit 679830
        c->lit3_r++;
Packit 679830
    }
Packit 679830
    do *op++ = *ii++; while (--t > 0);
Packit 679830
Packit 679830
    return op;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
static lzo_bytep
Packit 679830
code_run ( LZO_COMPRESS_T *c, lzo_bytep op, const lzo_bytep ii,
Packit 679830
           lzo_uint lit, lzo_uint m_len )
Packit 679830
{
Packit 679830
    if (lit > 0)
Packit 679830
    {
Packit 679830
        assert(m_len >= 2);
Packit 679830
        op = STORE_RUN(c,op,ii,lit);
Packit 679830
        c->r1_m_len = m_len;
Packit 679830
        c->r1_lit = lit;
Packit 679830
    }
Packit 679830
    else
Packit 679830
    {
Packit 679830
        assert(m_len >= 3);
Packit 679830
        c->r1_m_len = 0;
Packit 679830
        c->r1_lit = 0;
Packit 679830
    }
Packit 679830
Packit 679830
    return op;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
static lzo_uint
Packit 679830
len_of_coded_match ( lzo_uint m_len, lzo_uint m_off, lzo_uint lit )
Packit 679830
{
Packit 679830
    lzo_uint n = 4;
Packit 679830
Packit 679830
    if (m_len < 2)
Packit 679830
        return 0;
Packit 679830
    if (m_len == 2)
Packit 679830
        return (m_off <= M1_MAX_OFFSET && lit > 0 && lit < 4) ? 2 : 0;
Packit 679830
    if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
Packit 679830
        return 2;
Packit 679830
    if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
Packit 679830
        return 2;
Packit 679830
    if (m_off <= M3_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        if (m_len <= M3_MAX_LEN)
Packit 679830
            return 3;
Packit 679830
        m_len -= M3_MAX_LEN;
Packit 679830
        while (m_len > 255)
Packit 679830
        {
Packit 679830
            m_len -= 255;
Packit 679830
            n++;
Packit 679830
        }
Packit 679830
        return n;
Packit 679830
    }
Packit 679830
    if (m_off <= M4_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        if (m_len <= M4_MAX_LEN)
Packit 679830
            return 3;
Packit 679830
        m_len -= M4_MAX_LEN;
Packit 679830
        while (m_len > 255)
Packit 679830
        {
Packit 679830
            m_len -= 255;
Packit 679830
            n++;
Packit 679830
        }
Packit 679830
        return n;
Packit 679830
    }
Packit 679830
    return 0;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
static lzo_uint
Packit 679830
min_gain(lzo_uint ahead, lzo_uint lit1, lzo_uint lit2, lzo_uint l1, lzo_uint l2, lzo_uint l3)
Packit 679830
{
Packit 679830
    lzo_uint lazy_match_min_gain;
Packit 679830
Packit 679830
    assert (ahead >= 1);
Packit 679830
    lazy_match_min_gain = ahead;
Packit 679830
Packit 679830
#if 0
Packit 679830
    if (l3)
Packit 679830
        lit2 -= ahead;
Packit 679830
#endif
Packit 679830
Packit 679830
    if (lit1 <= 3)
Packit 679830
        lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
Packit 679830
    else if (lit1 <= 18)
Packit 679830
        lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
Packit 679830
Packit 679830
    lazy_match_min_gain += (l2 - l1) * 2;
Packit 679830
    if (l3)
Packit 679830
        lazy_match_min_gain -= (ahead - l3) * 2;
Packit 679830
Packit 679830
    if ((lzo_int) lazy_match_min_gain < 0)
Packit 679830
        lazy_match_min_gain = 0;
Packit 679830
Packit 679830
#if 0
Packit 679830
    if (l1 == 2)
Packit 679830
        if (lazy_match_min_gain == 0)
Packit 679830
            lazy_match_min_gain = 1;
Packit 679830
#endif
Packit 679830
Packit 679830
    return lazy_match_min_gain;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
#if !defined(NDEBUG)
Packit 679830
static
Packit 679830
void assert_match( const lzo_swd_p swd, lzo_uint m_len, lzo_uint m_off )
Packit 679830
{
Packit 679830
    const LZO_COMPRESS_T *c = swd->c;
Packit 679830
    lzo_uint d_off;
Packit 679830
Packit 679830
    assert(m_len >= 2);
Packit 679830
    if (m_off <= (lzo_uint) (c->bp - c->in))
Packit 679830
    {
Packit 679830
        assert(c->bp - m_off + m_len < c->ip);
Packit 679830
        assert(lzo_memcmp(c->bp, c->bp - m_off, m_len) == 0);
Packit 679830
    }
Packit 679830
    else
Packit 679830
    {
Packit 679830
        assert(swd->dict != NULL);
Packit 679830
        d_off = m_off - (lzo_uint) (c->bp - c->in);
Packit 679830
        assert(d_off <= swd->dict_len);
Packit 679830
        if (m_len > d_off)
Packit 679830
        {
Packit 679830
            assert(lzo_memcmp(c->bp, swd->dict_end - d_off, d_off) == 0);
Packit 679830
            assert(c->in + m_len - d_off < c->ip);
Packit 679830
            assert(lzo_memcmp(c->bp + d_off, c->in, m_len - d_off) == 0);
Packit 679830
        }
Packit 679830
        else
Packit 679830
        {
Packit 679830
            assert(lzo_memcmp(c->bp, swd->dict_end - d_off, m_len) == 0);
Packit 679830
        }
Packit 679830
    }
Packit 679830
}
Packit 679830
#else
Packit 679830
#  define assert_match(a,b,c)   ((void)0)
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
#if defined(SWD_BEST_OFF)
Packit 679830
Packit 679830
static void
Packit 679830
better_match ( const lzo_swd_p swd, lzo_uint *m_len, lzo_uint *m_off )
Packit 679830
{
Packit 679830
#if defined(LZO1Z)
Packit 679830
    const LZO_COMPRESS_T *c = swd->c;
Packit 679830
#endif
Packit 679830
Packit 679830
    if (*m_len <= M2_MIN_LEN)
Packit 679830
        return;
Packit 679830
#if defined(LZO1Z)
Packit 679830
    if (*m_off == c->last_m_off && *m_len <= M2_MAX_LEN)
Packit 679830
        return;
Packit 679830
#if 1
Packit 679830
    if (*m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
Packit 679830
        c->last_m_off && swd->best_off[*m_len-1] == c->last_m_off)
Packit 679830
    {
Packit 679830
        *m_len = *m_len - 1;
Packit 679830
        *m_off = swd->best_off[*m_len];
Packit 679830
        return;
Packit 679830
    }
Packit 679830
#endif
Packit 679830
#endif
Packit 679830
Packit 679830
    if (*m_off <= M2_MAX_OFFSET)
Packit 679830
        return;
Packit 679830
Packit 679830
#if 1
Packit 679830
    /* M3/M4 -> M2 */
Packit 679830
    if (*m_off > M2_MAX_OFFSET &&
Packit 679830
        *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
Packit 679830
        swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M2_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        *m_len = *m_len - 1;
Packit 679830
        *m_off = swd->best_off[*m_len];
Packit 679830
        return;
Packit 679830
    }
Packit 679830
#endif
Packit 679830
Packit 679830
#if 1
Packit 679830
    /* M4 -> M2 */
Packit 679830
    if (*m_off > M3_MAX_OFFSET &&
Packit 679830
        *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2 &&
Packit 679830
        swd->best_off[*m_len-2] && swd->best_off[*m_len-2] <= M2_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        *m_len = *m_len - 2;
Packit 679830
        *m_off = swd->best_off[*m_len];
Packit 679830
        return;
Packit 679830
    }
Packit 679830
#endif
Packit 679830
Packit 679830
#if 1
Packit 679830
    /* M4 -> M3 */
Packit 679830
    if (*m_off > M3_MAX_OFFSET &&
Packit 679830
        *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1 &&
Packit 679830
        swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M3_MAX_OFFSET)
Packit 679830
    {
Packit 679830
        *m_len = *m_len - 1;
Packit 679830
        *m_off = swd->best_off[*m_len];
Packit 679830
    }
Packit 679830
#endif
Packit 679830
}
Packit 679830
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                              const lzo_bytep dict, lzo_uint dict_len,
Packit 679830
                                    lzo_callback_p cb,
Packit 679830
                                    int try_lazy_parm,
Packit 679830
                                    lzo_uint good_length,
Packit 679830
                                    lzo_uint max_lazy,
Packit 679830
                                    lzo_uint nice_length,
Packit 679830
                                    lzo_uint max_chain,
Packit 679830
                                    lzo_uint32_t flags )
Packit 679830
{
Packit 679830
    lzo_bytep op;
Packit 679830
    const lzo_bytep ii;
Packit 679830
    lzo_uint lit;
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
    lzo_uint try_lazy;
Packit 679830
    int r;
Packit 679830
Packit 679830
    /* sanity check */
Packit 679830
#if defined(LZO1X)
Packit 679830
    LZO_COMPILE_TIME_ASSERT(LZO1X_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
Packit 679830
#elif defined(LZO1Y)
Packit 679830
    LZO_COMPILE_TIME_ASSERT(LZO1Y_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
Packit 679830
#elif defined(LZO1Z)
Packit 679830
    LZO_COMPILE_TIME_ASSERT(LZO1Z_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
Packit 679830
#else
Packit 679830
#  error
Packit 679830
#endif
Packit 679830
Packit 679830
/* setup parameter defaults */
Packit 679830
    /* number of lazy match tries */
Packit 679830
    try_lazy = (lzo_uint) try_lazy_parm;
Packit 679830
    if (try_lazy_parm < 0)
Packit 679830
        try_lazy = 1;
Packit 679830
    /* reduce lazy match search if we already have a match with this length */
Packit 679830
    if (good_length == 0)
Packit 679830
        good_length = 32;
Packit 679830
    /* do not try a lazy match if we already have a match with this length */
Packit 679830
    if (max_lazy == 0)
Packit 679830
        max_lazy = 32;
Packit 679830
    /* stop searching for longer matches than this one */
Packit 679830
    if (nice_length == 0)
Packit 679830
        nice_length = 0;
Packit 679830
    /* don't search more positions than this */
Packit 679830
    if (max_chain == 0)
Packit 679830
        max_chain = SWD_MAX_CHAIN;
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->out = out;
Packit 679830
    c->cb = cb;
Packit 679830
    c->m1a_m = c->m1b_m = c->m2_m = c->m3_m = c->m4_m = 0;
Packit 679830
    c->lit1_r = c->lit2_r = c->lit3_r = 0;
Packit 679830
Packit 679830
    op = out;
Packit 679830
    ii = c->ip;             /* point to start of literal run */
Packit 679830
    lit = 0;
Packit 679830
    c->r1_lit = c->r1_m_len = 0;
Packit 679830
Packit 679830
    r = init_match(c,swd,dict,dict_len,flags);
Packit 679830
    if (r != 0)
Packit 679830
        return r;
Packit 679830
    if (max_chain > 0)
Packit 679830
        swd->max_chain = max_chain;
Packit 679830
    if (nice_length > 0)
Packit 679830
        swd->nice_length = nice_length;
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 ahead;
Packit 679830
        lzo_uint max_ahead;
Packit 679830
        lzo_uint l1, l2, l3;
Packit 679830
Packit 679830
        c->codesize = pd(op, out);
Packit 679830
Packit 679830
        m_len = c->m_len;
Packit 679830
        m_off = c->m_off;
Packit 679830
Packit 679830
        assert(c->bp == c->ip - c->look);
Packit 679830
        assert(c->bp >= in);
Packit 679830
        if (lit == 0)
Packit 679830
            ii = c->bp;
Packit 679830
        assert(ii + lit == c->bp);
Packit 679830
        assert(swd->b_char == *(c->bp));
Packit 679830
Packit 679830
        if ( m_len < 2 ||
Packit 679830
            (m_len == 2 && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4)) ||
Packit 679830
#if 1
Packit 679830
            /* Do not accept this match for compressed-data compatibility
Packit 679830
             * with LZO v1.01 and before
Packit 679830
             * [ might be a problem for decompress() and optimize() ]
Packit 679830
             */
Packit 679830
            (m_len == 2 && op == out) ||
Packit 679830
#endif
Packit 679830
            (op == out && lit == 0))
Packit 679830
        {
Packit 679830
            /* a literal */
Packit 679830
            m_len = 0;
Packit 679830
        }
Packit 679830
        else if (m_len == M2_MIN_LEN)
Packit 679830
        {
Packit 679830
            /* compression ratio improves if we code a literal in some cases */
Packit 679830
            if (m_off > MX_MAX_OFFSET && lit >= 4)
Packit 679830
                m_len = 0;
Packit 679830
        }
Packit 679830
Packit 679830
        if (m_len == 0)
Packit 679830
        {
Packit 679830
    /* a literal */
Packit 679830
            lit++;
Packit 679830
            swd->max_chain = max_chain;
Packit 679830
            r = find_match(c,swd,1,0);
Packit 679830
            assert(r == 0); LZO_UNUSED(r);
Packit 679830
            continue;
Packit 679830
        }
Packit 679830
Packit 679830
    /* a match */
Packit 679830
#if defined(SWD_BEST_OFF)
Packit 679830
        if (swd->use_best_off)
Packit 679830
            better_match(swd,&m_len,&m_off);
Packit 679830
#endif
Packit 679830
        assert_match(swd,m_len,m_off);
Packit 679830
Packit 679830
Packit 679830
        /* shall we try a lazy match ? */
Packit 679830
        ahead = 0;
Packit 679830
        if (try_lazy == 0 || m_len >= max_lazy)
Packit 679830
        {
Packit 679830
            /* no */
Packit 679830
            l1 = 0;
Packit 679830
            max_ahead = 0;
Packit 679830
        }
Packit 679830
        else
Packit 679830
        {
Packit 679830
            /* yes, try a lazy match */
Packit 679830
            l1 = len_of_coded_match(m_len,m_off,lit);
Packit 679830
            assert(l1 > 0);
Packit 679830
#if 1
Packit 679830
            max_ahead = LZO_MIN(try_lazy, l1 - 1);
Packit 679830
#else
Packit 679830
            max_ahead = LZO_MIN3(try_lazy, l1, m_len - 1);
Packit 679830
#endif
Packit 679830
        }
Packit 679830
Packit 679830
Packit 679830
        while (ahead < max_ahead && c->look > m_len)
Packit 679830
        {
Packit 679830
            lzo_uint lazy_match_min_gain;
Packit 679830
Packit 679830
            if (m_len >= good_length)
Packit 679830
                swd->max_chain = max_chain >> 2;
Packit 679830
            else
Packit 679830
                swd->max_chain = max_chain;
Packit 679830
            r = find_match(c,swd,1,0);
Packit 679830
            ahead++;
Packit 679830
Packit 679830
            assert(r == 0); LZO_UNUSED(r);
Packit 679830
            assert(c->look > 0);
Packit 679830
            assert(ii + lit + ahead == c->bp);
Packit 679830
Packit 679830
#if defined(LZO1Z)
Packit 679830
            if (m_off == c->last_m_off && c->m_off != c->last_m_off)
Packit 679830
                if (m_len >= M2_MIN_LEN && m_len <= M2_MAX_LEN)
Packit 679830
                    c->m_len = 0;
Packit 679830
#endif
Packit 679830
            if (c->m_len < m_len)
Packit 679830
                continue;
Packit 679830
#if 1
Packit 679830
            if (c->m_len == m_len && c->m_off >= m_off)
Packit 679830
                continue;
Packit 679830
#endif
Packit 679830
#if defined(SWD_BEST_OFF)
Packit 679830
            if (swd->use_best_off)
Packit 679830
                better_match(swd,&c->m_len,&c->m_off);
Packit 679830
#endif
Packit 679830
            l2 = len_of_coded_match(c->m_len,c->m_off,lit+ahead);
Packit 679830
            if (l2 == 0)
Packit 679830
                continue;
Packit 679830
#if 0
Packit 679830
            if (c->m_len == m_len && l2 >= l1)
Packit 679830
                continue;
Packit 679830
#endif
Packit 679830
Packit 679830
Packit 679830
#if 1
Packit 679830
            /* compressed-data compatibility [see above] */
Packit 679830
            l3 = (op == out) ? 0 : len_of_coded_match(ahead,m_off,lit);
Packit 679830
#else
Packit 679830
            l3 = len_of_coded_match(ahead,m_off,lit);
Packit 679830
#endif
Packit 679830
Packit 679830
            lazy_match_min_gain = min_gain(ahead,lit,lit+ahead,l1,l2,l3);
Packit 679830
            if (c->m_len >= m_len + lazy_match_min_gain)
Packit 679830
            {
Packit 679830
                c->lazy++;
Packit 679830
                assert_match(swd,c->m_len,c->m_off);
Packit 679830
Packit 679830
                if (l3)
Packit 679830
                {
Packit 679830
                    /* code previous run */
Packit 679830
                    op = code_run(c,op,ii,lit,ahead);
Packit 679830
                    lit = 0;
Packit 679830
                    /* code shortened match */
Packit 679830
                    op = code_match(c,op,ahead,m_off);
Packit 679830
                }
Packit 679830
                else
Packit 679830
                {
Packit 679830
                    lit += ahead;
Packit 679830
                    assert(ii + lit == c->bp);
Packit 679830
                }
Packit 679830
                goto lazy_match_done;
Packit 679830
            }
Packit 679830
        }
Packit 679830
Packit 679830
Packit 679830
        assert(ii + lit + ahead == c->bp);
Packit 679830
Packit 679830
        /* 1 - code run */
Packit 679830
        op = code_run(c,op,ii,lit,m_len);
Packit 679830
        lit = 0;
Packit 679830
Packit 679830
        /* 2 - code match */
Packit 679830
        op = code_match(c,op,m_len,m_off);
Packit 679830
        swd->max_chain = max_chain;
Packit 679830
        r = find_match(c,swd,m_len,1+ahead);
Packit 679830
        assert(r == 0); LZO_UNUSED(r);
Packit 679830
Packit 679830
lazy_match_done: ;
Packit 679830
    }
Packit 679830
Packit 679830
Packit 679830
    /* store final run */
Packit 679830
    if (lit > 0)
Packit 679830
        op = STORE_RUN(c,op,ii,lit);
Packit 679830
Packit 679830
#if defined(LZO_EOF_CODE)
Packit 679830
    *op++ = M4_MARKER | 1;
Packit 679830
    *op++ = 0;
Packit 679830
    *op++ = 0;
Packit 679830
#endif
Packit 679830
Packit 679830
    c->codesize = pd(op, out);
Packit 679830
    assert(c->textsize == in_len);
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 %ld  %ld: %ld %ld %ld  %ld\n",
Packit 679830
        (long) c->textsize, (long) in_len, (long) c->codesize,
Packit 679830
        c->match_bytes, c->m1a_m, c->m1b_m, c->m2_m, c->m3_m, c->m4_m,
Packit 679830
        c->lit_bytes, c->lit1_r, c->lit2_r, c->lit3_r, c->lazy);
Packit 679830
#endif
Packit 679830
    assert(c->lit_bytes + c->match_bytes == in_len);
Packit 679830
Packit 679830
    return LZO_E_OK;
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo1x_999_compress_level    ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                              const lzo_bytep dict, lzo_uint dict_len,
Packit 679830
                                    lzo_callback_p cb,
Packit 679830
                                    int compression_level )
Packit 679830
{
Packit 679830
    static const struct
Packit 679830
    {
Packit 679830
        int try_lazy_parm;
Packit 679830
        lzo_uint good_length;
Packit 679830
        lzo_uint max_lazy;
Packit 679830
        lzo_uint nice_length;
Packit 679830
        lzo_uint max_chain;
Packit 679830
        lzo_uint32_t flags;
Packit 679830
    } c[9] = {
Packit 679830
        /* faster compression */
Packit 679830
        {   0,     0,     0,     8,    4,   0 },
Packit 679830
        {   0,     0,     0,    16,    8,   0 },
Packit 679830
        {   0,     0,     0,    32,   16,   0 },
Packit 679830
        {   1,     4,     4,    16,   16,   0 },
Packit 679830
        {   1,     8,    16,    32,   32,   0 },
Packit 679830
        {   1,     8,    16,   128,  128,   0 },
Packit 679830
        {   2,     8,    32,   128,  256,   0 },
Packit 679830
        {   2,    32,   128, SWD_F, 2048,   1 },
Packit 679830
        {   2, SWD_F, SWD_F, SWD_F, 4096,   1 }
Packit 679830
        /* max. compression */
Packit 679830
    };
Packit 679830
Packit 679830
    if (compression_level < 1 || compression_level > 9)
Packit 679830
        return LZO_E_ERROR;
Packit 679830
Packit 679830
    compression_level -= 1;
Packit 679830
    return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
Packit 679830
                                       dict, dict_len, cb,
Packit 679830
                                       c[compression_level].try_lazy_parm,
Packit 679830
                                       c[compression_level].good_length,
Packit 679830
                                       c[compression_level].max_lazy,
Packit 679830
#if 0
Packit 679830
                                       c[compression_level].nice_length,
Packit 679830
#else
Packit 679830
                                       0,
Packit 679830
#endif
Packit 679830
                                       c[compression_level].max_chain,
Packit 679830
                                       c[compression_level].flags);
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/***********************************************************************
Packit 679830
//
Packit 679830
************************************************************************/
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo1x_999_compress_dict     ( const lzo_bytep in , lzo_uint  in_len,
Packit 679830
                                    lzo_bytep out, lzo_uintp out_len,
Packit 679830
                                    lzo_voidp wrkmem,
Packit 679830
                              const lzo_bytep dict, lzo_uint dict_len )
Packit 679830
{
Packit 679830
    return lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
Packit 679830
                                    dict, dict_len, 0, 8);
Packit 679830
}
Packit 679830
Packit 679830
LZO_PUBLIC(int)
Packit 679830
lzo1x_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 lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
Packit 679830
                                    NULL, 0, (lzo_callback_p) 0, 8);
Packit 679830
}
Packit 679830
Packit 679830
Packit 679830
/*
Packit 679830
vi:ts=4:et
Packit 679830
*/
Packit 679830