1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// LzmaEncoder.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../C/Alloc.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/CWrappers.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/StreamUtils.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "LzmaEncoder.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NCompress {
13baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NLzma {
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void SzBigFree(void *, void *address) { BigFree(address); }
17baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
20baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void SzFree(void *, void *address) { MyFree(address); }
21baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic ISzAlloc g_Alloc = { SzAlloc, SzFree };
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
23baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCEncoder::CEncoder()
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _encoder = 0;
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _encoder = LzmaEnc_Create(&g_Alloc);
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_encoder == 0)
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    throw 1;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
31baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCEncoder::~CEncoder()
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_encoder != 0)
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
37baa3858d3f5d128a5c8466b700098109edcad5f2repo syncinline wchar_t GetUpperChar(wchar_t c)
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (c >= 'a' && c <= 'z')
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    c -= 0x20;
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return c;
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
44baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  wchar_t c = GetUpperChar(*s++);
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (c == L'H')
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (GetUpperChar(*s++) != L'C')
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return 0;
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int numHashBytesLoc = (int)(*s++ - L'0');
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return 0;
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (*s++ != 0)
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return 0;
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *btMode = 0;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *numHashBytes = numHashBytesLoc;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 1;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (c != L'B')
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (GetUpperChar(*s++) != L'T')
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numHashBytesLoc = (int)(*s++ - L'0');
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  c = GetUpperChar(*s++);
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (c != L'\0')
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *btMode = 1;
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *numHashBytes = numHashBytesLoc;
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 1;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
76baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (propID == NCoderPropID::kMatchFinder)
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (prop.vt != VT_BSTR)
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_INVALIDARG;
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (prop.vt != VT_UI4)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_INVALIDARG;
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 v = prop.ulVal;
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch (propID)
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kNumFastBytes: ep.fb = v; break;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kAlgorithm: ep.algo = v; break;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kDictionarySize: ep.dictSize = v; break;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kPosStateBits: ep.pb = v; break;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kLitPosBits: ep.lp = v; break;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NCoderPropID::kLitContextBits: ep.lc = v; break;
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    default: return E_INVALIDARG;
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
101baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const PROPVARIANT *coderProps, UInt32 numProps)
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CLzmaEncProps props;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LzmaEncProps_Init(&props);
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < numProps; i++)
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const PROPVARIANT &prop = coderProps[i];
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    PROPID propID = propIDs[i];
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    switch (propID)
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      case NCoderPropID::kEndMarker:
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      case NCoderPropID::kNumThreads:
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      default:
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(SetLzmaProp(propID, prop, props));
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
124baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte props[LZMA_PROPS_SIZE];
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t size = LZMA_PROPS_SIZE;
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return WriteStream(outStream, props, size);
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
132baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CSeqInStreamWrap inWrap(inStream);
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CSeqOutStreamWrap outWrap(outStream);
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCompressProgressWrap progressWrap(progress);
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return inWrap.Res;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return outWrap.Res;
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return progressWrap.Res;
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SResToHRESULT(res);
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}}
150