1 /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2 2023-03-03 : 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
Lzma86_Encode(Byte * dest,size_t * destLen,const Byte * src,size_t srcLen,int level,UInt32 dictSize,int filterMode)14 int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
15 int level, UInt32 dictSize, int filterMode)
16 {
17 size_t outSize2 = *destLen;
18 Byte *filteredStream;
19 BoolInt useFilter;
20 int mainResult = SZ_ERROR_OUTPUT_EOF;
21 CLzmaEncProps props;
22 LzmaEncProps_Init(&props);
23 props.level = level;
24 props.dictSize = dictSize;
25
26 *destLen = 0;
27 if (outSize2 < LZMA86_HEADER_SIZE)
28 return SZ_ERROR_OUTPUT_EOF;
29
30 {
31 int i;
32 UInt64 t = srcLen;
33 for (i = 0; i < 8; i++, t >>= 8)
34 dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
35 }
36
37 filteredStream = 0;
38 useFilter = (filterMode != SZ_FILTER_NO);
39 if (useFilter)
40 {
41 if (srcLen != 0)
42 {
43 filteredStream = (Byte *)MyAlloc(srcLen);
44 if (filteredStream == 0)
45 return SZ_ERROR_MEM;
46 memcpy(filteredStream, src, srcLen);
47 }
48 {
49 UInt32 x86State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;
50 z7_BranchConvSt_X86_Enc(filteredStream, srcLen, 0, &x86State);
51 }
52 }
53
54 {
55 size_t minSize = 0;
56 BoolInt bestIsFiltered = False;
57
58 /* passes for SZ_FILTER_AUTO:
59 0 - BCJ + LZMA
60 1 - LZMA
61 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
62 */
63 int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
64
65 int i;
66 for (i = 0; i < numPasses; i++)
67 {
68 size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
69 size_t outPropsSize = 5;
70 SRes curRes;
71 BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
72 if (curModeIsFiltered && !bestIsFiltered)
73 break;
74 if (useFilter && i == 0)
75 curModeIsFiltered = True;
76
77 curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
78 curModeIsFiltered ? filteredStream : src, srcLen,
79 &props, dest + 1, &outPropsSize, 0,
80 NULL, &g_Alloc, &g_Alloc);
81
82 if (curRes != SZ_ERROR_OUTPUT_EOF)
83 {
84 if (curRes != SZ_OK)
85 {
86 mainResult = curRes;
87 break;
88 }
89 if (outSizeProcessed <= minSize || mainResult != SZ_OK)
90 {
91 minSize = outSizeProcessed;
92 bestIsFiltered = curModeIsFiltered;
93 mainResult = SZ_OK;
94 }
95 }
96 }
97 dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
98 *destLen = LZMA86_HEADER_SIZE + minSize;
99 }
100 if (useFilter)
101 MyFree(filteredStream);
102 return mainResult;
103 }
104