Maemo patchset 20101501+0m5
[h-e-n] / lib / lzo / lzo1x_9x.c
diff --git a/lib/lzo/lzo1x_9x.c b/lib/lzo/lzo1x_9x.c
new file mode 100644 (file)
index 0000000..8b50d25
--- /dev/null
@@ -0,0 +1,1272 @@
+/* lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
+
+   This file is part of the LZO real-time data compression library.
+
+   Copyright (C) 1996-2002 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 version 2 of the GNU General Public
+   License as published by the Free Software Foundation.
+
+   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.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Markus F.X.J. Oberhumer
+   <markus@oberhumer.com>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+typedef unsigned int lzo_uint32;
+typedef int lzo_int32;
+typedef unsigned int lzo_uint;
+typedef int lzo_int;
+typedef int lzo_bool;
+
+typedef void ( *lzo_progress_callback_t) (unsigned, unsigned);
+
+typedef struct
+{
+ int init;
+
+ lzo_uint look;
+
+ lzo_uint m_len;
+ lzo_uint m_off;
+
+ lzo_uint last_m_len;
+ lzo_uint last_m_off;
+
+ const unsigned char *bp;
+ const unsigned char *ip;
+ const unsigned char *in;
+ const unsigned char *in_end;
+ unsigned char *out;
+
+ lzo_progress_callback_t cb;
+
+ lzo_uint textsize;
+ lzo_uint codesize;
+ lzo_uint printcount;
+
+
+ unsigned long lit_bytes;
+ unsigned long match_bytes;
+ unsigned long rep_bytes;
+ unsigned long lazy;
+
+ lzo_uint r1_lit;
+ lzo_uint r1_m_len;
+
+ unsigned long m1a_m, m1b_m, m2_m, m3_m, m4_m;
+ unsigned long lit1_r, lit2_r, lit3_r;
+}
+lzo1x_999_t;
+
+typedef unsigned short swd_uint;
+
+typedef struct
+{
+ lzo_uint n;
+ lzo_uint f;
+ lzo_uint threshold;
+
+ lzo_uint max_chain;
+ lzo_uint nice_length;
+ lzo_bool use_best_off;
+ lzo_uint lazy_insert;
+
+ lzo_uint m_len;
+ lzo_uint m_off;
+ lzo_uint look;
+ int b_char;
+
+ lzo_uint best_off[ (((8) >= (33) ? ((8) >= (9) ? (8) : (9)) : ((33) >= (9) ? (33) : (9))) + 1) ];
+
+ lzo1x_999_t *c;
+ lzo_uint m_pos;
+
+ lzo_uint best_pos[ (((8) >= (33) ? ((8) >= (9) ? (8) : (9)) : ((33) >= (9) ? (33) : (9))) + 1) ];
+
+ const unsigned char *dict;
+ const unsigned char *dict_end;
+ lzo_uint dict_len;
+
+ lzo_uint ip;
+ lzo_uint bp;
+ lzo_uint rp;
+ lzo_uint b_size;
+
+ unsigned char *b_wrap;
+
+ lzo_uint node_count;
+ lzo_uint first_rp;
+
+ unsigned char b [ 0xbfff + 2048 + 2048 ];
+ swd_uint head3 [ 16384 ];
+ swd_uint succ3 [ 0xbfff + 2048 ];
+ swd_uint best3 [ 0xbfff + 2048 ];
+ swd_uint llen3 [ 16384 ];
+
+ swd_uint head2 [ 65536L ];
+}
+lzo1x_999_swd_t;
+
+static
+void swd_initdict(lzo1x_999_swd_t *s, const unsigned char *dict, lzo_uint dict_len)
+{
+ s->dict = s->dict_end = ((void *)0);
+ s->dict_len = 0;
+
+ if (!dict || dict_len <= 0)
+  return;
+ if (dict_len > s->n)
+ {
+  dict += dict_len - s->n;
+  dict_len = s->n;
+ }
+
+ s->dict = dict;
+ s->dict_len = dict_len;
+ s->dict_end = dict + dict_len;
+ memcpy(s->b,dict,dict_len);
+ s->ip = dict_len;
+}
+
+
+static
+void swd_insertdict(lzo1x_999_swd_t *s, lzo_uint node, lzo_uint len)
+{
+ lzo_uint key;
+
+ s->node_count = s->n - len;
+ s->first_rp = node;
+
+ while (len-- > 0)
+ {
+  key = (((0x9f5f*(((((lzo_uint32)s->b[node]<<5)^s->b[node+1])<<5)^s->b[node+2]))>>5) & (16384 -1));
+  s->succ3[node] = s->head3[key];
+  s->head3[key] = ((swd_uint)(node));
+  s->best3[node] = ((swd_uint)(s->f + 1));
+  s->llen3[key]++;
+  ((void) (0));
+
+
+  key = (* (unsigned short *) &(s->b[node]));
+  s->head2[key] = ((swd_uint)(node));
+
+
+  node++;
+ }
+}
+
+
+
+
+
+
+static
+int swd_init(lzo1x_999_swd_t *s, const unsigned char *dict, lzo_uint dict_len)
+{
+ lzo_uint i = 0;
+ int c = 0;
+
+ s->n = 0xbfff;
+ s->f = 2048;
+ s->threshold = 1;
+
+
+ s->max_chain = 2048;
+ s->nice_length = 2048;
+ s->use_best_off = 0;
+ s->lazy_insert = 0;
+
+ s->b_size = s->n + s->f;
+ if (2 * s->f >= s->n || s->b_size + s->f >= (32767 * 2 + 1))
+  return (-1);
+ s->b_wrap = s->b + s->b_size;
+ s->node_count = s->n;
+
+ memset(s->llen3, 0, sizeof(s->llen3[0]) * 16384);
+
+
+ memset(s->head2, 0xff, sizeof(s->head2[0]) * 65536L);
+ ((void) (0));
+
+
+
+
+
+
+ s->ip = 0;
+ swd_initdict(s,dict,dict_len);
+ s->bp = s->ip;
+ s->first_rp = s->ip;
+
+ ((void) (0));
+
+ s->look = (lzo_uint) (s->c->in_end - s->c->ip);
+ if (s->look > 0)
+ {
+  if (s->look > s->f)
+   s->look = s->f;
+  memcpy(&s->b[s->ip],s->c->ip,s->look);
+  s->c->ip += s->look;
+  s->ip += s->look;
+ }
+
+ if (s->ip == s->b_size)
+  s->ip = 0;
+
+ if (s->look >= 2 && s->dict_len > 0)
+  swd_insertdict(s,0,s->dict_len);
+
+ s->rp = s->first_rp;
+ if (s->rp >= s->node_count)
+  s->rp -= s->node_count;
+ else
+  s->rp += s->b_size - s->node_count;
+
+ ((void)&i);
+ ((void)&c);
+ return 0;
+}
+
+
+static
+void swd_exit(lzo1x_999_swd_t *s)
+{
+
+ ((void)&s);
+
+}
+
+static __inline__
+void swd_getbyte(lzo1x_999_swd_t *s)
+{
+ int c;
+
+ if ((c = ((*(s->c)).ip < (*(s->c)).in_end ? *((*(s->c)).ip)++ : (-1))) < 0)
+ {
+  if (s->look > 0)
+   --s->look;
+
+
+
+
+
+
+ }
+ else
+ {
+  s->b[s->ip] = ((unsigned char) ((c) & 0xff));
+  if (s->ip < s->f)
+   s->b_wrap[s->ip] = ((unsigned char) ((c) & 0xff));
+ }
+ if (++s->ip == s->b_size)
+  s->ip = 0;
+ if (++s->bp == s->b_size)
+  s->bp = 0;
+ if (++s->rp == s->b_size)
+  s->rp = 0;
+}
+
+
+
+
+
+
+static __inline__
+void swd_remove_node(lzo1x_999_swd_t *s, lzo_uint node)
+{
+ if (s->node_count == 0)
+ {
+  lzo_uint key;
+
+  key = (((0x9f5f*(((((lzo_uint32)s->b[node]<<5)^s->b[node+1])<<5)^s->b[node+2]))>>5) & (16384 -1));
+  ((void) (0));
+  --s->llen3[key];
+
+
+  key = (* (unsigned short *) &(s->b[node]));
+  ((void) (0));
+  if ((lzo_uint) s->head2[key] == node)
+   s->head2[key] = (32767 * 2 + 1);
+
+ }
+ else
+  --s->node_count;
+}
+
+
+
+
+
+
+static
+void swd_accept(lzo1x_999_swd_t *s, lzo_uint n)
+{
+ ((void) (0));
+
+ while (n--)
+ {
+  lzo_uint key;
+
+  swd_remove_node(s,s->rp);
+
+
+  key = (((0x9f5f*(((((lzo_uint32)s->b[s->bp]<<5)^s->b[s->bp+1])<<5)^s->b[s->bp+2]))>>5) & (16384 -1));
+  s->succ3[s->bp] = s->head3[key];
+  s->head3[key] = ((swd_uint)(s->bp));
+  s->best3[s->bp] = ((swd_uint)(s->f + 1));
+  s->llen3[key]++;
+  ((void) (0));
+
+
+
+  key = (* (unsigned short *) &(s->b[s->bp]));
+  s->head2[key] = ((swd_uint)(s->bp));
+
+
+  swd_getbyte(s);
+ }
+}
+
+
+
+
+
+
+static
+void swd_search(lzo1x_999_swd_t *s, lzo_uint node, lzo_uint cnt)
+{
+
+
+
+
+
+ const unsigned char *p1;
+ const unsigned char *p2;
+ const unsigned char *px;
+
+ lzo_uint m_len = s->m_len;
+ const unsigned char * b = s->b;
+ const unsigned char * bp = s->b + s->bp;
+ const unsigned char * bx = s->b + s->bp + s->look;
+ unsigned char scan_end1;
+
+ ((void) (0));
+
+ scan_end1 = bp[m_len - 1];
+ for ( ; cnt-- > 0; node = s->succ3[node])
+ {
+  p1 = bp;
+  p2 = b + node;
+  px = bx;
+
+  ((void) (0));
+
+  if (
+
+      p2[m_len - 1] == scan_end1 &&
+      p2[m_len] == p1[m_len] &&
+
+      p2[0] == p1[0] &&
+      p2[1] == p1[1])
+  {
+   lzo_uint i;
+   ((void) (0));
+
+   p1 += 2; p2 += 2;
+   do {} while (++p1 < px && *p1 == *++p2);
+
+   i = p1 - bp;
+
+
+
+
+
+
+
+   ((void) (0));
+
+
+   if (i < (((8) >= (33) ? ((8) >= (9) ? (8) : (9)) : ((33) >= (9) ? (33) : (9))) + 1))
+   {
+    if (s->best_pos[i] == 0)
+     s->best_pos[i] = node + 1;
+   }
+
+   if (i > m_len)
+   {
+    s->m_len = m_len = i;
+    s->m_pos = node;
+    if (m_len == s->look)
+     return;
+    if (m_len >= s->nice_length)
+     return;
+    if (m_len > (lzo_uint) s->best3[node])
+     return;
+    scan_end1 = bp[m_len - 1];
+   }
+  }
+ }
+}
+
+static
+lzo_bool swd_search2(lzo1x_999_swd_t *s)
+{
+ lzo_uint key;
+
+ ((void) (0));
+ ((void) (0));
+
+ key = s->head2[ (* (unsigned short *) &(s->b[s->bp])) ];
+ if (key == (32767 * 2 + 1))
+  return 0;
+
+
+
+
+
+ ((void) (0));
+
+ if (s->best_pos[2] == 0)
+  s->best_pos[2] = key + 1;
+
+
+ if (s->m_len < 2)
+ {
+  s->m_len = 2;
+  s->m_pos = key;
+ }
+ return 1;
+}
+
+static
+void swd_findbest(lzo1x_999_swd_t *s)
+{
+ lzo_uint key;
+ lzo_uint cnt, node;
+ lzo_uint len;
+
+ ((void) (0));
+
+
+ key = (((0x9f5f*(((((lzo_uint32)s->b[s->bp]<<5)^s->b[s->bp+1])<<5)^s->b[s->bp+2]))>>5) & (16384 -1));
+ node = s->succ3[s->bp] = s->head3[key];
+ cnt = s->llen3[key]++;
+ ((void) (0));
+ if (cnt > s->max_chain && s->max_chain > 0)
+  cnt = s->max_chain;
+ s->head3[key] = ((swd_uint)(s->bp));
+
+ s->b_char = s->b[s->bp];
+ len = s->m_len;
+ if (s->m_len >= s->look)
+ {
+  if (s->look == 0)
+   s->b_char = -1;
+  s->m_off = 0;
+  s->best3[s->bp] = ((swd_uint)(s->f + 1));
+ }
+ else
+ {
+
+  if (swd_search2(s))
+
+   if (s->look >= 3)
+    swd_search(s,node,cnt);
+  if (s->m_len > len)
+   s->m_off = (s->bp > (s->m_pos) ? s->bp - (s->m_pos) : s->b_size - ((s->m_pos) - s->bp));
+  s->best3[s->bp] = ((swd_uint)(s->m_len));
+
+
+  if (s->use_best_off)
+  {
+   int i;
+   for (i = 2; i < (((8) >= (33) ? ((8) >= (9) ? (8) : (9)) : ((33) >= (9) ? (33) : (9))) + 1); i++)
+    if (s->best_pos[i] > 0)
+     s->best_off[i] = (s->bp > (s->best_pos[i]-1) ? s->bp - (s->best_pos[i]-1) : s->b_size - ((s->best_pos[i]-1) - s->bp));
+    else
+     s->best_off[i] = 0;
+  }
+
+ }
+
+ swd_remove_node(s,s->rp);
+
+
+
+ key = (* (unsigned short *) &(s->b[s->bp]));
+ s->head2[key] = ((swd_uint)(s->bp));
+
+}
+
+
+
+
+
+
+
+
+static int
+init_match ( lzo1x_999_t *c, lzo1x_999_swd_t *s,
+    const unsigned char *dict, lzo_uint dict_len,
+    lzo_uint32 flags )
+{
+ int r;
+
+ ((void) (0));
+ c->init = 1;
+
+ s->c = c;
+
+ c->last_m_len = c->last_m_off = 0;
+
+ c->textsize = c->codesize = c->printcount = 0;
+ c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
+ c->lazy = 0;
+
+ r = swd_init(s,dict,dict_len);
+ if (r != 0)
+  return r;
+
+ s->use_best_off = (flags & 1) ? 1 : 0;
+ return r;
+}
+
+
+
+
+
+
+static int
+find_match ( lzo1x_999_t *c, lzo1x_999_swd_t *s,
+    lzo_uint this_len, lzo_uint skip )
+{
+ ((void) (0));
+
+ if (skip > 0)
+ {
+  ((void) (0));
+  swd_accept(s, this_len - skip);
+  c->textsize += this_len - skip + 1;
+ }
+ else
+ {
+  ((void) (0));
+  c->textsize += this_len - skip;
+ }
+
+ s->m_len = 1;
+ s->m_len = 1;
+
+ if (s->use_best_off)
+  memset(s->best_pos,0,sizeof(s->best_pos));
+
+ swd_findbest(s);
+ c->m_len = s->m_len;
+ c->m_off = s->m_off;
+
+ swd_getbyte(s);
+
+ if (s->b_char < 0)
+ {
+  c->look = 0;
+  c->m_len = 0;
+  swd_exit(s);
+ }
+ else
+ {
+  c->look = s->look + 1;
+ }
+ c->bp = c->ip - c->look;
+
+ if (c->cb && c->textsize > c->printcount)
+ {
+  (*c->cb)(c->textsize,c->codesize);
+  c->printcount += 1024;
+ }
+
+ return 0;
+}
+
+
+
+
+static int
+lzo1x_999_compress_internal ( const unsigned char *in , lzo_uint in_len,
+                                    unsigned char *out, lzo_uint * out_len,
+                                    void * wrkmem,
+                              const unsigned char *dict, lzo_uint dict_len,
+                                    lzo_progress_callback_t cb,
+                                    int try_lazy,
+                                    lzo_uint good_length,
+                                    lzo_uint max_lazy,
+                                    lzo_uint nice_length,
+                                    lzo_uint max_chain,
+                                    lzo_uint32 flags );
+
+
+
+
+
+
+static unsigned char *
+code_match ( lzo1x_999_t *c, unsigned char *op, lzo_uint m_len, lzo_uint m_off )
+{
+ lzo_uint x_len = m_len;
+ lzo_uint x_off = m_off;
+
+ c->match_bytes += m_len;
+
+ ((void) (0));
+ if (m_len == 2)
+ {
+  ((void) (0));
+  ((void) (0)); ((void) (0));
+  m_off -= 1;
+
+
+
+
+  *op++ = ((unsigned char) ((0 | ((m_off & 3) << 2)) & 0xff));
+  *op++ = ((unsigned char) ((m_off >> 2) & 0xff));
+
+  c->m1a_m++;
+ }
+
+
+
+ else if (m_len <= 8 && m_off <= 0x0800)
+
+ {
+  ((void) (0));
+
+  m_off -= 1;
+  *op++ = ((unsigned char) ((((m_len - 1) << 5) | ((m_off & 7) << 2)) & 0xff));
+  *op++ = ((unsigned char) ((m_off >> 3) & 0xff));
+  ((void) (0));
+
+  c->m2_m++;
+ }
+ else if (m_len == 3 && m_off <= (0x0400 + 0x0800) && c->r1_lit >= 4)
+ {
+  ((void) (0));
+  ((void) (0));
+  m_off -= 1 + 0x0800;
+
+
+
+
+  *op++ = ((unsigned char) ((0 | ((m_off & 3) << 2)) & 0xff));
+  *op++ = ((unsigned char) ((m_off >> 2) & 0xff));
+
+  c->m1b_m++;
+ }
+ else if (m_off <= 0x4000)
+ {
+  ((void) (0));
+  m_off -= 1;
+  if (m_len <= 33)
+   *op++ = ((unsigned char) ((32 | (m_len - 2)) & 0xff));
+  else
+  {
+   m_len -= 33;
+   *op++ = 32 | 0;
+   while (m_len > 255)
+   {
+    m_len -= 255;
+    *op++ = 0;
+   }
+   ((void) (0));
+   *op++ = ((unsigned char) ((m_len) & 0xff));
+  }
+
+
+
+
+  *op++ = ((unsigned char) ((m_off << 2) & 0xff));
+  *op++ = ((unsigned char) ((m_off >> 6) & 0xff));
+
+  c->m3_m++;
+ }
+ else
+ {
+  lzo_uint k;
+
+  ((void) (0));
+  ((void) (0)); ((void) (0));
+  m_off -= 0x4000;
+  k = (m_off & 0x4000) >> 11;
+  if (m_len <= 9)
+   *op++ = ((unsigned char) ((16 | k | (m_len - 2)) & 0xff));
+  else
+  {
+   m_len -= 9;
+   *op++ = ((unsigned char) ((16 | k | 0) & 0xff));
+   while (m_len > 255)
+   {
+    m_len -= 255;
+    *op++ = 0;
+   }
+   ((void) (0));
+   *op++ = ((unsigned char) ((m_len) & 0xff));
+  }
+
+
+
+
+  *op++ = ((unsigned char) ((m_off << 2) & 0xff));
+  *op++ = ((unsigned char) ((m_off >> 6) & 0xff));
+
+  c->m4_m++;
+ }
+
+ c->last_m_len = x_len;
+ c->last_m_off = x_off;
+ return op;
+}
+
+
+static unsigned char *
+STORE_RUN ( lzo1x_999_t *c, unsigned char *op, const unsigned char *ii, lzo_uint t )
+{
+ c->lit_bytes += t;
+
+ if (op == c->out && t <= 238)
+ {
+  *op++ = ((unsigned char) ((17 + t) & 0xff));
+ }
+ else if (t <= 3)
+ {
+
+
+
+  op[-2] |= ((unsigned char) ((t) & 0xff));
+
+  c->lit1_r++;
+ }
+ else if (t <= 18)
+ {
+  *op++ = ((unsigned char) ((t - 3) & 0xff));
+  c->lit2_r++;
+ }
+ else
+ {
+  lzo_uint tt = t - 18;
+
+  *op++ = 0;
+  while (tt > 255)
+  {
+   tt -= 255;
+   *op++ = 0;
+  }
+  ((void) (0));
+  *op++ = ((unsigned char) ((tt) & 0xff));
+  c->lit3_r++;
+ }
+ do *op++ = *ii++; while (--t > 0);
+
+ return op;
+}
+
+
+static unsigned char *
+code_run ( lzo1x_999_t *c, unsigned char *op, const unsigned char *ii,
+           lzo_uint lit, lzo_uint m_len )
+{
+ if (lit > 0)
+ {
+  ((void) (0));
+  op = STORE_RUN(c,op,ii,lit);
+  c->r1_m_len = m_len;
+  c->r1_lit = lit;
+ }
+ else
+ {
+  ((void) (0));
+  c->r1_m_len = 0;
+  c->r1_lit = 0;
+ }
+
+ return op;
+}
+
+
+
+
+
+
+static int
+len_of_coded_match ( lzo_uint m_len, lzo_uint m_off, lzo_uint lit )
+{
+ int n = 4;
+
+ if (m_len < 2)
+  return -1;
+ if (m_len == 2)
+  return (m_off <= 0x0400 && lit > 0 && lit < 4) ? 2 : -1;
+ if (m_len <= 8 && m_off <= 0x0800)
+  return 2;
+ if (m_len == 3 && m_off <= (0x0400 + 0x0800) && lit >= 4)
+  return 2;
+ if (m_off <= 0x4000)
+ {
+  if (m_len <= 33)
+   return 3;
+  m_len -= 33;
+  while (m_len > 255)
+  {
+   m_len -= 255;
+   n++;
+  }
+  return n;
+ }
+ if (m_off <= 0xbfff)
+ {
+  if (m_len <= 9)
+   return 3;
+  m_len -= 9;
+  while (m_len > 255)
+  {
+   m_len -= 255;
+   n++;
+  }
+  return n;
+ }
+ return -1;
+}
+
+
+static lzo_int
+min_gain(lzo_uint ahead, lzo_uint lit1, lzo_uint lit2, int l1, int l2, int l3)
+{
+ lzo_int lazy_match_min_gain = 0;
+
+ ((void) (0));
+ lazy_match_min_gain += ahead;
+
+
+
+
+
+
+ if (lit1 <= 3)
+  lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
+ else if (lit1 <= 18)
+  lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
+
+ lazy_match_min_gain += (l2 - l1) * 2;
+ if (l3 > 0)
+  lazy_match_min_gain -= (ahead - l3) * 2;
+
+ if (lazy_match_min_gain < 0)
+  lazy_match_min_gain = 0;
+
+
+
+
+
+
+
+ return lazy_match_min_gain;
+}
+
+static void
+better_match ( const lzo1x_999_swd_t *swd, lzo_uint *m_len, lzo_uint *m_off )
+{
+
+
+
+
+ if (*m_len <= 3)
+  return;
+
+ if (*m_off <= 0x0800)
+  return;
+
+
+
+ if (*m_off > 0x0800 &&
+     *m_len >= 3 + 1 && *m_len <= 8 + 1 &&
+     swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= 0x0800)
+ {
+  *m_len = *m_len - 1;
+  *m_off = swd->best_off[*m_len];
+  return;
+ }
+
+
+
+
+ if (*m_off > 0x4000 &&
+     *m_len >= 9 + 1 && *m_len <= 8 + 2 &&
+     swd->best_off[*m_len-2] && swd->best_off[*m_len-2] <= 0x0800)
+ {
+  *m_len = *m_len - 2;
+  *m_off = swd->best_off[*m_len];
+  return;
+ }
+
+
+
+
+ if (*m_off > 0x4000 &&
+     *m_len >= 9 + 1 && *m_len <= 33 + 1 &&
+     swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= 0x4000)
+ {
+  *m_len = *m_len - 1;
+  *m_off = swd->best_off[*m_len];
+ }
+
+}
+
+ int
+lzo1x_999_compress_internal ( const unsigned char *in , lzo_uint in_len,
+                                    unsigned char *out, lzo_uint * out_len,
+                                    void * wrkmem,
+                              const unsigned char *dict, lzo_uint dict_len,
+                                    lzo_progress_callback_t cb,
+                                    int try_lazy,
+                                    lzo_uint good_length,
+                                    lzo_uint max_lazy,
+                                    lzo_uint nice_length,
+                                    lzo_uint max_chain,
+                                    lzo_uint32 flags )
+{
+ unsigned char *op;
+ const unsigned char *ii;
+ lzo_uint lit;
+ lzo_uint m_len, m_off;
+ lzo1x_999_t cc;
+ lzo1x_999_t * const c = &cc;
+ lzo1x_999_swd_t * const swd = (lzo1x_999_swd_t *) wrkmem;
+ int r;
+
+
+
+
+
+
+
+ if (!(((lzo_uint32) (14 * 16384L * sizeof(short))) >= ((lzo_uint) (sizeof(lzo1x_999_swd_t)))))
+  return (-1);
+
+
+
+ if (try_lazy < 0)
+  try_lazy = 1;
+
+ if (good_length <= 0)
+  good_length = 32;
+
+ if (max_lazy <= 0)
+  max_lazy = 32;
+
+ if (nice_length <= 0)
+  nice_length = 0;
+
+ if (max_chain <= 0)
+  max_chain = 2048;
+
+ c->init = 0;
+ c->ip = c->in = in;
+ c->in_end = in + in_len;
+ c->out = out;
+ c->cb = cb;
+ c->m1a_m = c->m1b_m = c->m2_m = c->m3_m = c->m4_m = 0;
+ c->lit1_r = c->lit2_r = c->lit3_r = 0;
+
+ op = out;
+ ii = c->ip;
+ lit = 0;
+ c->r1_lit = c->r1_m_len = 0;
+
+ r = init_match(c,swd,dict,dict_len,flags);
+ if (r != 0)
+  return r;
+ if (max_chain > 0)
+  swd->max_chain = max_chain;
+ if (nice_length > 0)
+  swd->nice_length = nice_length;
+
+ r = find_match(c,swd,0,0);
+ if (r != 0)
+  return r;
+ while (c->look > 0)
+ {
+  lzo_uint ahead;
+  lzo_uint max_ahead;
+  int l1, l2, l3;
+
+  c->codesize = op - out;
+
+  m_len = c->m_len;
+  m_off = c->m_off;
+
+  ((void) (0));
+  ((void) (0));
+  if (lit == 0)
+   ii = c->bp;
+  ((void) (0));
+  ((void) (0));
+
+  if ( m_len < 2 ||
+      (m_len == 2 && (m_off > 0x0400 || lit == 0 || lit >= 4)) ||
+
+
+
+
+
+      (m_len == 2 && op == out) ||
+
+   (op == out && lit == 0))
+  {
+
+   m_len = 0;
+  }
+  else if (m_len == 3)
+  {
+
+   if (m_off > (0x0400 + 0x0800) && lit >= 4)
+    m_len = 0;
+  }
+
+  if (m_len == 0)
+  {
+
+   lit++;
+   swd->max_chain = max_chain;
+   r = find_match(c,swd,1,0);
+   ((void) (0));
+   continue;
+  }
+
+
+
+  if (swd->use_best_off)
+   better_match(swd,&m_len,&m_off);
+
+  ((void)0);
+
+
+
+
+  ahead = 0;
+  if (try_lazy <= 0 || m_len >= max_lazy)
+  {
+
+   l1 = 0;
+   max_ahead = 0;
+  }
+  else
+  {
+
+   l1 = len_of_coded_match(m_len,m_off,lit);
+   ((void) (0));
+
+   max_ahead = ((try_lazy) <= (l1 - 1) ? (try_lazy) : (l1 - 1));
+
+
+
+  }
+
+
+  while (ahead < max_ahead && c->look > m_len)
+  {
+   lzo_int lazy_match_min_gain;
+
+   if (m_len >= good_length)
+    swd->max_chain = max_chain >> 2;
+   else
+    swd->max_chain = max_chain;
+   r = find_match(c,swd,1,0);
+   ahead++;
+
+   ((void) (0));
+   ((void) (0));
+   ((void) (0));
+
+
+
+
+
+
+   if (c->m_len < m_len)
+    continue;
+
+   if (c->m_len == m_len && c->m_off >= m_off)
+    continue;
+
+
+   if (swd->use_best_off)
+    better_match(swd,&c->m_len,&c->m_off);
+
+   l2 = len_of_coded_match(c->m_len,c->m_off,lit+ahead);
+   if (l2 < 0)
+    continue;
+
+   l3 = (op == out) ? -1 : len_of_coded_match(ahead,m_off,lit);
+
+
+
+
+   lazy_match_min_gain = min_gain(ahead,lit,lit+ahead,l1,l2,l3);
+   if (c->m_len >= m_len + lazy_match_min_gain)
+   {
+    c->lazy++;
+    ((void)0);
+
+    if (l3 > 0)
+    {
+
+     op = code_run(c,op,ii,lit,ahead);
+     lit = 0;
+
+     op = code_match(c,op,ahead,m_off);
+    }
+    else
+    {
+     lit += ahead;
+     ((void) (0));
+    }
+    goto lazy_match_done;
+   }
+  }
+
+
+  ((void) (0));
+
+
+  op = code_run(c,op,ii,lit,m_len);
+  lit = 0;
+
+
+  op = code_match(c,op,m_len,m_off);
+  swd->max_chain = max_chain;
+  r = find_match(c,swd,m_len,1+ahead);
+  ((void) (0));
+
+lazy_match_done: ;
+ }
+
+
+
+ if (lit > 0)
+  op = STORE_RUN(c,op,ii,lit);
+
+
+ *op++ = 16 | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+
+ c->codesize = op - out;
+ ((void) (0));
+
+ *out_len = op - out;
+
+ if (c->cb)
+  (*c->cb)(c->textsize,c->codesize);
+
+
+
+
+
+
+
+ ((void) (0));
+
+ return 0;
+}
+
+
+
+
+
+
+ int
+lzo1x_999_compress_level ( const unsigned char *in , unsigned in_len,
+                                    unsigned char *out, unsigned * out_len,
+                                    void * wrkmem,
+                              const unsigned char *dict, unsigned dict_len,
+                                    lzo_progress_callback_t cb,
+                                    int compression_level )
+{
+ static const struct
+ {
+  int try_lazy;
+  lzo_uint good_length;
+  lzo_uint max_lazy;
+  lzo_uint nice_length;
+  lzo_uint max_chain;
+  lzo_uint32 flags;
+ } c[9] = {
+  { 0, 0, 0, 8, 4, 0 },
+  { 0, 0, 0, 16, 8, 0 },
+  { 0, 0, 0, 32, 16, 0 },
+
+  { 1, 4, 4, 16, 16, 0 },
+  { 1, 8, 16, 32, 32, 0 },
+  { 1, 8, 16, 128, 128, 0 },
+
+  { 2, 8, 32, 128, 256, 0 },
+  { 2, 32, 128, 2048, 2048, 1 },
+  { 2, 2048, 2048, 2048, 4096, 1 }
+ };
+
+ if (compression_level < 1 || compression_level > 9)
+  return (-1);
+
+ compression_level -= 1;
+ return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
+                                    dict, dict_len, cb,
+                                    c[compression_level].try_lazy,
+                                    c[compression_level].good_length,
+                                    c[compression_level].max_lazy,
+
+
+
+                                    0,
+
+                                    c[compression_level].max_chain,
+                                    c[compression_level].flags);
+}
+EXPORT_SYMBOL_GPL(lzo1x_999_compress_level);
+
+
+
+
+
+ int
+lzo1x_999_compress_dict ( const unsigned char *in , unsigned in_len,
+                                    unsigned char *out, unsigned * out_len,
+                                    void * wrkmem,
+                              const unsigned char *dict, unsigned dict_len )
+{
+ return lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
+                                 dict, dict_len, 0, 8);
+}
+EXPORT_SYMBOL_GPL(lzo1x_999_compress_dict);
+
+ int
+lzo1x_999_compress ( const unsigned char *in , unsigned in_len,
+                            unsigned char *out, unsigned * out_len,
+                            void * wrkmem )
+{
+ return lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
+                                 ((void *)0), 0, 0, 8);
+}
+EXPORT_SYMBOL_GPL(lzo1x_999_compress);
+