| OLD | NEW |
| (Empty) |
| 1 /* 7zDecode.c */ | |
| 2 | |
| 3 #include <memory.h> | |
| 4 | |
| 5 #include "7zDecode.h" | |
| 6 #ifdef _SZ_ONE_DIRECTORY | |
| 7 #include "LzmaDecode.h" | |
| 8 #else | |
| 9 #include "../../Compress/Lzma/LzmaDecode.h" | |
| 10 #include "../../Compress/Branch/BranchX86.h" | |
| 11 #include "../../Compress/Branch/BranchX86_2.h" | |
| 12 #endif | |
| 13 | |
| 14 #define k_Copy 0 | |
| 15 #define k_LZMA 0x30101 | |
| 16 #define k_BCJ 0x03030103 | |
| 17 #define k_BCJ2 0x0303011B | |
| 18 | |
| 19 #ifdef _LZMA_IN_CB | |
| 20 | |
| 21 typedef struct _CLzmaInCallbackImp | |
| 22 { | |
| 23 ILzmaInCallback InCallback; | |
| 24 ISzInStream *InStream; | |
| 25 CFileSize Size; | |
| 26 } CLzmaInCallbackImp; | |
| 27 | |
| 28 int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) | |
| 29 { | |
| 30 CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; | |
| 31 size_t processedSize; | |
| 32 SZ_RESULT res; | |
| 33 size_t curSize = (1 << 20); | |
| 34 if (curSize > cb->Size) | |
| 35 curSize = (size_t)cb->Size; | |
| 36 *size = 0; | |
| 37 res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &proc
essedSize); | |
| 38 *size = (SizeT)processedSize; | |
| 39 if (processedSize > curSize) | |
| 40 return (int)SZE_FAIL; | |
| 41 cb->Size -= processedSize; | |
| 42 if (res == SZ_OK) | |
| 43 return 0; | |
| 44 return (int)res; | |
| 45 } | |
| 46 | |
| 47 #endif | |
| 48 | |
| 49 SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize, | |
| 50 #ifdef _LZMA_IN_CB | |
| 51 ISzInStream *inStream, | |
| 52 #else | |
| 53 const Byte *inBuffer, | |
| 54 #endif | |
| 55 Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) | |
| 56 { | |
| 57 #ifdef _LZMA_IN_CB | |
| 58 CLzmaInCallbackImp lzmaCallback; | |
| 59 #else | |
| 60 SizeT inProcessed; | |
| 61 #endif | |
| 62 | |
| 63 CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bi
t */ | |
| 64 int result; | |
| 65 SizeT outSizeProcessedLoc; | |
| 66 | |
| 67 #ifdef _LZMA_IN_CB | |
| 68 lzmaCallback.Size = inSize; | |
| 69 lzmaCallback.InStream = inStream; | |
| 70 lzmaCallback.InCallback.Read = LzmaReadImp; | |
| 71 #endif | |
| 72 | |
| 73 if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, | |
| 74 (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK) | |
| 75 return SZE_FAIL; | |
| 76 | |
| 77 state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * s
izeof(CProb)); | |
| 78 if (state.Probs == 0) | |
| 79 return SZE_OUTOFMEMORY; | |
| 80 | |
| 81 #ifdef _LZMA_OUT_READ | |
| 82 if (state.Properties.DictionarySize == 0) | |
| 83 state.Dictionary = 0; | |
| 84 else | |
| 85 { | |
| 86 state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.Dictio
narySize); | |
| 87 if (state.Dictionary == 0) | |
| 88 { | |
| 89 allocMain->Free(state.Probs); | |
| 90 return SZE_OUTOFMEMORY; | |
| 91 } | |
| 92 } | |
| 93 LzmaDecoderInit(&state); | |
| 94 #endif | |
| 95 | |
| 96 result = LzmaDecode(&state, | |
| 97 #ifdef _LZMA_IN_CB | |
| 98 &lzmaCallback.InCallback, | |
| 99 #else | |
| 100 inBuffer, (SizeT)inSize, &inProcessed, | |
| 101 #endif | |
| 102 outBuffer, (SizeT)outSize, &outSizeProcessedLoc); | |
| 103 allocMain->Free(state.Probs); | |
| 104 #ifdef _LZMA_OUT_READ | |
| 105 allocMain->Free(state.Dictionary); | |
| 106 #endif | |
| 107 if (result == LZMA_RESULT_DATA_ERROR) | |
| 108 return SZE_DATA_ERROR; | |
| 109 if (result != LZMA_RESULT_OK) | |
| 110 return SZE_FAIL; | |
| 111 return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR; | |
| 112 } | |
| 113 | |
| 114 #ifdef _LZMA_IN_CB | |
| 115 SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer) | |
| 116 { | |
| 117 while (inSize > 0) | |
| 118 { | |
| 119 void *inBuffer; | |
| 120 size_t processedSize, curSize = (1 << 18); | |
| 121 if (curSize > inSize) | |
| 122 curSize = (size_t)(inSize); | |
| 123 RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &process
edSize)); | |
| 124 if (processedSize == 0) | |
| 125 return SZE_DATA_ERROR; | |
| 126 if (processedSize > curSize) | |
| 127 return SZE_FAIL; | |
| 128 memcpy(outBuffer, inBuffer, processedSize); | |
| 129 outBuffer += processedSize; | |
| 130 inSize -= processedSize; | |
| 131 } | |
| 132 return SZ_OK; | |
| 133 } | |
| 134 #endif | |
| 135 | |
| 136 #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) | |
| 137 #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStr
eams != 1 || c.NumOutStreams != 1) | |
| 138 #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStre
ams != 1) | |
| 139 #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutSt
reams != 1) | |
| 140 | |
| 141 SZ_RESULT CheckSupportedFolder(const CFolder *f) | |
| 142 { | |
| 143 if (f->NumCoders < 1 || f->NumCoders > 4) | |
| 144 return SZE_NOTIMPL; | |
| 145 if (IS_UNSUPPORTED_CODER(f->Coders[0])) | |
| 146 return SZE_NOTIMPL; | |
| 147 if (f->NumCoders == 1) | |
| 148 { | |
| 149 if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0
) | |
| 150 return SZE_NOTIMPL; | |
| 151 return SZ_OK; | |
| 152 } | |
| 153 if (f->NumCoders == 2) | |
| 154 { | |
| 155 if (IS_NO_BCJ(f->Coders[1]) || | |
| 156 f->NumPackStreams != 1 || f->PackStreams[0] != 0 || | |
| 157 f->NumBindPairs != 1 || | |
| 158 f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) | |
| 159 return SZE_NOTIMPL; | |
| 160 return SZ_OK; | |
| 161 } | |
| 162 if (f->NumCoders == 4) | |
| 163 { | |
| 164 if (IS_UNSUPPORTED_CODER(f->Coders[1]) || | |
| 165 IS_UNSUPPORTED_CODER(f->Coders[2]) || | |
| 166 IS_NO_BCJ2(f->Coders[3])) | |
| 167 return SZE_NOTIMPL; | |
| 168 if (f->NumPackStreams != 4 || | |
| 169 f->PackStreams[0] != 2 || | |
| 170 f->PackStreams[1] != 6 || | |
| 171 f->PackStreams[2] != 1 || | |
| 172 f->PackStreams[3] != 0 || | |
| 173 f->NumBindPairs != 3 || | |
| 174 f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || | |
| 175 f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || | |
| 176 f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) | |
| 177 return SZE_NOTIMPL; | |
| 178 return SZ_OK; | |
| 179 } | |
| 180 return SZE_NOTIMPL; | |
| 181 } | |
| 182 | |
| 183 CFileSize GetSum(const CFileSize *values, UInt32 index) | |
| 184 { | |
| 185 CFileSize sum = 0; | |
| 186 UInt32 i; | |
| 187 for (i = 0; i < index; i++) | |
| 188 sum += values[i]; | |
| 189 return sum; | |
| 190 } | |
| 191 | |
| 192 SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, | |
| 193 #ifdef _LZMA_IN_CB | |
| 194 ISzInStream *inStream, CFileSize startPos, | |
| 195 #else | |
| 196 const Byte *inBuffer, | |
| 197 #endif | |
| 198 Byte *outBuffer, size_t outSize, ISzAlloc *allocMain, | |
| 199 Byte *tempBuf[]) | |
| 200 { | |
| 201 UInt32 ci; | |
| 202 size_t tempSizes[3] = { 0, 0, 0}; | |
| 203 size_t tempSize3 = 0; | |
| 204 Byte *tempBuf3 = 0; | |
| 205 | |
| 206 RINOK(CheckSupportedFolder(folder)); | |
| 207 | |
| 208 for (ci = 0; ci < folder->NumCoders; ci++) | |
| 209 { | |
| 210 CCoderInfo *coder = &folder->Coders[ci]; | |
| 211 | |
| 212 if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) | |
| 213 { | |
| 214 UInt32 si = 0; | |
| 215 CFileSize offset; | |
| 216 CFileSize inSize; | |
| 217 Byte *outBufCur = outBuffer; | |
| 218 size_t outSizeCur = outSize; | |
| 219 if (folder->NumCoders == 4) | |
| 220 { | |
| 221 UInt32 indices[] = { 3, 2, 0 }; | |
| 222 CFileSize unpackSize = folder->UnPackSizes[ci]; | |
| 223 si = indices[ci]; | |
| 224 if (ci < 2) | |
| 225 { | |
| 226 Byte *temp; | |
| 227 outSizeCur = (size_t)unpackSize; | |
| 228 if (outSizeCur != unpackSize) | |
| 229 return SZE_OUTOFMEMORY; | |
| 230 temp = (Byte *)allocMain->Alloc(outSizeCur); | |
| 231 if (temp == 0 && outSizeCur != 0) | |
| 232 return SZE_OUTOFMEMORY; | |
| 233 outBufCur = tempBuf[1 - ci] = temp; | |
| 234 tempSizes[1 - ci] = outSizeCur; | |
| 235 } | |
| 236 else if (ci == 2) | |
| 237 { | |
| 238 if (unpackSize > outSize) | |
| 239 return SZE_OUTOFMEMORY; | |
| 240 tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); | |
| 241 tempSize3 = outSizeCur = (size_t)unpackSize; | |
| 242 } | |
| 243 else | |
| 244 return SZE_NOTIMPL; | |
| 245 } | |
| 246 offset = GetSum(packSizes, si); | |
| 247 inSize = packSizes[si]; | |
| 248 #ifdef _LZMA_IN_CB | |
| 249 RINOK(inStream->Seek(inStream, startPos + offset)); | |
| 250 #endif | |
| 251 | |
| 252 if (coder->MethodID == k_Copy) | |
| 253 { | |
| 254 if (inSize != outSizeCur) | |
| 255 return SZE_DATA_ERROR; | |
| 256 | |
| 257 #ifdef _LZMA_IN_CB | |
| 258 RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); | |
| 259 #else | |
| 260 memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize); | |
| 261 #endif | |
| 262 } | |
| 263 else | |
| 264 { | |
| 265 SZ_RESULT res = SzDecodeLzma(coder, inSize, | |
| 266 #ifdef _LZMA_IN_CB | |
| 267 inStream, | |
| 268 #else | |
| 269 inBuffer + (size_t)offset, | |
| 270 #endif | |
| 271 outBufCur, outSizeCur, allocMain); | |
| 272 RINOK(res) | |
| 273 } | |
| 274 } | |
| 275 else if (coder->MethodID == k_BCJ) | |
| 276 { | |
| 277 UInt32 state; | |
| 278 if (ci != 1) | |
| 279 return SZE_NOTIMPL; | |
| 280 x86_Convert_Init(state); | |
| 281 x86_Convert(outBuffer, outSize, 0, &state, 0); | |
| 282 } | |
| 283 else if (coder->MethodID == k_BCJ2) | |
| 284 { | |
| 285 CFileSize offset = GetSum(packSizes, 1); | |
| 286 CFileSize s3Size = packSizes[1]; | |
| 287 SZ_RESULT res; | |
| 288 if (ci != 3) | |
| 289 return SZE_NOTIMPL; | |
| 290 | |
| 291 #ifdef _LZMA_IN_CB | |
| 292 RINOK(inStream->Seek(inStream, startPos + offset)); | |
| 293 tempSizes[2] = (size_t)s3Size; | |
| 294 if (tempSizes[2] != s3Size) | |
| 295 return SZE_OUTOFMEMORY; | |
| 296 tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]); | |
| 297 if (tempBuf[2] == 0 && tempSizes[2] != 0) | |
| 298 return SZE_OUTOFMEMORY; | |
| 299 res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); | |
| 300 RINOK(res) | |
| 301 #endif | |
| 302 | |
| 303 res = x86_2_Decode( | |
| 304 tempBuf3, tempSize3, | |
| 305 tempBuf[0], tempSizes[0], | |
| 306 tempBuf[1], tempSizes[1], | |
| 307 #ifdef _LZMA_IN_CB | |
| 308 tempBuf[2], tempSizes[2], | |
| 309 #else | |
| 310 inBuffer + (size_t)offset, (size_t)s3Size, | |
| 311 #endif | |
| 312 outBuffer, outSize); | |
| 313 RINOK(res) | |
| 314 } | |
| 315 else | |
| 316 return SZE_NOTIMPL; | |
| 317 } | |
| 318 return SZ_OK; | |
| 319 } | |
| 320 | |
| 321 SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, | |
| 322 #ifdef _LZMA_IN_CB | |
| 323 ISzInStream *inStream, CFileSize startPos, | |
| 324 #else | |
| 325 const Byte *inBuffer, | |
| 326 #endif | |
| 327 Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) | |
| 328 { | |
| 329 Byte *tempBuf[3] = { 0, 0, 0}; | |
| 330 int i; | |
| 331 SZ_RESULT res = SzDecode2(packSizes, folder, | |
| 332 #ifdef _LZMA_IN_CB | |
| 333 inStream, startPos, | |
| 334 #else | |
| 335 inBuffer, | |
| 336 #endif | |
| 337 outBuffer, outSize, allocMain, tempBuf); | |
| 338 for (i = 0; i < 3; i++) | |
| 339 allocMain->Free(tempBuf[i]); | |
| 340 return res; | |
| 341 } | |
| OLD | NEW |