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