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