| OLD | NEW |
| (Empty) |
| 1 // LzmaEncoder.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 extern "C" | |
| 6 { | |
| 7 #include "../../../C/Alloc.h" | |
| 8 } | |
| 9 | |
| 10 #include "../Common/StreamUtils.h" | |
| 11 | |
| 12 #include "LzmaEncoder.h" | |
| 13 | |
| 14 static HRESULT SResToHRESULT(SRes res) | |
| 15 { | |
| 16 switch(res) | |
| 17 { | |
| 18 case SZ_OK: return S_OK; | |
| 19 case SZ_ERROR_MEM: return E_OUTOFMEMORY; | |
| 20 case SZ_ERROR_PARAM: return E_INVALIDARG; | |
| 21 // case SZ_ERROR_THREAD: return E_FAIL; | |
| 22 } | |
| 23 return E_FAIL; | |
| 24 } | |
| 25 | |
| 26 namespace NCompress { | |
| 27 namespace NLzma { | |
| 28 | |
| 29 static const UInt32 kStreamStepSize = (UInt32)1 << 31; | |
| 30 | |
| 31 static SRes MyRead(void *object, void *data, size_t *size) | |
| 32 { | |
| 33 UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize)
; | |
| 34 HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSi
ze); | |
| 35 *size = curSize; | |
| 36 return (SRes)res; | |
| 37 } | |
| 38 | |
| 39 static size_t MyWrite(void *object, const void *data, size_t size) | |
| 40 { | |
| 41 CSeqOutStream *p = (CSeqOutStream *)object; | |
| 42 p->Res = WriteStream(p->RealStream, data, size); | |
| 43 if (p->Res != 0) | |
| 44 return 0; | |
| 45 return size; | |
| 46 } | |
| 47 | |
| 48 static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } | |
| 49 static void SzBigFree(void *, void *address) { BigFree(address); } | |
| 50 static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; | |
| 51 | |
| 52 static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } | |
| 53 static void SzFree(void *, void *address) { MyFree(address); } | |
| 54 static ISzAlloc g_Alloc = { SzAlloc, SzFree }; | |
| 55 | |
| 56 CEncoder::CEncoder() | |
| 57 { | |
| 58 _seqInStream.SeqInStream.Read = MyRead; | |
| 59 _seqOutStream.SeqOutStream.Write = MyWrite; | |
| 60 _encoder = 0; | |
| 61 _encoder = LzmaEnc_Create(&g_Alloc); | |
| 62 if (_encoder == 0) | |
| 63 throw 1; | |
| 64 } | |
| 65 | |
| 66 CEncoder::~CEncoder() | |
| 67 { | |
| 68 if (_encoder != 0) | |
| 69 LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); | |
| 70 } | |
| 71 | |
| 72 inline wchar_t GetUpperChar(wchar_t c) | |
| 73 { | |
| 74 if (c >= 'a' && c <= 'z') | |
| 75 c -= 0x20; | |
| 76 return c; | |
| 77 } | |
| 78 | |
| 79 static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) | |
| 80 { | |
| 81 wchar_t c = GetUpperChar(*s++); | |
| 82 if (c == L'H') | |
| 83 { | |
| 84 if (GetUpperChar(*s++) != L'C') | |
| 85 return 0; | |
| 86 int numHashBytesLoc = (int)(*s++ - L'0'); | |
| 87 if (numHashBytesLoc < 4 || numHashBytesLoc > 4) | |
| 88 return 0; | |
| 89 if (*s++ != 0) | |
| 90 return 0; | |
| 91 *btMode = 0; | |
| 92 *numHashBytes = numHashBytesLoc; | |
| 93 return 1; | |
| 94 } | |
| 95 if (c != L'B') | |
| 96 return 0; | |
| 97 | |
| 98 if (GetUpperChar(*s++) != L'T') | |
| 99 return 0; | |
| 100 int numHashBytesLoc = (int)(*s++ - L'0'); | |
| 101 if (numHashBytesLoc < 2 || numHashBytesLoc > 4) | |
| 102 return 0; | |
| 103 c = GetUpperChar(*s++); | |
| 104 if (c != L'\0') | |
| 105 return 0; | |
| 106 *btMode = 1; | |
| 107 *numHashBytes = numHashBytesLoc; | |
| 108 return 1; | |
| 109 } | |
| 110 | |
| 111 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, | |
| 112 const PROPVARIANT *coderProps, UInt32 numProps) | |
| 113 { | |
| 114 CLzmaEncProps props; | |
| 115 LzmaEncProps_Init(&props); | |
| 116 | |
| 117 for (UInt32 i = 0; i < numProps; i++) | |
| 118 { | |
| 119 const PROPVARIANT &prop = coderProps[i]; | |
| 120 switch (propIDs[i]) | |
| 121 { | |
| 122 case NCoderPropID::kNumFastBytes: | |
| 123 if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break
; | |
| 124 case NCoderPropID::kMatchFinderCycles: | |
| 125 if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break
; | |
| 126 case NCoderPropID::kAlgorithm: | |
| 127 if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; bre
ak; | |
| 128 case NCoderPropID::kDictionarySize: | |
| 129 if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal;
break; | |
| 130 case NCoderPropID::kPosStateBits: | |
| 131 if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break
; | |
| 132 case NCoderPropID::kLitPosBits: | |
| 133 if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break
; | |
| 134 case NCoderPropID::kLitContextBits: | |
| 135 if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break
; | |
| 136 case NCoderPropID::kNumThreads: | |
| 137 if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVa
l; break; | |
| 138 case NCoderPropID::kMultiThread: | |
| 139 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.b
oolVal == VARIANT_TRUE) ? 2 : 1); break; | |
| 140 case NCoderPropID::kEndMarker: | |
| 141 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.
boolVal == VARIANT_TRUE); break; | |
| 142 case NCoderPropID::kMatchFinder: | |
| 143 if (prop.vt != VT_BSTR) return E_INVALIDARG; | |
| 144 if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /
* , &_matchFinderBase.skipModeBits */)) | |
| 145 return E_INVALIDARG; break; | |
| 146 default: | |
| 147 return E_INVALIDARG; | |
| 148 } | |
| 149 } | |
| 150 return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); | |
| 151 } | |
| 152 | |
| 153 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) | |
| 154 { | |
| 155 Byte props[LZMA_PROPS_SIZE]; | |
| 156 size_t size = LZMA_PROPS_SIZE; | |
| 157 RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); | |
| 158 return WriteStream(outStream, props, size); | |
| 159 } | |
| 160 | |
| 161 STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) | |
| 162 { | |
| 163 _seqOutStream.RealStream = outStream; | |
| 164 _seqOutStream.Res = S_OK; | |
| 165 return S_OK; | |
| 166 } | |
| 167 | |
| 168 STDMETHODIMP CEncoder::ReleaseOutStream() | |
| 169 { | |
| 170 _seqOutStream.RealStream.Release(); | |
| 171 return S_OK; | |
| 172 } | |
| 173 | |
| 174 typedef struct _CCompressProgressImp | |
| 175 { | |
| 176 ICompressProgress p; | |
| 177 ICompressProgressInfo *Progress; | |
| 178 HRESULT Res; | |
| 179 } CCompressProgressImp; | |
| 180 | |
| 181 #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) | |
| 182 | |
| 183 #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) | |
| 184 | |
| 185 SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) | |
| 186 { | |
| 187 CCompressProgressImp *p = (CCompressProgressImp *)pp; | |
| 188 p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outS
ize)); | |
| 189 return (SRes)p->Res; | |
| 190 } | |
| 191 | |
| 192 STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
*outStream, | |
| 193 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgress
Info *progress) | |
| 194 { | |
| 195 CCompressProgressImp progressImp; | |
| 196 progressImp.p.Progress = CompressProgress; | |
| 197 progressImp.Progress = progress; | |
| 198 progressImp.Res = SZ_OK; | |
| 199 | |
| 200 _seqInStream.RealStream = inStream; | |
| 201 SetOutStream(outStream); | |
| 202 SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream
.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); | |
| 203 ReleaseOutStream(); | |
| 204 if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) | |
| 205 return _seqOutStream.Res; | |
| 206 if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) | |
| 207 return progressImp.Res; | |
| 208 return SResToHRESULT(res); | |
| 209 } | |
| 210 | |
| 211 }} | |
| OLD | NEW |