xref: /third_party/lzma/C/Lzma86Enc.c (revision 370b324c)
1370b324cSopenharmony_ci/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2370b324cSopenharmony_ci2023-03-03 : Igor Pavlov : Public domain */
3370b324cSopenharmony_ci
4370b324cSopenharmony_ci#include "Precomp.h"
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include <string.h>
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#include "Lzma86.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "Alloc.h"
11370b324cSopenharmony_ci#include "Bra.h"
12370b324cSopenharmony_ci#include "LzmaEnc.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_ciint Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
15370b324cSopenharmony_ci    int level, UInt32 dictSize, int filterMode)
16370b324cSopenharmony_ci{
17370b324cSopenharmony_ci  size_t outSize2 = *destLen;
18370b324cSopenharmony_ci  Byte *filteredStream;
19370b324cSopenharmony_ci  BoolInt useFilter;
20370b324cSopenharmony_ci  int mainResult = SZ_ERROR_OUTPUT_EOF;
21370b324cSopenharmony_ci  CLzmaEncProps props;
22370b324cSopenharmony_ci  LzmaEncProps_Init(&props);
23370b324cSopenharmony_ci  props.level = level;
24370b324cSopenharmony_ci  props.dictSize = dictSize;
25370b324cSopenharmony_ci
26370b324cSopenharmony_ci  *destLen = 0;
27370b324cSopenharmony_ci  if (outSize2 < LZMA86_HEADER_SIZE)
28370b324cSopenharmony_ci    return SZ_ERROR_OUTPUT_EOF;
29370b324cSopenharmony_ci
30370b324cSopenharmony_ci  {
31370b324cSopenharmony_ci    int i;
32370b324cSopenharmony_ci    UInt64 t = srcLen;
33370b324cSopenharmony_ci    for (i = 0; i < 8; i++, t >>= 8)
34370b324cSopenharmony_ci      dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
35370b324cSopenharmony_ci  }
36370b324cSopenharmony_ci
37370b324cSopenharmony_ci  filteredStream = 0;
38370b324cSopenharmony_ci  useFilter = (filterMode != SZ_FILTER_NO);
39370b324cSopenharmony_ci  if (useFilter)
40370b324cSopenharmony_ci  {
41370b324cSopenharmony_ci    if (srcLen != 0)
42370b324cSopenharmony_ci    {
43370b324cSopenharmony_ci      filteredStream = (Byte *)MyAlloc(srcLen);
44370b324cSopenharmony_ci      if (filteredStream == 0)
45370b324cSopenharmony_ci        return SZ_ERROR_MEM;
46370b324cSopenharmony_ci      memcpy(filteredStream, src, srcLen);
47370b324cSopenharmony_ci    }
48370b324cSopenharmony_ci    {
49370b324cSopenharmony_ci      UInt32 x86State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;
50370b324cSopenharmony_ci      z7_BranchConvSt_X86_Enc(filteredStream, srcLen, 0, &x86State);
51370b324cSopenharmony_ci    }
52370b324cSopenharmony_ci  }
53370b324cSopenharmony_ci
54370b324cSopenharmony_ci  {
55370b324cSopenharmony_ci    size_t minSize = 0;
56370b324cSopenharmony_ci    BoolInt bestIsFiltered = False;
57370b324cSopenharmony_ci
58370b324cSopenharmony_ci    /* passes for SZ_FILTER_AUTO:
59370b324cSopenharmony_ci        0 - BCJ + LZMA
60370b324cSopenharmony_ci        1 - LZMA
61370b324cSopenharmony_ci        2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
62370b324cSopenharmony_ci    */
63370b324cSopenharmony_ci    int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
64370b324cSopenharmony_ci
65370b324cSopenharmony_ci    int i;
66370b324cSopenharmony_ci    for (i = 0; i < numPasses; i++)
67370b324cSopenharmony_ci    {
68370b324cSopenharmony_ci      size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
69370b324cSopenharmony_ci      size_t outPropsSize = 5;
70370b324cSopenharmony_ci      SRes curRes;
71370b324cSopenharmony_ci      BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
72370b324cSopenharmony_ci      if (curModeIsFiltered && !bestIsFiltered)
73370b324cSopenharmony_ci        break;
74370b324cSopenharmony_ci      if (useFilter && i == 0)
75370b324cSopenharmony_ci        curModeIsFiltered = True;
76370b324cSopenharmony_ci
77370b324cSopenharmony_ci      curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
78370b324cSopenharmony_ci          curModeIsFiltered ? filteredStream : src, srcLen,
79370b324cSopenharmony_ci          &props, dest + 1, &outPropsSize, 0,
80370b324cSopenharmony_ci          NULL, &g_Alloc, &g_Alloc);
81370b324cSopenharmony_ci
82370b324cSopenharmony_ci      if (curRes != SZ_ERROR_OUTPUT_EOF)
83370b324cSopenharmony_ci      {
84370b324cSopenharmony_ci        if (curRes != SZ_OK)
85370b324cSopenharmony_ci        {
86370b324cSopenharmony_ci          mainResult = curRes;
87370b324cSopenharmony_ci          break;
88370b324cSopenharmony_ci        }
89370b324cSopenharmony_ci        if (outSizeProcessed <= minSize || mainResult != SZ_OK)
90370b324cSopenharmony_ci        {
91370b324cSopenharmony_ci          minSize = outSizeProcessed;
92370b324cSopenharmony_ci          bestIsFiltered = curModeIsFiltered;
93370b324cSopenharmony_ci          mainResult = SZ_OK;
94370b324cSopenharmony_ci        }
95370b324cSopenharmony_ci      }
96370b324cSopenharmony_ci    }
97370b324cSopenharmony_ci    dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
98370b324cSopenharmony_ci    *destLen = LZMA86_HEADER_SIZE + minSize;
99370b324cSopenharmony_ci  }
100370b324cSopenharmony_ci  if (useFilter)
101370b324cSopenharmony_ci    MyFree(filteredStream);
102370b324cSopenharmony_ci  return mainResult;
103370b324cSopenharmony_ci}
104