kusano 7d535a
/* lzo_swd.ch -- sliding window dictionary
kusano 7d535a
kusano 7d535a
   This file is part of the LZO real-time data compression library.
kusano 7d535a
kusano 7d535a
   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
kusano 7d535a
   All Rights Reserved.
kusano 7d535a
kusano 7d535a
   The LZO library is free software; you can redistribute it and/or
kusano 7d535a
   modify it under the terms of the GNU General Public License as
kusano 7d535a
   published by the Free Software Foundation; either version 2 of
kusano 7d535a
   the License, or (at your option) any later version.
kusano 7d535a
kusano 7d535a
   The LZO library is distributed in the hope that it will be useful,
kusano 7d535a
   but WITHOUT ANY WARRANTY; without even the implied warranty of
kusano 7d535a
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
kusano 7d535a
   GNU General Public License for more details.
kusano 7d535a
kusano 7d535a
   You should have received a copy of the GNU General Public License
kusano 7d535a
   along with the LZO library; see the file COPYING.
kusano 7d535a
   If not, write to the Free Software Foundation, Inc.,
kusano 7d535a
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
kusano 7d535a
kusano 7d535a
   Markus F.X.J. Oberhumer
kusano 7d535a
   <markus@oberhumer.com></markus@oberhumer.com>
kusano 7d535a
   http://www.oberhumer.com/opensource/lzo/
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
kusano 7d535a
#if (LZO_UINT_MAX < LZO_0xffffffffL)
kusano 7d535a
#  error "LZO_UINT_MAX"
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
#ifndef SWD_N
kusano 7d535a
#  define SWD_N             N
kusano 7d535a
#endif
kusano 7d535a
#ifndef SWD_F
kusano 7d535a
#  define SWD_F             F
kusano 7d535a
#endif
kusano 7d535a
#ifndef SWD_THRESHOLD
kusano 7d535a
#  define SWD_THRESHOLD     THRESHOLD
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* unsigned type for dictionary access - don't waste memory here */
kusano 7d535a
#if (0UL + SWD_N + SWD_F + SWD_F < 0UL + USHRT_MAX)
kusano 7d535a
   typedef unsigned short   swd_uint;
kusano 7d535a
#  define SWD_UINT_MAX      USHRT_MAX
kusano 7d535a
#elif (0UL + SWD_N + SWD_F + SWD_F < 0UL + UINT_MAX)
kusano 7d535a
   typedef unsigned         swd_uint;
kusano 7d535a
#  define SWD_UINT_MAX      UINT_MAX
kusano 7d535a
#else
kusano 7d535a
   typedef lzo_uint         swd_uint;
kusano 7d535a
#  define SWD_UINT_MAX      LZO_UINT_MAX
kusano 7d535a
#endif
kusano 7d535a
#define swd_uintp           swd_uint __LZO_MMODEL *
kusano 7d535a
#define SWD_UINT(x)         ((swd_uint)(x))
kusano 7d535a
kusano 7d535a
kusano 7d535a
#ifndef SWD_HSIZE
kusano 7d535a
#  define SWD_HSIZE         16384
kusano 7d535a
#endif
kusano 7d535a
#ifndef SWD_MAX_CHAIN
kusano 7d535a
#  define SWD_MAX_CHAIN     2048
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#if !defined(HEAD3)
kusano 7d535a
#if 1
kusano 7d535a
#  define HEAD3(b,p) \
kusano 7d535a
    ((DMUL(0x9f5f,(((((lzo_xint)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
kusano 7d535a
#else
kusano 7d535a
#  define HEAD3(b,p) \
kusano 7d535a
    ((DMUL(0x9f5f,(((((lzo_xint)b[p+2]<<5)^b[p+1])<<5)^b[p]))>>5) & (SWD_HSIZE-1))
kusano 7d535a
#endif
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#if (SWD_THRESHOLD == 1) && !defined(HEAD2)
kusano 7d535a
#  if 1 && defined(LZO_UNALIGNED_OK_2)
kusano 7d535a
#    define HEAD2(b,p)      (* (lzo_ushortp) &(b[p]))
kusano 7d535a
#  else
kusano 7d535a
#    define HEAD2(b,p)      (b[p] ^ ((unsigned)b[p+1]<<8))
kusano 7d535a
#  endif
kusano 7d535a
#  define NIL2              SWD_UINT_MAX
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
typedef struct
kusano 7d535a
{
kusano 7d535a
/* public - "built-in" */
kusano 7d535a
    lzo_uint n;
kusano 7d535a
    lzo_uint f;
kusano 7d535a
    lzo_uint threshold;
kusano 7d535a
kusano 7d535a
/* public - configuration */
kusano 7d535a
    lzo_uint max_chain;
kusano 7d535a
    lzo_uint nice_length;
kusano 7d535a
    lzo_bool use_best_off;
kusano 7d535a
    lzo_uint lazy_insert;
kusano 7d535a
kusano 7d535a
/* public - output */
kusano 7d535a
    lzo_uint m_len;
kusano 7d535a
    lzo_uint m_off;
kusano 7d535a
    lzo_uint look;
kusano 7d535a
    int b_char;
kusano 7d535a
#if defined(SWD_BEST_OFF)
kusano 7d535a
    lzo_uint best_off[ SWD_BEST_OFF ];
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* semi public */
kusano 7d535a
    LZO_COMPRESS_T *c;
kusano 7d535a
    lzo_uint m_pos;
kusano 7d535a
#if defined(SWD_BEST_OFF)
kusano 7d535a
    lzo_uint best_pos[ SWD_BEST_OFF ];
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* private */
kusano 7d535a
    const lzo_bytep dict;
kusano 7d535a
    const lzo_bytep dict_end;
kusano 7d535a
    lzo_uint dict_len;
kusano 7d535a
kusano 7d535a
/* private */
kusano 7d535a
    lzo_uint ip;                /* input pointer (lookahead) */
kusano 7d535a
    lzo_uint bp;                /* buffer pointer */
kusano 7d535a
    lzo_uint rp;                /* remove pointer */
kusano 7d535a
    lzo_uint b_size;
kusano 7d535a
kusano 7d535a
    lzo_bytep b_wrap;
kusano 7d535a
kusano 7d535a
    lzo_uint node_count;
kusano 7d535a
    lzo_uint first_rp;
kusano 7d535a
kusano 7d535a
#if defined(__LZO_MMODEL_HUGE)
kusano 7d535a
#  define A(type, n)    ((((n) * sizeof(type)) + 3UL) &~ 3UL)
kusano 7d535a
kusano 7d535a
#  define O_b(s)        (0L)
kusano 7d535a
#  define O_head3(s)    (O_b(s) + A(char, 0UL + SWD_N + SWD_F + SWD_F))
kusano 7d535a
#  define O_succ3(s)    (O_head3(s) + A(swd_uint, 0UL + SWD_HSIZE))
kusano 7d535a
#  define O_best3(s)    (O_succ3(s) + A(swd_uint, 0UL + SWD_N + SWD_F))
kusano 7d535a
#  define O_llen3(s)    (O_best3(s) + A(swd_uint, 0UL + SWD_N + SWD_F))
kusano 7d535a
# ifdef HEAD2
kusano 7d535a
#  define O_head2(s)    (O_llen3(s) + A(swd_uint, 0UL + SWD_HSIZE))
kusano 7d535a
#  define O_END(s)      (O_head2(s) + A(swd_uint, 0UL + 65536L))
kusano 7d535a
# else
kusano 7d535a
#  define O_END(s)      (O_llen3(s) + A(swd_uint, 0UL + SWD_HSIZE))
kusano 7d535a
# endif
kusano 7d535a
kusano 7d535a
#  define S_DEF(s,type,off)  ((type) ((lzo_bytep)s + 0L + sizeof(*s) + off))
kusano 7d535a
#  define s_b(s)        S_DEF(s, lzo_bytep, O_b(s))
kusano 7d535a
#  define s_head3(s)    S_DEF(s, swd_uintp, O_head3(s))
kusano 7d535a
#  define s_succ3(s)    S_DEF(s, swd_uintp, O_succ3(s))
kusano 7d535a
#  define s_best3(s)    S_DEF(s, swd_uintp, O_best3(s))
kusano 7d535a
#  define s_llen3(s)    S_DEF(s, swd_uintp, O_llen3(s))
kusano 7d535a
# ifdef HEAD2
kusano 7d535a
#  define s_head2(s)    S_DEF(s, swd_uintp, O_head2(s))
kusano 7d535a
# endif
kusano 7d535a
kusano 7d535a
#elif defined(__LZO_CHECKER)
kusano 7d535a
    /* malloc arrays of the exact size to detect any overrun */
kusano 7d535a
    unsigned char *b;
kusano 7d535a
    swd_uint *head3;
kusano 7d535a
    swd_uint *succ3;
kusano 7d535a
    swd_uint *best3;
kusano 7d535a
    swd_uint *llen3;
kusano 7d535a
# ifdef HEAD2
kusano 7d535a
    swd_uint *head2;
kusano 7d535a
# endif
kusano 7d535a
kusano 7d535a
#else
kusano 7d535a
    unsigned char b [ SWD_N + SWD_F + SWD_F ];
kusano 7d535a
    swd_uint head3 [ SWD_HSIZE ];
kusano 7d535a
    swd_uint succ3 [ SWD_N + SWD_F ];
kusano 7d535a
    swd_uint best3 [ SWD_N + SWD_F ];
kusano 7d535a
    swd_uint llen3 [ SWD_HSIZE ];
kusano 7d535a
# ifdef HEAD2
kusano 7d535a
    swd_uint head2 [ 65536L ];
kusano 7d535a
# endif
kusano 7d535a
#endif
kusano 7d535a
}
kusano 7d535a
lzo_swd_t;
kusano 7d535a
#define lzo_swd_p   lzo_swd_t __LZO_MMODEL *
kusano 7d535a
kusano 7d535a
kusano 7d535a
#if defined(__LZO_MMODEL_HUGE)
kusano 7d535a
#define SIZEOF_LZO_SWD_T    O_END(0)
kusano 7d535a
#else
kusano 7d535a
#define s_b(s)      s->b
kusano 7d535a
#define s_head3(s)  s->head3
kusano 7d535a
#define s_succ3(s)  s->succ3
kusano 7d535a
#define s_best3(s)  s->best3
kusano 7d535a
#define s_llen3(s)  s->llen3
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
#define s_head2(s)  s->head2
kusano 7d535a
#endif
kusano 7d535a
#define SIZEOF_LZO_SWD_T    (sizeof(lzo_swd_t))
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* Access macro for head3.
kusano 7d535a
 * head3[key] may be uninitialized, but then its value will never be used.
kusano 7d535a
 */
kusano 7d535a
#if defined(__LZO_CHECKER)
kusano 7d535a
#  define s_get_head3(s,key) \
kusano 7d535a
        ((s->llen3[key] == 0) ? SWD_UINT_MAX : s_head3(s)[key])
kusano 7d535a
#else
kusano 7d535a
#  define s_get_head3(s,key)    s_head3(s)[key]
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_initdict(lzo_swd_p s, const lzo_bytep dict, lzo_uint dict_len)
kusano 7d535a
{
kusano 7d535a
    s->dict = s->dict_end = NULL;
kusano 7d535a
    s->dict_len = 0;
kusano 7d535a
kusano 7d535a
    if (!dict || dict_len <= 0)
kusano 7d535a
        return;
kusano 7d535a
    if (dict_len > s->n)
kusano 7d535a
    {
kusano 7d535a
        dict += dict_len - s->n;
kusano 7d535a
        dict_len = s->n;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    s->dict = dict;
kusano 7d535a
    s->dict_len = dict_len;
kusano 7d535a
    s->dict_end = dict + dict_len;
kusano 7d535a
    lzo_memcpy(s_b(s),dict,dict_len);
kusano 7d535a
    s->ip = dict_len;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_insertdict(lzo_swd_p s, lzo_uint node, lzo_uint len)
kusano 7d535a
{
kusano 7d535a
    lzo_uint key;
kusano 7d535a
kusano 7d535a
    s->node_count = s->n - len;
kusano 7d535a
    s->first_rp = node;
kusano 7d535a
kusano 7d535a
    while (len-- > 0)
kusano 7d535a
    {
kusano 7d535a
        key = HEAD3(s_b(s),node);
kusano 7d535a
        s_succ3(s)[node] = s_get_head3(s,key);
kusano 7d535a
        s_head3(s)[key] = SWD_UINT(node);
kusano 7d535a
        s_best3(s)[node] = SWD_UINT(s->f + 1);
kusano 7d535a
        s_llen3(s)[key]++;
kusano 7d535a
        assert(s_llen3(s)[key] <= SWD_N);
kusano 7d535a
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
        key = HEAD2(s_b(s),node);
kusano 7d535a
        s_head2(s)[key] = SWD_UINT(node);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
        node++;
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
int swd_init(lzo_swd_p s, const lzo_bytep dict, lzo_uint dict_len)
kusano 7d535a
{
kusano 7d535a
    lzo_uint i = 0;
kusano 7d535a
    int c = 0;
kusano 7d535a
kusano 7d535a
#if defined(__LZO_CHECKER)
kusano 7d535a
    s->b = malloc(SWD_N + SWD_F + SWD_F);
kusano 7d535a
    s->head3 = malloc(sizeof(swd_uint) * SWD_HSIZE);
kusano 7d535a
    s->succ3 = malloc(sizeof(swd_uint) * (SWD_N + SWD_F));
kusano 7d535a
    s->best3 = malloc(sizeof(swd_uint) * (SWD_N + SWD_F));
kusano 7d535a
    s->llen3 = malloc(sizeof(swd_uint) * SWD_HSIZE);
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
    s->head2 = malloc(sizeof(swd_uint) * 65536L);
kusano 7d535a
#endif
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    s->n = SWD_N;
kusano 7d535a
    s->f = SWD_F;
kusano 7d535a
    s->threshold = SWD_THRESHOLD;
kusano 7d535a
kusano 7d535a
    /* defaults */
kusano 7d535a
    s->max_chain = SWD_MAX_CHAIN;
kusano 7d535a
    s->nice_length = SWD_F;
kusano 7d535a
    s->use_best_off = 0;
kusano 7d535a
    s->lazy_insert = 0;
kusano 7d535a
kusano 7d535a
    s->b_size = s->n + s->f;
kusano 7d535a
#if 0
kusano 7d535a
    if (2 * s->f >= s->n || s->b_size + s->f >= SWD_UINT_MAX)
kusano 7d535a
        return LZO_E_ERROR;
kusano 7d535a
#else
kusano 7d535a
    LZO_COMPILE_TIME_ASSERT(!(0ul + 2 * SWD_F >= SWD_N))
kusano 7d535a
    LZO_COMPILE_TIME_ASSERT(!(0ul + SWD_N + SWD_F + SWD_F >= SWD_UINT_MAX))
kusano 7d535a
#endif
kusano 7d535a
    s->b_wrap = s_b(s) + s->b_size;
kusano 7d535a
    s->node_count = s->n;
kusano 7d535a
kusano 7d535a
    lzo_memset(s_llen3(s), 0, sizeof(s_llen3(s)[0]) * (lzo_uint)SWD_HSIZE);
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
#if 1
kusano 7d535a
    lzo_memset(s_head2(s), 0xff, sizeof(s_head2(s)[0]) * 65536L);
kusano 7d535a
    assert(s_head2(s)[0] == NIL2);
kusano 7d535a
#else
kusano 7d535a
    for (i = 0; i < 65536L; i++)
kusano 7d535a
        s_head2(s)[i] = NIL2;
kusano 7d535a
#endif
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    s->ip = 0;
kusano 7d535a
    swd_initdict(s,dict,dict_len);
kusano 7d535a
    s->bp = s->ip;
kusano 7d535a
    s->first_rp = s->ip;
kusano 7d535a
kusano 7d535a
    assert(s->ip + s->f <= s->b_size);
kusano 7d535a
#if 1
kusano 7d535a
    s->look = (lzo_uint) (s->c->in_end - s->c->ip);
kusano 7d535a
    if (s->look > 0)
kusano 7d535a
    {
kusano 7d535a
        if (s->look > s->f)
kusano 7d535a
            s->look = s->f;
kusano 7d535a
        lzo_memcpy(&s_b(s)[s->ip],s->c->ip,s->look);
kusano 7d535a
        s->c->ip += s->look;
kusano 7d535a
        s->ip += s->look;
kusano 7d535a
    }
kusano 7d535a
#else
kusano 7d535a
    s->look = 0;
kusano 7d535a
    while (s->look < s->f)
kusano 7d535a
    {
kusano 7d535a
        if ((c = getbyte(*(s->c))) < 0)
kusano 7d535a
            break;
kusano 7d535a
        s_b(s)[s->ip] = LZO_BYTE(c);
kusano 7d535a
        s->ip++;
kusano 7d535a
        s->look++;
kusano 7d535a
    }
kusano 7d535a
#endif
kusano 7d535a
    if (s->ip == s->b_size)
kusano 7d535a
        s->ip = 0;
kusano 7d535a
kusano 7d535a
    if (s->look >= 2 && s->dict_len > 0)
kusano 7d535a
        swd_insertdict(s,0,s->dict_len);
kusano 7d535a
kusano 7d535a
    s->rp = s->first_rp;
kusano 7d535a
    if (s->rp >= s->node_count)
kusano 7d535a
        s->rp -= s->node_count;
kusano 7d535a
    else
kusano 7d535a
        s->rp += s->b_size - s->node_count;
kusano 7d535a
kusano 7d535a
#if defined(__LZO_CHECKER)
kusano 7d535a
    /* initialize memory for the first few HEAD3 (if s->ip is not far
kusano 7d535a
     * enough ahead to do this job for us). The value doesn't matter. */
kusano 7d535a
    if (s->look < 3)
kusano 7d535a
        lzo_memset(&s_b(s)[s->bp+s->look],0,3);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    LZO_UNUSED(i);
kusano 7d535a
    LZO_UNUSED(c);
kusano 7d535a
    return LZO_E_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_exit(lzo_swd_p s)
kusano 7d535a
{
kusano 7d535a
#if defined(__LZO_CHECKER)
kusano 7d535a
    /* free in reverse order of allocations */
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
    free(s->head2); s->head2 = NULL;
kusano 7d535a
#endif
kusano 7d535a
    free(s->llen3); s->llen3 = NULL;
kusano 7d535a
    free(s->best3); s->best3 = NULL;
kusano 7d535a
    free(s->succ3); s->succ3 = NULL;
kusano 7d535a
    free(s->head3); s->head3 = NULL;
kusano 7d535a
    free(s->b); s->b = NULL;
kusano 7d535a
#else
kusano 7d535a
    LZO_UNUSED(s);
kusano 7d535a
#endif
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define swd_pos2off(s,pos) \
kusano 7d535a
    (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static __lzo_inline
kusano 7d535a
void swd_getbyte(lzo_swd_p s)
kusano 7d535a
{
kusano 7d535a
    int c;
kusano 7d535a
kusano 7d535a
    if ((c = getbyte(*(s->c))) < 0)
kusano 7d535a
    {
kusano 7d535a
        if (s->look > 0)
kusano 7d535a
            --s->look;
kusano 7d535a
#if defined(__LZO_CHECKER)
kusano 7d535a
        /* initialize memory - value doesn't matter */
kusano 7d535a
        s_b(s)[s->ip] = 0;
kusano 7d535a
        if (s->ip < s->f)
kusano 7d535a
            s->b_wrap[s->ip] = 0;
kusano 7d535a
#endif
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        s_b(s)[s->ip] = LZO_BYTE(c);
kusano 7d535a
        if (s->ip < s->f)
kusano 7d535a
            s->b_wrap[s->ip] = LZO_BYTE(c);
kusano 7d535a
    }
kusano 7d535a
    if (++s->ip == s->b_size)
kusano 7d535a
        s->ip = 0;
kusano 7d535a
    if (++s->bp == s->b_size)
kusano 7d535a
        s->bp = 0;
kusano 7d535a
    if (++s->rp == s->b_size)
kusano 7d535a
        s->rp = 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
// remove node from lists
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static __lzo_inline
kusano 7d535a
void swd_remove_node(lzo_swd_p s, lzo_uint node)
kusano 7d535a
{
kusano 7d535a
    if (s->node_count == 0)
kusano 7d535a
    {
kusano 7d535a
        lzo_uint key;
kusano 7d535a
kusano 7d535a
#ifdef LZO_DEBUG
kusano 7d535a
        if (s->first_rp != LZO_UINT_MAX)
kusano 7d535a
        {
kusano 7d535a
            if (node != s->first_rp)
kusano 7d535a
                printf("Remove %5u: %5u %5u %5u %5u  %6u %6u\n",
kusano 7d535a
                        node, s->rp, s->ip, s->bp, s->first_rp,
kusano 7d535a
                        s->ip - node, s->ip - s->bp);
kusano 7d535a
            assert(node == s->first_rp);
kusano 7d535a
            s->first_rp = LZO_UINT_MAX;
kusano 7d535a
        }
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
        key = HEAD3(s_b(s),node);
kusano 7d535a
        assert(s_llen3(s)[key] > 0);
kusano 7d535a
        --s_llen3(s)[key];
kusano 7d535a
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
        key = HEAD2(s_b(s),node);
kusano 7d535a
        assert(s_head2(s)[key] != NIL2);
kusano 7d535a
        if ((lzo_uint) s_head2(s)[key] == node)
kusano 7d535a
            s_head2(s)[key] = NIL2;
kusano 7d535a
#endif
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
        --s->node_count;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_accept(lzo_swd_p s, lzo_uint n)
kusano 7d535a
{
kusano 7d535a
    assert(n <= s->look);
kusano 7d535a
kusano 7d535a
    while (n--)
kusano 7d535a
    {
kusano 7d535a
        lzo_uint key;
kusano 7d535a
kusano 7d535a
        swd_remove_node(s,s->rp);
kusano 7d535a
kusano 7d535a
        /* add bp into HEAD3 */
kusano 7d535a
        key = HEAD3(s_b(s),s->bp);
kusano 7d535a
        s_succ3(s)[s->bp] = s_get_head3(s,key);
kusano 7d535a
        s_head3(s)[key] = SWD_UINT(s->bp);
kusano 7d535a
        s_best3(s)[s->bp] = SWD_UINT(s->f + 1);
kusano 7d535a
        s_llen3(s)[key]++;
kusano 7d535a
        assert(s_llen3(s)[key] <= SWD_N);
kusano 7d535a
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
        /* add bp into HEAD2 */
kusano 7d535a
        key = HEAD2(s_b(s),s->bp);
kusano 7d535a
        s_head2(s)[key] = SWD_UINT(s->bp);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
        swd_getbyte(s);
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_search(lzo_swd_p s, lzo_uint node, lzo_uint cnt)
kusano 7d535a
{
kusano 7d535a
    const lzo_bytep p1;
kusano 7d535a
    const lzo_bytep p2;
kusano 7d535a
    const lzo_bytep px;
kusano 7d535a
    lzo_uint m_len = s->m_len;
kusano 7d535a
    const lzo_bytep b  = s_b(s);
kusano 7d535a
    const lzo_bytep bp = s_b(s) + s->bp;
kusano 7d535a
    const lzo_bytep bx = s_b(s) + s->bp + s->look;
kusano 7d535a
    unsigned char scan_end1;
kusano 7d535a
kusano 7d535a
    assert(s->m_len > 0);
kusano 7d535a
kusano 7d535a
    scan_end1 = bp[m_len - 1];
kusano 7d535a
    for ( ; cnt-- > 0; node = s_succ3(s)[node])
kusano 7d535a
    {
kusano 7d535a
        p1 = bp;
kusano 7d535a
        p2 = b + node;
kusano 7d535a
        px = bx;
kusano 7d535a
kusano 7d535a
        assert(m_len < s->look);
kusano 7d535a
kusano 7d535a
        if (
kusano 7d535a
#if 1
kusano 7d535a
            p2[m_len - 1] == scan_end1 &&
kusano 7d535a
            p2[m_len] == p1[m_len] &&
kusano 7d535a
#endif
kusano 7d535a
            p2[0] == p1[0] &&
kusano 7d535a
            p2[1] == p1[1])
kusano 7d535a
        {
kusano 7d535a
            lzo_uint i;
kusano 7d535a
            assert(lzo_memcmp(bp,&b[node],3) == 0);
kusano 7d535a
kusano 7d535a
#if 0 && defined(LZO_UNALIGNED_OK_4)
kusano 7d535a
            p1 += 3; p2 += 3;
kusano 7d535a
            while (p1 < px && * (const lzo_uint32p) p1 == * (const lzo_uint32p) p2)
kusano 7d535a
                p1 += 4, p2 += 4;
kusano 7d535a
            while (p1 < px && *p1 == *p2)
kusano 7d535a
                p1 += 1, p2 += 1;
kusano 7d535a
#else
kusano 7d535a
            p1 += 2; p2 += 2;
kusano 7d535a
            do {} while (++p1 < px && *p1 == *++p2);
kusano 7d535a
#endif
kusano 7d535a
            i = pd(p1, bp);
kusano 7d535a
kusano 7d535a
#ifdef LZO_DEBUG
kusano 7d535a
            if (lzo_memcmp(bp,&b[node],i) != 0)
kusano 7d535a
                printf("%5ld %5ld %02x%02x %02x%02x\n",
kusano 7d535a
                        (long)s->bp, (long) node,
kusano 7d535a
                        bp[0], bp[1], b[node], b[node+1]);
kusano 7d535a
#endif
kusano 7d535a
            assert(lzo_memcmp(bp,&b[node],i) == 0);
kusano 7d535a
kusano 7d535a
#if defined(SWD_BEST_OFF)
kusano 7d535a
            if (i < SWD_BEST_OFF)
kusano 7d535a
            {
kusano 7d535a
                if (s->best_pos[i] == 0)
kusano 7d535a
                    s->best_pos[i] = node + 1;
kusano 7d535a
            }
kusano 7d535a
#endif
kusano 7d535a
            if (i > m_len)
kusano 7d535a
            {
kusano 7d535a
                s->m_len = m_len = i;
kusano 7d535a
                s->m_pos = node;
kusano 7d535a
                if (m_len == s->look)
kusano 7d535a
                    return;
kusano 7d535a
                if (m_len >= s->nice_length)
kusano 7d535a
                    return;
kusano 7d535a
                if (m_len > (lzo_uint) s_best3(s)[node])
kusano 7d535a
                    return;
kusano 7d535a
                scan_end1 = bp[m_len - 1];
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
lzo_bool swd_search2(lzo_swd_p s)
kusano 7d535a
{
kusano 7d535a
    lzo_uint key;
kusano 7d535a
kusano 7d535a
    assert(s->look >= 2);
kusano 7d535a
    assert(s->m_len > 0);
kusano 7d535a
kusano 7d535a
    key = s_head2(s)[ HEAD2(s_b(s),s->bp) ];
kusano 7d535a
    if (key == NIL2)
kusano 7d535a
        return 0;
kusano 7d535a
#ifdef LZO_DEBUG
kusano 7d535a
    if (lzo_memcmp(&s_b(s)[s->bp],&s_b(s)[key],2) != 0)
kusano 7d535a
        printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
kusano 7d535a
                s_b(s)[s->bp], s_b(s)[s->bp+1], s_b(s)[key], s_b(s)[key+1]);
kusano 7d535a
#endif
kusano 7d535a
    assert(lzo_memcmp(&s_b(s)[s->bp],&s_b(s)[key],2) == 0);
kusano 7d535a
#if defined(SWD_BEST_OFF)
kusano 7d535a
    if (s->best_pos[2] == 0)
kusano 7d535a
        s->best_pos[2] = key + 1;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    if (s->m_len < 2)
kusano 7d535a
    {
kusano 7d535a
        s->m_len = 2;
kusano 7d535a
        s->m_pos = key;
kusano 7d535a
    }
kusano 7d535a
    return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
//
kusano 7d535a
************************************************************************/
kusano 7d535a
kusano 7d535a
static
kusano 7d535a
void swd_findbest(lzo_swd_p s)
kusano 7d535a
{
kusano 7d535a
    lzo_uint key;
kusano 7d535a
    lzo_uint cnt, node;
kusano 7d535a
    lzo_uint len;
kusano 7d535a
kusano 7d535a
    assert(s->m_len > 0);
kusano 7d535a
kusano 7d535a
    /* get current head, add bp into HEAD3 */
kusano 7d535a
    key = HEAD3(s_b(s),s->bp);
kusano 7d535a
    node = s_succ3(s)[s->bp] = s_get_head3(s,key);
kusano 7d535a
    cnt = s_llen3(s)[key]++;
kusano 7d535a
    assert(s_llen3(s)[key] <= SWD_N + SWD_F);
kusano 7d535a
    if (cnt > s->max_chain && s->max_chain > 0)
kusano 7d535a
        cnt = s->max_chain;
kusano 7d535a
    s_head3(s)[key] = SWD_UINT(s->bp);
kusano 7d535a
kusano 7d535a
    s->b_char = s_b(s)[s->bp];
kusano 7d535a
    len = s->m_len;
kusano 7d535a
    if (s->m_len >= s->look)
kusano 7d535a
    {
kusano 7d535a
        if (s->look == 0)
kusano 7d535a
            s->b_char = -1;
kusano 7d535a
        s->m_off = 0;
kusano 7d535a
        s_best3(s)[s->bp] = SWD_UINT(s->f + 1);
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
        if (swd_search2(s))
kusano 7d535a
#endif
kusano 7d535a
            if (s->look >= 3)
kusano 7d535a
                swd_search(s,node,cnt);
kusano 7d535a
        if (s->m_len > len)
kusano 7d535a
            s->m_off = swd_pos2off(s,s->m_pos);
kusano 7d535a
        s_best3(s)[s->bp] = SWD_UINT(s->m_len);
kusano 7d535a
kusano 7d535a
#if defined(SWD_BEST_OFF)
kusano 7d535a
        if (s->use_best_off)
kusano 7d535a
        {
kusano 7d535a
            int i;
kusano 7d535a
            for (i = 2; i < SWD_BEST_OFF; i++)
kusano 7d535a
                if (s->best_pos[i] > 0)
kusano 7d535a
                    s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1);
kusano 7d535a
                else
kusano 7d535a
                    s->best_off[i] = 0;
kusano 7d535a
        }
kusano 7d535a
#endif
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    swd_remove_node(s,s->rp);
kusano 7d535a
kusano 7d535a
#ifdef HEAD2
kusano 7d535a
    /* add bp into HEAD2 */
kusano 7d535a
    key = HEAD2(s_b(s),s->bp);
kusano 7d535a
    s_head2(s)[key] = SWD_UINT(s->bp);
kusano 7d535a
#endif
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#undef HEAD3
kusano 7d535a
#undef HEAD2
kusano 7d535a
#undef s_get_head3
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
vi:ts=4:et
kusano 7d535a
*/
kusano 7d535a