1/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 22016-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 16int 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