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