home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2003 November / VPR0311.ISO / OLS / TAR32223 / tar32223.lzh / tar32_2 / src / arcz.cpp < prev    next >
C/C++ Source or Header  |  2003-01-17  |  5KB  |  198 lines

  1. #include "arcz.h"
  2. #include "util.h"
  3. #include <stdlib.h>
  4.  
  5.  
  6. const unsigned char    CTarArcFile_Compress::MAGIC_1 = '\037';    /* First byte of compressed file    */
  7. const unsigned char    CTarArcFile_Compress::MAGIC_2 = '\235';    /* Second byte of compressed file    */
  8.  
  9. // static const int            C::HSIZE    = 1 << 17;    /* 131072 */
  10. static const int            BITS    = 16;
  11. static const int            INIT_BITS = 9;
  12.  
  13. static const int            BIT_MASK = 0x1f;
  14. static const int            BLOCK_MODE    = 0x80; /* Block compresssion if table is full and compression rate is dropping flush tables*/
  15.  
  16. static const int            FIRST    = 257;
  17. static const int            CLEAR    = 256;
  18.  
  19. CTarArcFile_Compress::CTarArcFile_Compress()
  20. {
  21.     m_pFile = NULL;
  22. }
  23. CTarArcFile_Compress::~CTarArcFile_Compress()
  24. {
  25.     if(m_pFile){fclose(m_pFile);}
  26. }
  27. bool CTarArcFile_Compress::open(const char *arcfile, const char *mode)
  28. {
  29.     m_arcfile = arcfile;
  30.  
  31.     /* only decompress implemented */
  32.     if(strchr(mode,'w')){return false;}
  33.     m_pFile = fopen(arcfile, "rb");
  34.  
  35.     m_insize = m_rsize = 0;
  36.  
  37.     m_insize = m_rsize = fread(m_inbuf, 1, BUFSIZ, m_pFile);
  38.  
  39.     char magic[2];
  40.     memcpy(magic, m_inbuf, 2);
  41.     //if(fread(magic, 1, 2, m_pFile) !=2){return false;}
  42.     //m_insize += 2; m_rsize += 2;
  43.     if(magic[0] != (char)MAGIC_1 || magic[1] != (char)MAGIC_2){return false;}
  44.  
  45.     char buf[1];
  46.     memcpy(buf, m_inbuf+2, 1);
  47.     //if(fread(buf, 1, 1, m_pFile) != 1){return false;}
  48.     //m_insize += 1; m_rsize +=1;
  49.     m_maxbits        = buf[0] & BIT_MASK;
  50.     if(m_maxbits > BITS){return false;}
  51.     m_block_mode    = ((buf[0] & BLOCK_MODE) != 0);
  52.  
  53.     m_eof = false;
  54.     m_n_bits = INIT_BITS;
  55.     m_maxcode = (1<<m_n_bits) - 1;
  56.     m_oldcode = -1;
  57.     m_finchar = 0;
  58.     m_posbits = 3*8;
  59.     m_free_ent = m_block_mode ? FIRST : 256;
  60.     memset(m_codetab, 0, 256);
  61.     for(int code=0; code<256; code++){
  62.         m_htab[code]= code;
  63.     }
  64.  
  65.     return true;
  66. }
  67. int CTarArcFile_Compress::read(void *buf, int size)
  68. {
  69.     int nread = 0;
  70.     
  71.     while(!m_eof && size > 0){
  72.         int in_avail;
  73.         in_avail = m_strstream.rdbuf()->in_avail();
  74.         if(in_avail == 0){
  75.             if(!readonce()){break;}
  76.         }
  77.         in_avail = m_strstream.rdbuf()->in_avail();
  78.         int n = min(in_avail, size);
  79.         m_strstream.read((char*)buf, n);
  80.         nread += n;
  81.         size -= n;
  82.         buf = (void*)((char*)buf + n);
  83.     }
  84.     return nread;
  85. }
  86. bool CTarArcFile_Compress::readonce()
  87. {
  88. resetbuf:
  89.     m_insize -= m_posbits/8;
  90.     memmove(m_inbuf, m_inbuf + m_posbits/8, m_insize);
  91.     m_posbits = 0;
  92.  
  93.     if(m_insize < sizeof(m_inbuf) - BUFSIZ){
  94.         m_rsize = fread(m_inbuf + m_insize, 1, BUFSIZ, m_pFile);
  95.         m_insize += m_rsize;
  96.     }
  97.     int inbits;
  98.     if(m_rsize>0){
  99.         inbits = (m_insize-m_insize%m_n_bits)*8;
  100.     }else{
  101.         inbits = (m_insize*8)-(m_n_bits-1);
  102.     }
  103.     while(inbits > m_posbits){
  104.         if(m_free_ent > m_maxcode){
  105.             m_posbits = (m_posbits-1)+((m_n_bits*8)-(m_posbits-1+(m_n_bits*8))%(m_n_bits*8));
  106.             m_n_bits++;
  107.             if(m_n_bits == m_maxbits){
  108.                 m_maxcode = 1 << m_maxbits;
  109.             }else{
  110.                 m_maxcode = (1 << m_n_bits) - 1;
  111.             }
  112.             goto resetbuf;
  113.         }
  114.         // input()
  115.         // input(inbuf, posbits, code, n_bits, bitmask);
  116.         /*@3 = (*(long*)(&@1[@2>>3]) >> (@2&0x7)) & @5;
  117.         @2 += @4;*/
  118.         int code;
  119.         {
  120.             int bitmask = (1<<m_n_bits) - 1;
  121.             code = (*(long*)(&m_inbuf[m_posbits/8]) >> (m_posbits&7)) & bitmask;
  122.             m_posbits += m_n_bits;
  123.         }
  124.  
  125.         if(m_oldcode == -1){
  126.             // outbuf[outpos++] = (unsigned char)(code);
  127.             m_strstream.put((unsigned char)code);
  128.             m_oldcode = code;
  129.             m_finchar = (int) code;
  130.             continue;
  131.         }
  132.         if(code == CLEAR && m_block_mode){
  133.             memset(m_codetab, 0, 256);
  134.             m_free_ent = FIRST - 1;
  135.             int tmp = (m_posbits-1) + (m_n_bits*8);
  136.             m_posbits = tmp - tmp%(m_n_bits*8);
  137.             m_n_bits = INIT_BITS;
  138.             m_maxcode = (1 << m_n_bits) - 1;
  139.             goto resetbuf;
  140.         }
  141.         int incode = code;
  142.         unsigned char *stackp = m_htab + sizeof(m_htab);
  143.         if(code > m_free_ent){
  144.             return false;
  145.         }else if(code == m_free_ent){    /* Special case for KwKwK string.    */
  146.             //m_posbits -= m_n_bits;
  147.             // p = &inbuf[posbits/8];
  148.             * --stackp = (unsigned char)m_finchar;
  149.             code = m_oldcode;
  150.         }
  151.         while((unsigned int)code >= (unsigned)256){
  152.             *--stackp    = m_htab[code];
  153.             code        = m_codetab[code];
  154.         }
  155.         * --stackp = (unsigned char)(m_finchar = m_htab[code] );
  156.  
  157.         m_strstream.write((char*)stackp, m_htab + sizeof(m_htab) - stackp);
  158.         /*
  159.         if(outpos + (i=(de_stack - stackp)) > OBUFSIZ){
  160.             do{
  161.                 if( i > OBUFSIZ - outpos){ i = OBUFSIZ - outpos; }
  162.                 memcpy(outbuf+outpos, stackp, i);
  163.                  if(outpos >= OBUFSIZ){
  164.                      m_stream.write(m_outbuf, outpos); outpos = 0;
  165.                  }
  166.                  stackp += i;
  167.             }while((i=(de_stack - stackp))>0);
  168.         }else{
  169.             memcpy(outbuf + outpos, stackp, i);
  170.             outpos += i;
  171.         }
  172.         */
  173.         if(m_free_ent < (1<<m_maxbits)){
  174.             m_codetab[m_free_ent]    = (unsigned short)m_oldcode;
  175.             m_htab[m_free_ent]        = m_finchar;
  176.             m_free_ent ++;
  177.         }
  178.         m_oldcode = incode;
  179.     }
  180.     // bytes_in += rsize;
  181.     if(m_rsize<=0){ m_eof = true; }
  182.     // m_strstream.write(outbuf, outpos); outpos = 0;
  183.     return true;
  184. }
  185. void CTarArcFile_Compress::close()
  186. {
  187.     if(m_pFile){fclose(m_pFile);m_pFile=NULL;}
  188. }
  189. string CTarArcFile_Compress::get_orig_filename(){
  190.     if(! m_orig_filename.empty()){return m_orig_filename;}
  191.     string fname = get_filename(m_arcfile.c_str());
  192.     if(fname.length()>2 && stricmp(fname.substr(fname.length()-2).c_str(),".z") == 0){
  193.         return fname.substr(0, fname.length()-2);
  194.     }
  195.     return fname + "_extracted";
  196. }
  197.  
  198.