Blame src/lzo1b_cm.ch

Packit Service 5195f2
/* lzo1b_cm.ch -- implementation of the LZO1B compression algorithm
Packit Service 5195f2
Packit Service 5195f2
   This file is part of the LZO real-time data compression library.
Packit Service 5195f2
Packit Service 5195f2
   Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
Packit Service 5195f2
   All Rights Reserved.
Packit Service 5195f2
Packit Service 5195f2
   The LZO library is free software; you can redistribute it and/or
Packit Service 5195f2
   modify it under the terms of the GNU General Public License as
Packit Service 5195f2
   published by the Free Software Foundation; either version 2 of
Packit Service 5195f2
   the License, or (at your option) any later version.
Packit Service 5195f2
Packit Service 5195f2
   The LZO library is distributed in the hope that it will be useful,
Packit Service 5195f2
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 5195f2
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 5195f2
   GNU General Public License for more details.
Packit Service 5195f2
Packit Service 5195f2
   You should have received a copy of the GNU General Public License
Packit Service 5195f2
   along with the LZO library; see the file COPYING.
Packit Service 5195f2
   If not, write to the Free Software Foundation, Inc.,
Packit Service 5195f2
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit Service 5195f2
Packit Service 5195f2
   Markus F.X.J. Oberhumer
Packit Service 5195f2
   <markus@oberhumer.com>
Packit Service 5195f2
   http://www.oberhumer.com/opensource/lzo/
Packit Service 5195f2
 */
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
/* WARNING: this file should *not* be used by applications. It is
Packit Service 5195f2
   part of the implementation of the library and is subject
Packit Service 5195f2
   to change.
Packit Service 5195f2
 */
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
/***********************************************************************
Packit Service 5195f2
// code the match
Packit Service 5195f2
************************************************************************/
Packit Service 5195f2
Packit Service 5195f2
#if (DD_BITS == 0)
Packit Service 5195f2
Packit Service 5195f2
        /* we already matched M2_MIN_LEN bytes,
Packit Service 5195f2
         * m_pos also already advanced M2_MIN_LEN bytes */
Packit Service 5195f2
        ip += M2_MIN_LEN;
Packit Service 5195f2
        assert(m_pos < ip);
Packit Service 5195f2
Packit Service 5195f2
        /* try to match another M2_MAX_LEN + 1 - M2_MIN_LEN bytes
Packit Service 5195f2
         * to see if we get more than a M2 match */
Packit Service 5195f2
#define M2_OR_M3    (MATCH_M2)
Packit Service 5195f2
Packit Service 5195f2
#else /* (DD_BITS == 0) */
Packit Service 5195f2
Packit Service 5195f2
        /* we already matched m_len bytes */
Packit Service 5195f2
        assert(m_len >= M2_MIN_LEN);
Packit Service 5195f2
        ip += m_len;
Packit Service 5195f2
        assert(ip <= in_end);
Packit Service 5195f2
Packit Service 5195f2
#define M2_OR_M3    (m_len <= M2_MAX_LEN)
Packit Service 5195f2
Packit Service 5195f2
#endif /* (DD_BITS == 0) */
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
        if (M2_OR_M3)
Packit Service 5195f2
        {
Packit Service 5195f2
        /* we've found a M2 or M3 match */
Packit Service 5195f2
            assert(ip <= in_end);
Packit Service 5195f2
Packit Service 5195f2
        /* 2a) compute match parameters */
Packit Service 5195f2
#if (DD_BITS == 0)
Packit Service 5195f2
            assert(pd(ip,m_pos) == m_off);
Packit Service 5195f2
            --ip;   /* ran one too far, point back to non-match */
Packit Service 5195f2
            m_len = pd(ip, ii);
Packit Service 5195f2
#endif
Packit Service 5195f2
Packit Service 5195f2
        /* 2a2) verify match parameters */
Packit Service 5195f2
            assert(m_len >= M2_MIN_LEN);
Packit Service 5195f2
            assert(m_len <= M2_MAX_LEN);
Packit Service 5195f2
            assert(m_len <= M3_MAX_LEN);
Packit Service 5195f2
Packit Service 5195f2
            assert(m_off >= M2_MIN_OFFSET);
Packit Service 5195f2
            assert(m_off >= M3_MIN_OFFSET);
Packit Service 5195f2
            assert(m_off <= M3_MAX_OFFSET);
Packit Service 5195f2
            assert(ii-m_off == m_pos_sav);
Packit Service 5195f2
            assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
Packit Service 5195f2
Packit Service 5195f2
        /* 2b) code the match */
Packit Service 5195f2
#if (_M2_MAX_OFFSET != _M3_MAX_OFFSET)
Packit Service 5195f2
            if (m_off <= M2_MAX_OFFSET)
Packit Service 5195f2
            {
Packit Service 5195f2
#else
Packit Service 5195f2
                assert(m_off <= M2_MAX_OFFSET);
Packit Service 5195f2
#endif
Packit Service 5195f2
                m_off -= M2_MIN_OFFSET;
Packit Service 5195f2
                /* code match len + low offset bits */
Packit Service 5195f2
                *op++ = LZO_BYTE(((m_len - (M2_MIN_LEN - 2)) << M2O_BITS) |
Packit Service 5195f2
                                  (m_off & M2O_MASK));
Packit Service 5195f2
                /* code high offset bits */
Packit Service 5195f2
                *op++ = LZO_BYTE(m_off >> M2O_BITS);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m2_matches++);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m2_match[m_len]++);
Packit Service 5195f2
#if (_M2_MAX_OFFSET != _M3_MAX_OFFSET)
Packit Service 5195f2
            }
Packit Service 5195f2
            else
Packit Service 5195f2
            {
Packit Service 5195f2
#if defined(LZO_HAVE_R1)
Packit Service 5195f2
#if (M3_MIN_LEN == M2_MIN_LEN)
Packit Service 5195f2
                r1 = ip_end;    /* invalidate R1 pointer */
Packit Service 5195f2
#endif
Packit Service 5195f2
#endif
Packit Service 5195f2
                assert(m_len >= M3_MIN_LEN);
Packit Service 5195f2
                m_off -= M3_MIN_OFFSET - M3_EOF_OFFSET;
Packit Service 5195f2
                /* code match len */
Packit Service 5195f2
                *op++ = LZO_BYTE(M3_MARKER | (m_len - (M3_MIN_LEN - 1)));
Packit Service 5195f2
                /* code low offset bits */
Packit Service 5195f2
                *op++ = LZO_BYTE(m_off & M3O_MASK);
Packit Service 5195f2
                /* code high offset bits */
Packit Service 5195f2
                *op++ = LZO_BYTE(m_off >> M3O_BITS);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m3_matches++);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m3_match[m_len]++);
Packit Service 5195f2
#if defined(LZO_HAVE_M3)
Packit Service 5195f2
                m3 = op;        /* set M3 pointer */
Packit Service 5195f2
#endif
Packit Service 5195f2
            }
Packit Service 5195f2
#endif /* (_M2_MAX_OFFSET != _M3_MAX_OFFSET) */
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
            if (ip >= ip_end)
Packit Service 5195f2
            {
Packit Service 5195f2
                ii = ip;
Packit Service 5195f2
                break;
Packit Service 5195f2
            }
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
        /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
Packit Service 5195f2
Packit Service 5195f2
#if (CLEVEL == 9) || (CLEVEL >= 7 && M2L_BITS <= 4) || (CLEVEL >= 5 && M2L_BITS <= 3)
Packit Service 5195f2
        /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
Packit Service 5195f2
            ++ii;
Packit Service 5195f2
            do {
Packit Service 5195f2
                DVAL_NEXT(dv,ii);
Packit Service 5195f2
#if 0
Packit Service 5195f2
                UPDATE_D(dict,drun,dv,ii,in);
Packit Service 5195f2
#else
Packit Service 5195f2
                dict[ DINDEX(dv,ii) ] = DENTRY(ii,in);
Packit Service 5195f2
#endif
Packit Service 5195f2
                MI
Packit Service 5195f2
            } while (++ii < ip);
Packit Service 5195f2
            DVAL_NEXT(dv,ii);
Packit Service 5195f2
            assert(ii == ip);
Packit Service 5195f2
            DVAL_ASSERT(dv,ip);
Packit Service 5195f2
#elif (CLEVEL >= 3)
Packit Service 5195f2
            SI   DI DI   XI
Packit Service 5195f2
#elif (CLEVEL >= 2)
Packit Service 5195f2
            SI   DI      XI
Packit Service 5195f2
#else
Packit Service 5195f2
                         XI
Packit Service 5195f2
#endif
Packit Service 5195f2
        }
Packit Service 5195f2
Packit Service 5195f2
        else
Packit Service 5195f2
Packit Service 5195f2
        {
Packit Service 5195f2
        /* we've found a M3 or M4 match - see how far we can still go */
Packit Service 5195f2
            assert(ip <= in_end);
Packit Service 5195f2
            assert(lzo_memcmp(m_pos_sav,ii,(lzo_uint)(ip-ii)) == 0);
Packit Service 5195f2
Packit Service 5195f2
        /* 2a) compute match parameters */
Packit Service 5195f2
#if !defined(MATCH_IP_END)
Packit Service 5195f2
            assert(ii == ip - (M2_MAX_LEN + 1));
Packit Service 5195f2
#if (DD_BITS > 0)
Packit Service 5195f2
            assert(m_len == (lzo_uint)(ip-ii));
Packit Service 5195f2
            m_pos = ip - m_off;
Packit Service 5195f2
            assert(m_pos == m_pos_sav + m_len);
Packit Service 5195f2
#endif
Packit Service 5195f2
            {
Packit Service 5195f2
                const lzo_bytep end;
Packit Service 5195f2
                end = in_end;
Packit Service 5195f2
                while (ip < end  &&  *m_pos == *ip)
Packit Service 5195f2
                    m_pos++, ip++;
Packit Service 5195f2
                assert(ip <= in_end);
Packit Service 5195f2
                m_len = pd(ip, ii);
Packit Service 5195f2
            }
Packit Service 5195f2
            assert(pd(ip,m_pos) == m_off);
Packit Service 5195f2
#endif
Packit Service 5195f2
Packit Service 5195f2
        /* 2a2) verify match parameters */
Packit Service 5195f2
            assert(m_len >= M3_MIN_LEN);
Packit Service 5195f2
Packit Service 5195f2
            assert(m_off >= M3_MIN_OFFSET);
Packit Service 5195f2
            assert(m_off >= M4_MIN_OFFSET);
Packit Service 5195f2
            assert(m_off <= M3_MAX_OFFSET);
Packit Service 5195f2
            assert(m_off <= M4_MAX_OFFSET);
Packit Service 5195f2
            assert(ii-m_off == m_pos_sav);
Packit Service 5195f2
            assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
Packit Service 5195f2
Packit Service 5195f2
        /* 2b) code the match */
Packit Service 5195f2
            if (m_len <= M3_MAX_LEN)
Packit Service 5195f2
            {
Packit Service 5195f2
                /* code match len */
Packit Service 5195f2
                *op++ = LZO_BYTE(M3_MARKER | (m_len - (M3_MIN_LEN - 1)));
Packit Service 5195f2
                LZO_STATS(lzo_stats->m3_matches++);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m3_match[m_len]++);
Packit Service 5195f2
            }
Packit Service 5195f2
            else
Packit Service 5195f2
            {
Packit Service 5195f2
                assert(m_len >= M4_MIN_LEN);
Packit Service 5195f2
                /* code M4 match len flag */
Packit Service 5195f2
                *op++ = M4_MARKER;
Packit Service 5195f2
                /* code match len */
Packit Service 5195f2
                m_len -= M4_MIN_LEN - 1;
Packit Service 5195f2
                while (m_len > 255)
Packit Service 5195f2
                {
Packit Service 5195f2
                    m_len -= 255;
Packit Service 5195f2
                    *op++ = 0;
Packit Service 5195f2
                }
Packit Service 5195f2
                assert(m_len > 0);
Packit Service 5195f2
                *op++ = LZO_BYTE(m_len);
Packit Service 5195f2
                LZO_STATS(lzo_stats->m4_matches++);
Packit Service 5195f2
            }
Packit Service 5195f2
Packit Service 5195f2
            m_off -= M3_MIN_OFFSET - M3_EOF_OFFSET;
Packit Service 5195f2
            /* code low offset bits */
Packit Service 5195f2
            *op++ = LZO_BYTE(m_off & M3O_MASK);
Packit Service 5195f2
            /* code high offset bits */
Packit Service 5195f2
            *op++ = LZO_BYTE(m_off >> M3O_BITS);
Packit Service 5195f2
Packit Service 5195f2
#if defined(LZO_HAVE_M3)
Packit Service 5195f2
            m3 = op;        /* set M3 pointer */
Packit Service 5195f2
#endif
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
            if (ip >= ip_end)
Packit Service 5195f2
            {
Packit Service 5195f2
                ii = ip;
Packit Service 5195f2
                break;
Packit Service 5195f2
            }
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
        /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
Packit Service 5195f2
#if (CLEVEL == 9)
Packit Service 5195f2
        /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
Packit Service 5195f2
        /* This is not recommended because it can be slow. */
Packit Service 5195f2
            ++ii;
Packit Service 5195f2
            do {
Packit Service 5195f2
                DVAL_NEXT(dv,ii);
Packit Service 5195f2
#if 0
Packit Service 5195f2
                UPDATE_D(dict,drun,dv,ii,in);
Packit Service 5195f2
#else
Packit Service 5195f2
                dict[ DINDEX(dv,ii) ] = DENTRY(ii,in);
Packit Service 5195f2
#endif
Packit Service 5195f2
                MI
Packit Service 5195f2
            } while (++ii < ip);
Packit Service 5195f2
            DVAL_NEXT(dv,ii);
Packit Service 5195f2
            assert(ii == ip);
Packit Service 5195f2
            DVAL_ASSERT(dv,ip);
Packit Service 5195f2
#elif (CLEVEL >= 8)
Packit Service 5195f2
            SI   DI DI DI DI DI DI DI DI   XI
Packit Service 5195f2
#elif (CLEVEL >= 7)
Packit Service 5195f2
            SI   DI DI DI DI DI DI DI      XI
Packit Service 5195f2
#elif (CLEVEL >= 6)
Packit Service 5195f2
            SI   DI DI DI DI DI DI         XI
Packit Service 5195f2
#elif (CLEVEL >= 5)
Packit Service 5195f2
            SI   DI DI DI DI               XI
Packit Service 5195f2
#elif (CLEVEL >= 4)
Packit Service 5195f2
            SI   DI DI DI                  XI
Packit Service 5195f2
#elif (CLEVEL >= 3)
Packit Service 5195f2
            SI   DI DI                     XI
Packit Service 5195f2
#elif (CLEVEL >= 2)
Packit Service 5195f2
            SI   DI                        XI
Packit Service 5195f2
#else
Packit Service 5195f2
                                           XI
Packit Service 5195f2
#endif
Packit Service 5195f2
        }
Packit Service 5195f2
Packit Service 5195f2
        /* ii now points to the start of the next literal run */
Packit Service 5195f2
        assert(ii == ip);
Packit Service 5195f2
Packit Service 5195f2
Packit Service 5195f2
/*
Packit Service 5195f2
vi:ts=4:et
Packit Service 5195f2
*/