Home | History | Annotate | Download | only in C
      1 /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
      2 2009-08-14 : Igor Pavlov : Public domain */
      3 
      4 #include <string.h>
      5 
      6 #include "Lzma86.h"
      7 
      8 #include "Alloc.h"
      9 #include "Bra.h"
     10 #include "LzmaEnc.h"
     11 
     12 #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
     13 
     14 static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
     15 static void SzFree(void *p, void *address) { p = p; MyFree(address); }
     16 
     17 int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
     18     int level, UInt32 dictSize, int filterMode)
     19 {
     20   ISzAlloc g_Alloc = { SzAlloc, SzFree };
     21   size_t outSize2 = *destLen;
     22   Byte *filteredStream;
     23   Bool useFilter;
     24   int mainResult = SZ_ERROR_OUTPUT_EOF;
     25   CLzmaEncProps props;
     26   LzmaEncProps_Init(&props);
     27   props.level = level;
     28   props.dictSize = dictSize;
     29 
     30   *destLen = 0;
     31   if (outSize2 < LZMA86_HEADER_SIZE)
     32     return SZ_ERROR_OUTPUT_EOF;
     33 
     34   {
     35     int i;
     36     UInt64 t = srcLen;
     37     for (i = 0; i < 8; i++, t >>= 8)
     38       dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
     39   }
     40 
     41   filteredStream = 0;
     42   useFilter = (filterMode != SZ_FILTER_NO);
     43   if (useFilter)
     44   {
     45     if (srcLen != 0)
     46     {
     47       filteredStream = (Byte *)MyAlloc(srcLen);
     48       if (filteredStream == 0)
     49         return SZ_ERROR_MEM;
     50       memcpy(filteredStream, src, srcLen);
     51     }
     52     {
     53       UInt32 x86State;
     54       x86_Convert_Init(x86State);
     55       x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
     56     }
     57   }
     58 
     59   {
     60     size_t minSize = 0;
     61     Bool bestIsFiltered = False;
     62 
     63     /* passes for SZ_FILTER_AUTO:
     64         0 - BCJ + LZMA
     65         1 - LZMA
     66         2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
     67     */
     68     int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
     69 
     70     int i;
     71     for (i = 0; i < numPasses; i++)
     72     {
     73       size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
     74       size_t outPropsSize = 5;
     75       SRes curRes;
     76       Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
     77       if (curModeIsFiltered && !bestIsFiltered)
     78         break;
     79       if (useFilter && i == 0)
     80         curModeIsFiltered = True;
     81 
     82       curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
     83           curModeIsFiltered ? filteredStream : src, srcLen,
     84           &props, dest + 1, &outPropsSize, 0,
     85           NULL, &g_Alloc, &g_Alloc);
     86 
     87       if (curRes != SZ_ERROR_OUTPUT_EOF)
     88       {
     89         if (curRes != SZ_OK)
     90         {
     91           mainResult = curRes;
     92           break;
     93         }
     94         if (outSizeProcessed <= minSize || mainResult != SZ_OK)
     95         {
     96           minSize = outSizeProcessed;
     97           bestIsFiltered = curModeIsFiltered;
     98           mainResult = SZ_OK;
     99         }
    100       }
    101     }
    102     dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
    103     *destLen = LZMA86_HEADER_SIZE + minSize;
    104   }
    105   if (useFilter)
    106     MyFree(filteredStream);
    107   return mainResult;
    108 }
    109