home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 March / PCO3_97.ISO / filesbbs / os2 / lzo026.arj / LZO026.ZIP / lzo-0.26 / src / lzo1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-16  |  16.4 KB  |  668 lines

  1. /* lzo1.c -- implementation of the LZO1 algorithm
  2.  
  3.    This file is part of the LZO real-time data compression library.
  4.  
  5.    Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
  6.  
  7.    The LZO library is free software; you can redistribute it and/or
  8.    modify it under the terms of the GNU General Public License as
  9.    published by the Free Software Foundation; either version 2 of
  10.    the License, or (at your option) any later version.
  11.  
  12.    The LZO library is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with the LZO library; see the file COPYING.
  19.    If not, write to the Free Software Foundation, Inc.,
  20.    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  
  22.    Markus F.X.J. Oberhumer
  23.    markus.oberhumer@jk.uni-linz.ac.at
  24.  */
  25.  
  26.  
  27. /* set tabsize to 4 */
  28.  
  29.  
  30. #undef NDEBUG
  31. #if 1 && !defined(NDEBUG) && !defined(LZO_DEBUG)
  32. #define NDEBUG
  33. #endif
  34. #include <assert.h>
  35.  
  36. #include <lzo1.h>
  37. #include "lzo_conf.h"
  38.  
  39.  
  40. /***********************************************************************
  41. // The next two defines can be changed to customize LZO1.
  42. // The default version is LZO1-5/1.
  43. ************************************************************************/
  44.  
  45. /* run bits (3 - 5) - the compressor and the decompressor
  46.  * must use the same value. */
  47. #if !defined(RBITS)
  48. #  define RBITS        5
  49. #endif
  50.  
  51. /* compression level (1 - 9) - this only affects the compressor.
  52.  * 1 is fastest, 9 is best compression ratio */
  53. #if !defined(CLEVEL)
  54. #  define CLEVEL    1            /* fastest by default */
  55. #endif
  56.  
  57.  
  58. /* check configuration */
  59. #if (RBITS < 3 || RBITS > 5)
  60. #  error invalid RBITS
  61. #endif
  62. #if (CLEVEL < 1 || CLEVEL > 9)
  63. #  error invalid CLEVEL
  64. #endif
  65.  
  66.  
  67. /***********************************************************************
  68. // You should not have to change anything below this line.
  69. ************************************************************************/
  70.  
  71. #undef LZO_ALWAYS_USE_MEMCPY
  72. #undef LZO_ALWAYS_USE_MEMMOVE
  73. #include "lzo_util.h"
  74.  
  75.  
  76.  
  77. /***********************************************************************
  78. //
  79. ************************************************************************/
  80.  
  81. /*  
  82.      Format of the marker byte
  83.  
  84.  
  85.      76543210
  86.      --------
  87.      00000000    a long run (a 'R0' run) - there are short and long R0 runs
  88.      000rrrrr    a short run with len r
  89.      mmmooooo    a short match (len = 2+m, o = offset low bits)
  90.      111ooooo    a long match (o = offset low bits)
  91. */
  92.  
  93.  
  94. #define RSIZE    (1 << RBITS)
  95. #define RMASK    (RSIZE - 1)
  96.  
  97. #define OBITS    RBITS                /* offset and run-length use same bits */
  98. #define OSIZE    (1 << OBITS)
  99. #define OMASK    (OSIZE - 1)
  100.  
  101. #define MBITS    (8 - OBITS)
  102. #define MSIZE    (1 << MBITS)
  103. #define MMASK    (MSIZE - 1)
  104.  
  105.  
  106. /* sanity checks */
  107. #if (OBITS < 3 || OBITS > 5)
  108. #  error invalid OBITS
  109. #endif
  110. #if (MBITS < 3 || MBITS > 5)
  111. #  error invalid MBITS
  112. #endif
  113.  
  114.  
  115. /***********************************************************************
  116. // some macros to improve readability
  117. ************************************************************************/
  118.  
  119. /* Minimum len of a match */
  120. #define    MIN_MATCH            3
  121. #define    THRESHOLD            (MIN_MATCH - 1)
  122.  
  123. /* Minimum len of match coded in 2 bytes */
  124. #define    MIN_MATCH_SHORT        MIN_MATCH
  125.  
  126. /* Maximum len of match coded in 2 bytes */
  127. #define    MAX_MATCH_SHORT        (THRESHOLD + (MSIZE - 2))
  128. /* MSIZE - 2: 0 is used to indicate runs,
  129.  *            MSIZE-1 is used to indicate a long match */
  130.  
  131. /* Minimum len of match coded in 3 bytes */
  132. #define    MIN_MATCH_LONG        (MAX_MATCH_SHORT + 1)
  133.  
  134. /* Maximum len of match coded in 3 bytes */
  135. #define    MAX_MATCH_LONG        (MIN_MATCH_LONG + 255)
  136.  
  137. /* Maximum offset of a match */
  138. #define    MAX_OFFSET            (1 << (8 + OBITS))
  139.  
  140.  
  141. /*
  142.  
  143. RBITS | MBITS  MIN  THR.  MSIZE  MAXS  MINL  MAXL   MAXO  R0MAX R0FAST
  144. ======+===============================================================
  145.   3   |   5      3    2     32    32    33    288   2048    263   256
  146.   4   |   4      3    2     16    16    17    272   4096    271   264
  147.   5   |   3      3    2      8     8     9    264   8192    287   280
  148.  
  149.  */
  150.  
  151.  
  152. /***********************************************************************
  153. // internal configuration 
  154. // all of these affect compression only
  155. ************************************************************************/
  156.  
  157. /* return -1 instead of copying if the data cannot be compressed */
  158. #undef LZO_RETURN_IF_NOT_COMPRESSIBLE
  159.  
  160.  
  161. /* choose the hashing strategy */
  162. #define LZO_HASH_LZO_INCREMENTAL_A
  163.  
  164. #define DBITS        (8 + RBITS)
  165. #include "lzo_dict.h"
  166. #define DVAL_LEN    DVAL_LOOKAHEAD
  167.  
  168.  
  169. /***********************************************************************
  170. // get algorithm info, return memory required for compression
  171. ************************************************************************/
  172.  
  173. LZO_PUBLIC(lzo_uint)
  174. lzo1_info ( int *rbits, int *clevel )
  175. {
  176.     if (rbits)
  177.         *rbits = RBITS;
  178.     if (clevel)
  179.         *clevel = CLEVEL;
  180.     return D_SIZE * lzo_sizeof(lzo_byte *);
  181. }
  182.  
  183.  
  184. /***********************************************************************
  185. // decode a R0 literal run (a long run)
  186. ************************************************************************/
  187.  
  188. #define    R0MIN    (RSIZE)                /* Minimum len of R0 run of literals */
  189. #define    R0MAX    (R0MIN + 255)        /* Maximum len of R0 run of literals */
  190. #define    R0FAST    (R0MAX & ~7u)        /* R0MAX aligned to 8 byte boundary */
  191.  
  192. #if (R0MAX - R0FAST != 7) || ((R0FAST & 7) != 0)
  193. #  error something went wrong
  194. #endif
  195.  
  196. /* 7 special codes from R0FAST+1 .. R0MAX
  197.  * these codes mean long R0 runs with lengths
  198.  * 512, 1024, 2048, 4096, 8192, 16384, 32768 */ 
  199.  
  200. static lzo_uint 
  201. unstore_long_r0(lzo_byte *op, const lzo_byte *ip, const unsigned t) 
  202. {
  203.     /* this function is only for long R0 runs */
  204.     assert(t <= (R0MAX - R0FAST));
  205.  
  206.     if (t == 0)
  207.     {
  208.         MEMCPY8_DS(op, ip, R0FAST);
  209.         return R0FAST;
  210.     }
  211.     else 
  212.     {
  213. #if 0
  214.         lzo_uint tt = 256u << t;
  215.         MEMCPY8_DS(op, ip, tt);
  216.         return t;
  217. #else
  218.         lzo_uint tt = (256u/8) << t;
  219.         MEMCPY8_DS(op, ip, tt * 8);
  220.         return tt * 8;
  221. #endif
  222.     }
  223. }
  224.  
  225.  
  226. /***********************************************************************
  227. // LZO1 decompress a block of data.
  228. //
  229. // Could be easily translated into assembly code.
  230. //
  231. // unstore_long_r0 has been moved to it's own function to improve
  232. // performance on machines with few registers (like the Intel 80x86)
  233. ************************************************************************/
  234.  
  235. LZO_PUBLIC(int)
  236. lzo1_decompress  ( const lzo_byte *in , lzo_uint  in_len,
  237.                          lzo_byte *out, lzo_uint *out_len,
  238.                          lzo_voidp LZO_UNUSED(wrkmem) )
  239. {
  240.     lzo_byte *op;
  241.     const lzo_byte *ip;
  242.     const lzo_byte * const ip_end = in + in_len;
  243.     unsigned char t;
  244.  
  245.     op = out;
  246.     ip = in;
  247.     while (ip < ip_end)
  248.     {
  249.         t = *ip++;    /* get marker */
  250.  
  251.         if (t < R0MIN)            /* a literal run */
  252.         {
  253.             if (t == 0)                /* a R0 literal run */
  254.             {
  255.                 t = *ip++;
  256.                 if (t < R0FAST - R0MIN)                /* a short R0 run */
  257.                 {
  258.                     lzo_uint tt = t + R0MIN;
  259.                     MEMCPY_DS(op,ip,tt);
  260.                 }
  261.                 else                                 /* a long R0 run */
  262.                 {
  263.                     lzo_uint tt;
  264.                     t -= R0FAST - R0MIN;
  265.                     tt = unstore_long_r0(op,ip,(unsigned)t);
  266.                     op += tt;
  267.                     ip += tt;
  268.                 }
  269.             }
  270.             else
  271.             {
  272.                 MEMCPY_DS(op,ip,t);
  273.             }
  274.         }
  275.         else                    /* a match */
  276.         {
  277.             lzo_uint tt;
  278.             /* get match offset */
  279.             const lzo_byte *m_pos = op - 1;
  280.             m_pos -= (lzo_uint)(t & OMASK) | (((lzo_uint) *ip++) << OBITS);
  281.  
  282.             /* get match len */
  283.             if (t >= ((MSIZE - 1) << OBITS))                /* all m-bits set */
  284.                 tt = (MIN_MATCH_LONG - THRESHOLD) + *ip++;    /* a long match */
  285.             else
  286.                 tt = t >> OBITS;                            /* a short match */
  287.  
  288.             assert(m_pos >= out);
  289.             assert(m_pos <  op);
  290. #if defined(LZO_ALWAYS_USE_MEMMOVE)
  291.             MEMMOVE_DS(op,m_pos,tt + THRESHOLD);
  292. #else
  293.             /* a half unrolled loop */
  294.             *op++ = *m_pos++;
  295.             *op++ = *m_pos++;
  296.             MEMMOVE_DS(op,m_pos,tt);
  297. #endif
  298.         }
  299.     }
  300.  
  301.     *out_len = op - out;
  302.  
  303.     /* the next line is the only check in the decompressor ! */
  304.     return (ip == ip_end ? 0 : -1);
  305. }
  306.  
  307.  
  308. /***********************************************************************
  309. // code a literal run
  310. ************************************************************************/
  311.  
  312. static lzo_byte *
  313. store_run(lzo_byte *op, const lzo_byte *ii, lzo_uint r_len)
  314. {
  315.     assert(r_len > 0);
  316.  
  317.     /* code a long R0 run */
  318.     if (r_len >= 512)
  319.     {
  320.         unsigned r_bits = 7;        /* 256 << 7 == 32768 */
  321.         do {
  322.             while (r_len >= (256u << r_bits))
  323.             {
  324.                 r_len -= (256u << r_bits);
  325.                 *op++ = 0; *op++ = LZO_BYTE((R0FAST - R0MIN) + r_bits);
  326.                 MEMCPY8_DS(op, ii, (256u << r_bits));
  327.             }
  328.         } while (--r_bits > 0);
  329.     }
  330.     while (r_len >= R0FAST)
  331.     {
  332.         r_len -= R0FAST;
  333.         *op++ = 0; *op++ = R0FAST - R0MIN;
  334.         MEMCPY8_DS(op, ii, R0FAST);
  335.     }
  336.  
  337.     if (r_len >= R0MIN)
  338.     {
  339.         /* code a short R0 run */
  340.         *op++ = 0; *op++ = LZO_BYTE(r_len - R0MIN);
  341.         MEMCPY_DS(op, ii, r_len);
  342.     }
  343.     else if (r_len > 0)
  344.     {
  345.         /* code a 'normal' run */
  346.         *op++ = LZO_BYTE(r_len);
  347.         MEMCPY_DS(op, ii, r_len);
  348.     }
  349.  
  350.     assert(r_len == 0);
  351.     return op;
  352. }
  353.  
  354.  
  355.  
  356. /***********************************************************************
  357. // LZO1 compress a block of data.
  358. //
  359. // Could be translated into assembly code without too much effort.
  360. //
  361. // I apologize for the spaghetti code, but it really helps the optimizer.
  362. ************************************************************************/
  363.  
  364. static int
  365. do_compress    ( const lzo_byte *in , lzo_uint  in_len,
  366.                        lzo_byte *out, lzo_uint *out_len,
  367.                        lzo_voidp wrkmem )
  368. {
  369.     const lzo_byte *ip;
  370. #if defined(__LZO_HASH_INCREMENTAL)
  371.     lzo_uint32 dv;
  372. #endif
  373.     lzo_byte *op;
  374.     const lzo_byte *m_pos;
  375.     const lzo_byte * const ip_end = in+in_len - DVAL_LEN - MIN_MATCH_LONG;
  376.     const lzo_byte * const in_end = in+in_len - DVAL_LEN;
  377.     const lzo_byte *ii;
  378.     const lzo_bytepp const dict = (const lzo_bytepp) wrkmem;
  379.     lzo_ptrdiff_t m_off;
  380.  
  381. #if !defined(NDEBUG)
  382.     const lzo_byte *m_pos_sav;
  383. #endif
  384.  
  385.     op = out;
  386.     ip = in;
  387.     ii = ip;                /* point to start of literal run */
  388.     if (in_len <= MIN_MATCH_LONG + DVAL_LEN + 1)
  389.         goto the_end;
  390.  
  391.     /* init dictionary */
  392. #if defined(LZO_DETERMINISTIC)
  393.     BZERO8_PTR(dict,D_SIZE);
  394. #endif
  395.  
  396.     DVAL_FIRST(dv,ip);
  397.     UPDATE_D(dict,cycle,dv,ip);
  398.     ip++;
  399.     DVAL_NEXT(dv,ip);
  400.  
  401.     do {
  402.  
  403.     dsearch:
  404.  
  405.         /* search ip in the dictionary */
  406.         {
  407.             lzo_uint dindex;
  408.  
  409.             dindex = DINDEX(dv,ip);
  410.             m_pos = dict[dindex];
  411.             UPDATE_I(dict,cycle,dindex,ip);
  412.         }
  413.  
  414. #if !defined(NDEBUG)
  415.         m_pos_sav = m_pos;
  416. #endif
  417.  
  418.     /* check potential match in m_pos */
  419.         if (LZO_CHECK_MPOS(m_pos,m_off,in,ip,MAX_OFFSET) 
  420.             || *m_pos++ != ip[0] || *m_pos++ != ip[1] || *m_pos++ != ip[2])
  421.         {
  422.     /* a literal */
  423.             /* OPTIMIZED: use a goto instead of '++ip' and end of do-loop */
  424.             if (++ip < ip_end)
  425.             {
  426.                 DVAL_NEXT(dv,ip);
  427.                 goto dsearch;
  428.             }
  429.         }
  430.         else
  431.         {
  432.     /* else we have found a match (of at least length 3) */
  433.             /* 1) store the current literal run */
  434.             if (ip - ii > 0)
  435.             {
  436. #if 1
  437.                 /* OPTIMIZED: inline the copying of a short run */
  438.                 if (ip - ii < R0MIN)
  439.                 {
  440.                     lzo_uint t = ip - ii;
  441.                     *op++ = LZO_BYTE(t);
  442.                     MEMCPY_DS(op, ii, t);
  443.                 }
  444.                 else
  445. #endif
  446.                     op = store_run(op,ii,(lzo_uint)(ip-ii));
  447.             }
  448.  
  449.             /* 2a) compute match len */
  450.             ii = ip;        /* point to start of current match */
  451.  
  452.             /* we already matched MIN_MATCH bytes,
  453.              * m_pos also already advanced MIN_MATCH bytes */
  454.             ip += MIN_MATCH;
  455.             assert(m_pos < ip);
  456.  
  457.             /* try to match another MIN_MATCH_LONG - MIN_MATCH bytes
  458.              * to see if we get a long match */
  459.  
  460.             /* the 'classic' PS macro :-) */
  461. #define PS    *m_pos++ != *ip++
  462.  
  463. #if (MIN_MATCH_LONG - MIN_MATCH == 2)                    /* MBITS == 2 */
  464.             if (PS || PS)
  465. #elif (MIN_MATCH_LONG - MIN_MATCH == 6)                    /* MBITS == 3 */
  466.             if (PS || PS || PS || PS || PS || PS)
  467. #elif (MIN_MATCH_LONG - MIN_MATCH == 14)                /* MBITS == 4 */
  468.             if (PS || PS || PS || PS || PS || PS || PS ||
  469.                 PS || PS || PS || PS || PS || PS || PS)
  470. #elif (MIN_MATCH_LONG - MIN_MATCH == 30)                /* MBITS == 5 */
  471.             if (PS || PS || PS || PS || PS || PS || PS || PS ||
  472.                 PS || PS || PS || PS || PS || PS || PS || PS ||
  473.                 PS || PS || PS || PS || PS || PS || PS || PS ||
  474.                 PS || PS || PS || PS || PS || PS)
  475. #else
  476. #  error MBITS not yet implemented
  477. #endif
  478.             {
  479.                 lzo_uint m_len;
  480.  
  481.             /* 2b) code a short match */
  482.                     assert(ip-m_pos == m_off);
  483.                 --ip;    /* ran one too far, point back to non-match */
  484.                 m_len = ip - ii;
  485.                     assert(m_len >= MIN_MATCH_SHORT);
  486.                     assert(m_len <= MAX_MATCH_SHORT);
  487.                     assert(m_off > 0);
  488.                     assert(m_off <= MAX_OFFSET);
  489.                     assert(ii-m_off == m_pos_sav);
  490.                     assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
  491.                 --m_off;
  492.                 /* code short match len + low offset bits */
  493.                 *op++ = LZO_BYTE(((m_len - THRESHOLD) << OBITS) |
  494.                                  (m_off & OMASK));
  495.                 /* code high offset bits */
  496.                 *op++ = LZO_BYTE(m_off >> OBITS);
  497.  
  498.  
  499.             /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
  500.  
  501. #define SI        /* nothing */
  502. #define DI        ++ii; DVAL_NEXT(dv,ii); UPDATE_D(dict,cycle,dv,ii);
  503. #define XI        assert(ii < ip); ii = ip; DVAL_FIRST(dv,(ip));
  504.  
  505. #if (CLEVEL == 9) || (CLEVEL >= 7 && MBITS <= 4) || (CLEVEL >= 5 && MBITS <= 3) 
  506.             /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
  507.                 ++ii;
  508.                 do {
  509.                     DVAL_NEXT(dv,ii);
  510.                     dict[ DINDEX(dv,ii) ] = ii;
  511.                 } while (++ii < ip);
  512.                 DVAL_NEXT(dv,ii);
  513.                 assert(ii == ip);
  514.                 DVAL_ASSERT(dv,ip);
  515. #elif (CLEVEL >= 3)
  516.                 SI   DI DI   XI
  517. #elif (CLEVEL >= 2)
  518.                 SI   DI      XI
  519. #else
  520.                              XI
  521. #endif
  522.  
  523.             }
  524.             else
  525.             {
  526.             /* we've found a long match - see how far we can still go */
  527.                 const lzo_byte *end;
  528.                 lzo_uint m_len;
  529.  
  530.                 assert(ip <= in_end);
  531.                 assert(ii == ip - MIN_MATCH_LONG);
  532.  
  533. #if defined(__BOUNDS_CHECKING_ON)
  534.                 if (in_end - ip <= (MAX_MATCH_LONG - MIN_MATCH_LONG))
  535. #else
  536.                 if (in_end <= ip + (MAX_MATCH_LONG - MIN_MATCH_LONG))
  537. #endif
  538.                     end = in_end;
  539.                 else
  540.                 {
  541.                     end = ip + (MAX_MATCH_LONG - MIN_MATCH_LONG);
  542.                     assert(end < in_end);
  543.                 }
  544.  
  545.                 while (ip < end  &&  *m_pos == *ip)
  546.                     m_pos++, ip++;
  547.                 assert(ip <= in_end);
  548.  
  549.             /* 2b) code the long match */
  550.                 m_len = ip - ii;
  551.                     assert(m_len >= MIN_MATCH_LONG);
  552.                     assert(m_len <= MAX_MATCH_LONG);
  553.                     assert(m_off > 0);
  554.                     assert(m_off <= MAX_OFFSET);
  555.                     assert(ii-m_off == m_pos_sav);
  556.                     assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
  557.                     assert(ip-m_pos == m_off);
  558.                 --m_off;
  559.                 /* code long match flag + low offset bits */
  560.                 *op++ = LZO_BYTE(((MSIZE - 1) << OBITS) | (m_off & OMASK));
  561.                 /* code high offset bits */
  562.                 *op++ = LZO_BYTE(m_off >> OBITS);
  563.                 /* code match len */
  564.                 *op++ = LZO_BYTE(m_len - MIN_MATCH_LONG);
  565.  
  566.  
  567.             /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
  568. #if (CLEVEL == 9)
  569.             /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
  570.             /* This is not recommended because it is slow. */
  571.                 ++ii;
  572.                 do {
  573.                     DVAL_NEXT(dv,ii);
  574.                     dict[ DINDEX(dv,ii) ] = ii;
  575.                 } while (++ii < ip);
  576.                 DVAL_NEXT(dv,ii);
  577.                 assert(ii == ip);
  578.                 DVAL_ASSERT(dv,ip);
  579. #elif (CLEVEL >= 8)
  580.                 SI   DI DI DI DI DI DI DI DI   XI
  581. #elif (CLEVEL >= 7)
  582.                 SI   DI DI DI DI DI DI DI      XI
  583. #elif (CLEVEL >= 6)
  584.                 SI   DI DI DI DI DI DI         XI
  585. #elif (CLEVEL >= 5)
  586.                 SI   DI DI DI DI               XI
  587. #elif (CLEVEL >= 4)
  588.                 SI   DI DI DI                  XI
  589. #elif (CLEVEL >= 3)
  590.                 SI   DI DI                     XI
  591. #elif (CLEVEL >= 2)
  592.                 SI   DI                        XI
  593. #else
  594.                                                XI
  595. #endif
  596.             }
  597.  
  598.             /* ii now points to the start of next literal run */
  599.             assert(ii == ip);
  600.         }
  601.     } while (ip < ip_end);
  602.  
  603.  
  604.  
  605. the_end:
  606.     assert(ip <= in_end);
  607.  
  608.  
  609. #if defined(LZO_RETURN_IF_NOT_COMPRESSIBLE)
  610.     /* return -1 if op == out to indicate that we
  611.      * couldn't compress and didn't copy anything.
  612.      */
  613.     if (op == out)
  614.     {
  615.         *out_len = 0;
  616.         return LZO_E_NOT_COMPRESSIBLE;
  617.     }
  618. #endif
  619.  
  620.  
  621.     /* store the final literal run */
  622.     if (in_end + DVAL_LEN - ii > 0)
  623.         op = store_run(op,ii,(lzo_uint)(in_end+DVAL_LEN-ii));
  624.  
  625.     *out_len = op - out;
  626.     return 0;                /* compression went ok */
  627. }
  628.  
  629.  
  630. /***********************************************************************
  631. // compress public entry point.
  632. ************************************************************************/
  633.  
  634. LZO_PUBLIC(int)
  635. lzo1_compress ( const lzo_byte *in , lzo_uint  in_len,
  636.                       lzo_byte *out, lzo_uint *out_len,
  637.                       lzo_voidp wrkmem )
  638. {
  639.     int r;
  640.  
  641.     /* sanity check */
  642.     if (!lzo_assert(LZO1_MEM_COMPRESS >= D_SIZE * lzo_sizeof(lzo_byte *)))
  643.         return LZO_E_ERROR;
  644.  
  645.     /* don't try to compress a block that's too short */
  646.     if (in_len <= MIN_MATCH_LONG + DVAL_LEN + 1)
  647.     {
  648. #if defined(LZO_RETURN_IF_NOT_COMPRESSIBLE)
  649.         r = LZO_E_NOT_COMPRESSIBLE;
  650. #else
  651.         *out_len = store_run(out,in,in_len) - out;
  652.         r =  0;                /* compression went ok */
  653. #endif
  654.     }
  655.     else
  656.         r = do_compress(in,in_len,out,out_len,wrkmem);
  657.  
  658.     if (r != 0)
  659.         *out_len = 0;
  660.  
  661.     return r;
  662. }
  663.  
  664.  
  665. /*
  666. vi:ts=4
  667. */
  668.