summaryrefslogtreecommitdiff
path: root/src/lzo1a_cm.ch
diff options
context:
space:
mode:
Diffstat (limited to 'src/lzo1a_cm.ch')
-rw-r--r--src/lzo1a_cm.ch245
1 files changed, 245 insertions, 0 deletions
diff --git a/src/lzo1a_cm.ch b/src/lzo1a_cm.ch
new file mode 100644
index 0000000..d86b891
--- /dev/null
+++ b/src/lzo1a_cm.ch
@@ -0,0 +1,245 @@
+/* lzo1a_cm.ch -- implementation of the LZO1A compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+
+/***********************************************************************
+// code the match in LZO1 compatible format
+************************************************************************/
+
+#define THRESHOLD (M2_MIN_LEN - 1)
+#define MSIZE LZO_SIZE(M2L_BITS)
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if (DD_BITS == 0)
+
+ /* we already matched M2_MIN_LEN bytes,
+ * m_pos also already advanced M2_MIN_LEN bytes */
+ ip += M2_MIN_LEN;
+ assert(m_pos < ip);
+
+ /* try to match another M2_MAX_LEN + 1 - M2_MIN_LEN bytes
+ * to see if we get more than a M2 match */
+#define M2_OR_M3 (MATCH_M2)
+
+#else /* (DD_BITS == 0) */
+
+ /* we already matched m_len bytes */
+ assert(m_len >= M2_MIN_LEN);
+ ip += m_len;
+ assert(ip <= in_end);
+
+#define M2_OR_M3 (m_len <= M2_MAX_LEN)
+
+#endif /* (DD_BITS == 0) */
+
+
+ if (M2_OR_M3)
+ {
+ /* we've found a short match */
+ assert(ip <= in_end);
+
+ /* 2a) compute match parameters */
+#if (DD_BITS == 0)
+ assert(pd(ip,m_pos) == m_off);
+ --ip; /* ran one too far, point back to non-match */
+ m_len = ip - ii;
+#endif
+ assert(m_len >= M2_MIN_LEN);
+ assert(m_len <= M2_MAX_LEN);
+
+ assert(m_off >= M2_MIN_OFFSET);
+ assert(m_off <= M2_MAX_OFFSET);
+ assert(ii-m_off == m_pos_sav);
+ assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
+
+ /* 2b) code the match */
+ m_off -= M2_MIN_OFFSET;
+ /* code short match len + low offset bits */
+ *op++ = LZO_BYTE(((m_len - THRESHOLD) << M2O_BITS) |
+ (m_off & M2O_MASK));
+ /* code high offset bits */
+ *op++ = LZO_BYTE(m_off >> M2O_BITS);
+
+
+ if (ip >= ip_end)
+ {
+ ii = ip;
+ break;
+ }
+
+
+ /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
+
+#if (CLEVEL == 9) || (CLEVEL >= 7 && M2L_BITS <= 4) || (CLEVEL >= 5 && M2L_BITS <= 3)
+ /* Insert the whole match (ii+1)..(ip-1) into dictionary. */
+ ++ii;
+ do {
+ DVAL_NEXT(dv,ii);
+#if 0
+ UPDATE_D(dict,drun,dv,ii,in);
+#else
+ dict[ DINDEX(dv,ii) ] = DENTRY(ii,in);
+#endif
+ MI
+ } while (++ii < ip);
+ DVAL_NEXT(dv,ii);
+ assert(ii == ip);
+ DVAL_ASSERT(dv,ip);
+#elif (CLEVEL >= 3)
+ SI DI DI XI
+#elif (CLEVEL >= 2)
+ SI DI XI
+#else
+ XI
+#endif
+ }
+
+ else
+
+ {
+ /* we've found a long match - see how far we can still go */
+ const lzo_bytep end;
+
+ assert(ip <= in_end);
+ assert(ii == ip - (M2_MAX_LEN + 1));
+ assert(lzo_memcmp(m_pos_sav,ii,(lzo_uint)(ip-ii)) == 0);
+
+#if (DD_BITS > 0)
+ assert(m_len == (lzo_uint)(ip-ii));
+ m_pos = ip - m_off;
+ assert(m_pos == m_pos_sav + m_len);
+#endif
+
+ if (pd(in_end,ip) <= (M3_MAX_LEN - M3_MIN_LEN))
+ end = in_end;
+ else
+ {
+ end = ip + (M3_MAX_LEN - M3_MIN_LEN);
+ assert(end < in_end);
+ }
+
+ while (ip < end && *m_pos == *ip)
+ m_pos++, ip++;
+ assert(ip <= in_end);
+
+ /* 2a) compute match parameters */
+ m_len = pd(ip, ii);
+ assert(m_len >= M3_MIN_LEN);
+ assert(m_len <= M3_MAX_LEN);
+
+ assert(m_off >= M3_MIN_OFFSET);
+ assert(m_off <= M3_MAX_OFFSET);
+ assert(ii-m_off == m_pos_sav);
+ assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
+ assert(pd(ip,m_pos) == m_off);
+
+ /* 2b) code the match */
+ m_off -= M3_MIN_OFFSET - M3_EOF_OFFSET;
+ /* code long match flag + low offset bits */
+ *op++ = LZO_BYTE(((MSIZE - 1) << M3O_BITS) | (m_off & M3O_MASK));
+ /* code high offset bits */
+ *op++ = LZO_BYTE(m_off >> M3O_BITS);
+ /* code match len */
+ *op++ = LZO_BYTE(m_len - M3_MIN_LEN);
+
+
+ if (ip >= ip_end)
+ {
+ ii = ip;
+ break;
+ }
+
+
+ /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
+#if (CLEVEL == 9)
+ /* Insert the whole match (ii+1)..(ip-1) into dictionary. */
+ /* This is not recommended because it can be slow. */
+ ++ii;
+ do {
+ DVAL_NEXT(dv,ii);
+#if 0
+ UPDATE_D(dict,drun,dv,ii,in);
+#else
+ dict[ DINDEX(dv,ii) ] = DENTRY(ii,in);
+#endif
+ MI
+ } while (++ii < ip);
+ DVAL_NEXT(dv,ii);
+ assert(ii == ip);
+ DVAL_ASSERT(dv,ip);
+#elif (CLEVEL >= 8)
+ SI DI DI DI DI DI DI DI DI XI
+#elif (CLEVEL >= 7)
+ SI DI DI DI DI DI DI DI XI
+#elif (CLEVEL >= 6)
+ SI DI DI DI DI DI DI XI
+#elif (CLEVEL >= 5)
+ SI DI DI DI DI XI
+#elif (CLEVEL >= 4)
+ SI DI DI DI XI
+#elif (CLEVEL >= 3)
+ SI DI DI XI
+#elif (CLEVEL >= 2)
+ SI DI XI
+#else
+ XI
+#endif
+ }
+
+ /* ii now points to the start of the next literal run */
+ assert(ii == ip);
+
+
+/*
+vi:ts=4:et
+*/