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