Subversion Repositories spk

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2
2008-08-05
3
Igor Pavlov
4
Public 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
 
16
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
17
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
18
static 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
 
23
unsigned long *g_ProgressData = NULL;
24
SRes DoProgress(void *p, UInt64 inSize, UInt64 outSize)
25
{
26
	if ( g_ProgressData )
27
		(*g_ProgressData) = (unsigned long)inSize;
28
	return SZ_OK;
29
}
30
 
31
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
32
    int level, UInt32 dictSize, int filterMode, unsigned long *progressPointer)
33
{
34
  size_t outSize2 = *destLen;
35
  Byte *filteredStream;
36
  Bool useFilter;
37
  int mainResult = SZ_ERROR_OUTPUT_EOF;
38
  CLzmaEncProps props;
39
  LzmaEncProps_Init(&props);
40
  props.level = level;
41
  props.dictSize = dictSize;
42
 
43
  *destLen = 0;
44
  if (outSize2 < LZMA86_HEADER_SIZE)
45
    return SZ_ERROR_OUTPUT_EOF;
46
 
47
  {
48
    int i;
49
    UInt64 t = srcLen;
50
    for (i = 0; i < 8; i++, t >>= 8)
51
      dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
52
  }
53
 
54
  filteredStream = 0;
55
  useFilter = (filterMode != SZ_FILTER_NO);
56
  if (useFilter)
57
  {
58
    if (srcLen != 0)
59
    {
60
      filteredStream = (Byte *)MyAlloc(srcLen);
61
      if (filteredStream == 0)
62
        return SZ_ERROR_MEM;
63
      memcpy(filteredStream, src, srcLen);
64
    }
65
    {
66
      UInt32 x86State;
67
      x86_Convert_Init(x86State);
68
      x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
69
    }
70
  }
71
 
72
  {
73
    size_t minSize = 0;
74
    Bool bestIsFiltered = False;
75
 
76
    /* passes for SZ_FILTER_AUTO:
77
 
78
        1 - LZMA
79
        2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
80
    */
81
    int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
82
	int i;
83
	ICompressProgress progress;
84
	progress.Progress = DoProgress;
85
	g_ProgressData = progressPointer;
86
 
87
    for (i = 0; i < numPasses; i++)
88
    {
89
      size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
90
      size_t outPropsSize = 5;
91
      SRes curRes;
92
      Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
93
      if (curModeIsFiltered && !bestIsFiltered)
94
        break;
95
      if (useFilter && i == 0)
96
        curModeIsFiltered = True;
97
 
98
      curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
99
          curModeIsFiltered ? filteredStream : src, srcLen,
100
          &props, dest + 1, &outPropsSize, 0,
101
          &progress, &g_Alloc, &g_Alloc);
102
 
103
      if (curRes != SZ_ERROR_OUTPUT_EOF)
104
      {
105
        if (curRes != SZ_OK)
106
        {
107
          mainResult = curRes;
108
          break;
109
        }
110
        if (outSizeProcessed <= minSize || mainResult != SZ_OK)
111
        {
112
          minSize = outSizeProcessed;
113
          bestIsFiltered = curModeIsFiltered;
114
          mainResult = SZ_OK;
115
        }
116
      }
117
    }
118
    dest[0] = (bestIsFiltered ? 1 : 0);
119
    *destLen = LZMA86_HEADER_SIZE + minSize;
120
  }
121
  if (useFilter)
122
    MyFree(filteredStream);
123
  return mainResult;
124
}