home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 March / PCO3_97.ISO / filesbbs / os2 / lzo026.arj / LZO026.ZIP / lzo-0.26 / src / lzo1b_d.ch < prev    next >
Encoding:
Text File  |  1996-10-26  |  5.4 KB  |  240 lines

  1. /* lzo1b_d.ch -- implementation of the LZO1B decompression 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. #include "lzo1_d.h"
  28.  
  29.  
  30. #if defined(HAVE_ANY_IP) && defined(HAVE_ANY_OP)
  31.    /* too many local variables, cannot allocate registers */
  32. #  undef LZO_OPTIMIZE_GNUC_i386
  33. #endif
  34.  
  35.  
  36. /***********************************************************************
  37. // decompress a block of data.
  38. ************************************************************************/
  39.  
  40. LZO_PUBLIC(int)
  41. DO_DECOMPRESS    ( const lzo_byte *in , lzo_uint  in_len,
  42.                          lzo_byte *out, lzo_uint *out_len,
  43.                          lzo_voidp LZO_UNUSED(wrkmem) )
  44. {
  45. #if defined(LZO_OPTIMIZE_GNUC_i386)
  46.     register lzo_byte *op __asm__("%edi");
  47.     register const lzo_byte *ip __asm__("%esi");
  48.     register lzo_uint t __asm__("%ecx");
  49.     register const lzo_byte *m_pos __asm__("%ebx");
  50. #else
  51.     register lzo_byte *op;
  52.     register const lzo_byte *ip;
  53.     register lzo_uint t;
  54.     register const lzo_byte *m_pos;
  55. #endif
  56.  
  57.     const lzo_byte * const ip_end = in + in_len;
  58. #if defined(HAVE_ANY_OP)
  59.     lzo_byte * const op_end = out + *out_len;
  60. #endif
  61.  
  62.     op = out;
  63.     ip = in;
  64.  
  65.     while (TEST_IP && TEST_OP)
  66.     {
  67.         t = *ip++;        /* get marker */
  68.  
  69.         if (t < R0MIN)        /* a literal run */
  70.         {
  71.             if (t == 0)                /* a R0 literal run */
  72.             {
  73.                 NEED_IP(1);
  74.                 t = *ip++;
  75.                 if (t >= R0FAST - R0MIN)            /* a long R0 run */
  76.                 {
  77.                     t -= R0FAST - R0MIN;
  78.                     t = (t == 0) ? R0FAST : 256u << ((unsigned) t);
  79.                     NEED_IP(t); NEED_OP(t);
  80.                     MEMCPY8_DS(op,ip,t);
  81.                     continue;
  82.                 }
  83.                 t += R0MIN;                            /* a short R0 run */
  84.             }
  85.  
  86. #if (M3O_BITS < 7)
  87. literal1:
  88. #endif
  89.  
  90.             NEED_IP(t); NEED_OP(t);
  91.             MEMCPY_DS(op,ip,t);            /* copy literal run */
  92.  
  93. #if (M3O_BITS == 7)
  94. literal2:
  95. #endif
  96.  
  97.             /* after a literal a match must follow */
  98.             while (TEST_IP && TEST_OP)
  99.             {
  100.                 t = *ip++;            /* get R1 marker */
  101.                 if (t >= R0MIN)
  102.                     goto match;
  103.  
  104.                 NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
  105.  
  106.             /* R1 match - a M2_MIN_LEN match + 1 byte literal */
  107.                 assert((t & M2O_MASK) == t);
  108.                 m_pos = op - M2_MIN_OFFSET;
  109.                 m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
  110.                 assert(m_pos >= out); assert(m_pos < op);
  111.                 TEST_LOOKBEHIND(m_pos,out); 
  112.                 COPY_M2;
  113.                 *op++ = *ip++;
  114.             }
  115.  
  116.             break;
  117.         }
  118.  
  119. match:
  120.  
  121.         if (t >= M2_MARKER)                /* a M2 match */
  122.         {
  123.             /* get match offset */
  124.             NEED_IP(1);
  125.             m_pos = op - M2_MIN_OFFSET;
  126.             m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
  127.             assert(m_pos >= out); assert(m_pos < op);
  128.             TEST_LOOKBEHIND(m_pos,out); 
  129.  
  130.             /* get match len */
  131.             t = (t >> M2O_BITS) - 1;
  132.             NEED_OP(t + M2_MIN_LEN - 1);
  133.             COPY_M2X;
  134.             MEMMOVE_DS(op,m_pos,t);
  135.         }
  136.         else                            /* a M3 or M4 match */
  137.         {
  138.             /* get match len */
  139.             t &= M3L_MASK;
  140.             if (t == 0)            /* a M4 match */
  141.             {
  142.                 NEED_IP(1);
  143.                 while (*ip == 0)
  144.                 {
  145.                     t += 255;
  146.                     ip++;
  147.                     NEED_IP(1);
  148.                 }
  149.                 t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
  150.             }
  151.  
  152.             /* get match offset */
  153.             NEED_IP(2);
  154.             m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
  155.             m_pos -= *ip++ & M3O_MASK;
  156.             m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
  157. #if defined(LZO_EOF_CODE)
  158.             if (m_pos == op)
  159.                 goto eof_found;
  160. #endif
  161.  
  162.             /* copy match */
  163.             assert(m_pos >= out); assert(m_pos < op);
  164.             TEST_LOOKBEHIND(m_pos,out); NEED_OP(t + M3_MIN_LEN - 1);
  165. #if defined(LZO_UNALIGNED_OK_4)
  166.             if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
  167.             {
  168.                 * (lzo_uint32p) op = * (lzo_uint32p) m_pos;
  169.                 op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
  170.                 do {
  171.                     * (lzo_uint32p) op = * (lzo_uint32p) m_pos;
  172.                     op += 4; m_pos += 4; t -= 4;
  173.                 } while (t >= 4); 
  174.                 if (t > 0) do *op++ = *m_pos++; while (--t > 0);
  175.             }
  176.             else
  177. #endif
  178.             {
  179.             COPY_M3X;
  180.             MEMMOVE_DS(op,m_pos,t);
  181.             }
  182.  
  183.  
  184. #if (M3O_BITS < 7)
  185.             t = ip[-2] >> M3O_BITS;
  186.             if (t)
  187.                 goto literal1;
  188. #elif (M3O_BITS == 7)
  189.             /* optimized version */
  190.             if (ip[-2] & (1 << M3O_BITS))
  191.             {
  192.                 NEED_IP(1); NEED_OP(1);
  193.                 *op++ = *ip++;
  194.                 goto literal2;
  195.             }
  196. #endif
  197.         }
  198.     }
  199.  
  200.  
  201. #if defined(LZO_EOF_CODE)
  202.     /* ip == ip_end and no EOF code was found */
  203.     *out_len = op - out;
  204.     return (ip == ip_end ? LZO_E_EOF_NOT_FOUND : LZO_E_ERROR);
  205.  
  206. eof_found:
  207.     assert(t == 1);
  208. #endif
  209.  
  210.     *out_len = op - out;
  211.  
  212.     /* the next line is the only check in the decompressor */
  213.     return (ip == ip_end ? LZO_E_OK : LZO_E_ERROR);
  214.  
  215.  
  216. #if defined(HAVE_NEED_IP)
  217. input_overrun:
  218.     *out_len = op - out;
  219.     return LZO_E_INPUT_OVERRUN;
  220. #endif
  221.  
  222. #if defined(HAVE_NEED_OP)
  223. output_overrun:
  224.     *out_len = op - out;
  225.     return LZO_E_OUTPUT_OVERRUN;
  226. #endif
  227.  
  228. #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
  229. lookbehind_overrun:
  230.     *out_len = op - out;
  231.     return LZO_E_LOOKBEHIND_OVERRUN;
  232. #endif
  233. }
  234.  
  235.  
  236. /*
  237. vi:ts=4
  238. */
  239.  
  240.