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