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