home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Source / clzma.h < prev    next >
C/C++ Source or Header  |  2004-01-05  |  7KB  |  321 lines

  1. #ifndef __CLZMA_H__
  2. #define __CLZMA_H__
  3.  
  4. #include "compressor.h"
  5. #include "7zip/7zip/IStream.h"
  6. #include "7zip/7zip/Compress/LZMA/LZMAEncoder.h"
  7. #include "7zip/Common/MyCom.h"
  8.  
  9. // implemented in build.cpp - simply calls CompressReal
  10. DWORD WINAPI lzmaCompressThread(LPVOID lpParameter);
  11.  
  12. class CLZMA:
  13.   public ICompressor,
  14.   public ISequentialInStream,
  15.   public ISequentialOutStream,
  16.   public CMyUnknownImp
  17. {
  18. private:
  19.   NCompress::NLZMA::CEncoder *_encoder;
  20.  
  21.   HANDLE hCompressionThread;
  22.  
  23.   BYTE *next_in; /* next input byte */
  24.   UINT avail_in; /* number of bytes available at next_in */
  25.  
  26.   BYTE *next_out; /* next output byte should be put there */
  27.   UINT avail_out; /* remaining free space at next_out */
  28.  
  29.   int res;
  30.  
  31.   BOOL finish;
  32.  
  33.   CRITICAL_SECTION cs;
  34.   BOOL nt_locked; /* nsis thread locked */
  35.   BOOL ct_locked; /* compression thread locked */
  36.   BOOL compressor_finished;
  37.  
  38. public:
  39.   MY_UNKNOWN_IMP
  40.  
  41.   CLZMA(): _encoder(NULL)
  42.   {
  43.     _encoder = new NCompress::NLZMA::CEncoder();
  44.     _encoder->SetWriteEndMarkerMode(true);
  45.     hCompressionThread = NULL;
  46.     compressor_finished = FALSE;
  47.     finish = FALSE;
  48.     ct_locked = TRUE;
  49.     End();
  50.     InitializeCriticalSection(&cs);
  51.   }
  52.  
  53.   ~CLZMA()
  54.   {
  55.     End();
  56.     DeleteCriticalSection(&cs);
  57.     if (_encoder)
  58.     {
  59.       delete _encoder;
  60.       _encoder = NULL;
  61.     }
  62.   }
  63.  
  64.   int Init(int level, UINT32 dicSize)
  65.   {
  66.     End();
  67.  
  68.     nt_locked = TRUE;
  69.     ct_locked = FALSE;
  70.  
  71.     compressor_finished = FALSE;
  72.     finish = FALSE;
  73.  
  74.     res = C_OK;
  75.  
  76.     PROPID propdIDs [] =
  77.     {
  78.       NCoderPropID::kAlgorithm,
  79.       NCoderPropID::kDictionarySize,
  80.       NCoderPropID::kNumFastBytes
  81.     };
  82.     const kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]);
  83.     PROPVARIANT props[kNumProps];
  84.     // NCoderPropID::kAlgorithm
  85.     props[0].vt = VT_UI4;
  86.     props[0].ulVal = 2;
  87.     // NCoderPropID::kDictionarySize
  88.     props[1].vt = VT_UI4;
  89.     props[1].ulVal = dicSize;
  90.     // NCoderPropID::kNumFastBytes
  91.     props[2].vt = VT_UI4;
  92.     props[2].ulVal = 64;
  93.     if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0)
  94.       return -1;
  95.     return _encoder->SetStreams(this, this, 0, 0);
  96.   }
  97.  
  98.   int Init(int level)
  99.   {
  100.     // default dictionary size is 8MB
  101.     return Init(level, 8 << 20);
  102.   }
  103.  
  104.   int End()
  105.   {
  106.     if (!compressor_finished && !ct_locked)
  107.     {
  108.       // kill compression thread
  109.       avail_in = 0;
  110.       avail_out = 0;
  111.       finish = TRUE;
  112.       LeaveCriticalSection(&cs);
  113.       while (!ct_locked)
  114.         Sleep(0);
  115.       nt_locked = FALSE;
  116.       EnterCriticalSection(&cs);
  117.       while (ct_locked)
  118.         Sleep(0);
  119.       nt_locked = TRUE;
  120.       LeaveCriticalSection(&cs);
  121.     }
  122.     if (hCompressionThread)
  123.     {
  124.       CloseHandle(hCompressionThread);
  125.       hCompressionThread = NULL;
  126.     }
  127.     SetNextOut(NULL, 0);
  128.     SetNextIn(NULL, 0);
  129.     return C_OK;
  130.   }
  131.  
  132.   int CompressReal()
  133.   {
  134.     EnterCriticalSection(&cs);
  135.     ct_locked = TRUE;
  136.  
  137.     while (nt_locked)
  138.       Sleep(0);
  139.  
  140.     try
  141.     {
  142.       if (_encoder->WriteCoderProperties(this) == S_OK)
  143.       {
  144.         while (true)
  145.         {
  146.           UINT64 inSize, outSize;
  147.           INT32 finished;
  148.           if (_encoder->CodeOneBlock(&inSize, &outSize, &finished))
  149.           {
  150.             res = -2;
  151.             break;
  152.           }
  153.           if (finished)
  154.           {
  155.             res = C_OK;
  156.             break;
  157.           }
  158.         }
  159.       }
  160.       else
  161.       {
  162.         res = -2;
  163.       }
  164.     }
  165.     catch (...)
  166.     {
  167.       res = -3;
  168.     }
  169.  
  170.     compressor_finished = TRUE;
  171.     LeaveCriticalSection(&cs);
  172.     ct_locked = FALSE;
  173.     return C_OK;
  174.   }
  175.  
  176.   int Compress(BOOL flush)
  177.   {
  178.     if (compressor_finished)
  179.     {
  180.       // act like zlib when it comes to stream ending
  181.       if (flush)
  182.         return C_OK;
  183.       else
  184.         return -1;
  185.     }
  186.  
  187.     finish = flush;
  188.  
  189.     if (!hCompressionThread)
  190.     {
  191.       DWORD dwThreadId;
  192.  
  193.       hCompressionThread = CreateThread(0, 0, lzmaCompressThread, (LPVOID) this, 0, &dwThreadId);
  194.       if (!hCompressionThread)
  195.         return -2;
  196.     }
  197.     else
  198.     {
  199.       LeaveCriticalSection(&cs);
  200.     }
  201.  
  202.     while (!ct_locked)
  203.       Sleep(0);
  204.  
  205.     nt_locked = FALSE;
  206.  
  207.     EnterCriticalSection(&cs);
  208.     nt_locked = TRUE;
  209.  
  210.     while (ct_locked)
  211.       Sleep(0);
  212.  
  213.     if (compressor_finished)
  214.     {
  215.       LeaveCriticalSection(&cs);
  216.       return res;
  217.     }
  218.  
  219.     return C_OK;
  220.   }
  221.  
  222.   void GetMoreIO()
  223.   {
  224.     LeaveCriticalSection(&cs);
  225.     while (!nt_locked)
  226.       Sleep(0);
  227.  
  228.     ct_locked = FALSE;
  229.  
  230.     EnterCriticalSection(&cs);
  231.     ct_locked = TRUE;
  232.  
  233.     while (nt_locked)
  234.       Sleep(0);
  235.   }
  236.  
  237.   STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize)
  238.   {
  239.     return ReadPart(data, size, processedSize);
  240.   }
  241.  
  242.   STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize)
  243.   {
  244.     if (processedSize)
  245.       *processedSize = 0;
  246.     while (size)
  247.     {
  248.       if (!avail_in)
  249.       {
  250.         if (finish)
  251.         {
  252.           return S_OK;
  253.         }
  254.         GetMoreIO();
  255.         if (!avail_in && finish)
  256.         {
  257.           return S_OK;
  258.         }
  259.         if (!avail_in)
  260.           return E_ABORT;
  261.       }
  262.       UINT32 l = min(size, avail_in);
  263.       memcpy(data, next_in, l);
  264.       avail_in -= l;
  265.       size -= l;
  266.       next_in += l;
  267.       data = LPBYTE(data) + l;
  268.       if (processedSize)
  269.         *processedSize += l;
  270.     }
  271.     return S_OK;
  272.   }
  273.  
  274.   STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize)
  275.   {
  276.     return WritePart(data, size, processedSize);
  277.   }
  278.  
  279.   STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize)
  280.   {
  281.     if (processedSize)
  282.       *processedSize = 0;
  283.     while (size)
  284.     {
  285.       if (!avail_out)
  286.       {
  287.         GetMoreIO();
  288.         if (!avail_out)
  289.           return E_ABORT;
  290.       }
  291.       UINT32 l = min(size, avail_out);
  292.       memcpy(next_out, data, l);
  293.       avail_out -= l;
  294.       size -= l;
  295.       next_out += l;
  296.       data = LPBYTE(data) + l;
  297.       if (processedSize)
  298.         *processedSize += l;
  299.     }
  300.     return S_OK;
  301.   }
  302.  
  303.   void SetNextIn(char *in, unsigned int size)
  304.   {
  305.     next_in = (LPBYTE) in;
  306.     avail_in = size;
  307.   }
  308.  
  309.   void SetNextOut(char *out, unsigned int size)
  310.   {
  311.     next_out = (LPBYTE) out;
  312.     avail_out = size;
  313.   }
  314.  
  315.   virtual char *GetNextOut() { return (char *) next_out; }
  316.   virtual unsigned int GetAvailIn() { return avail_in; }
  317.   virtual unsigned int GetAvailOut() { return avail_out; }
  318.   const char *GetName() { return "lzma"; }
  319. };
  320.  
  321. #endif