• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Lzma86_Encode(Byte * dest,size_t * destLen,const Byte * src,size_t srcLen,int level,UInt32 dictSize,int filterMode)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