Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/Bcj2Coder.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/Bcj2Coder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,393 @@ 1.4 +// Bcj2Coder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +extern "C" 1.9 +{ 1.10 +#include "../../../C/Alloc.h" 1.11 +} 1.12 + 1.13 +#include "Bcj2Coder.h" 1.14 + 1.15 +namespace NCompress { 1.16 +namespace NBcj2 { 1.17 + 1.18 +inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } 1.19 +inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } 1.20 +inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } 1.21 + 1.22 +#ifndef EXTRACT_ONLY 1.23 + 1.24 +static const int kBufferSize = 1 << 17; 1.25 + 1.26 +static bool inline Test86MSByte(Byte b) 1.27 +{ 1.28 + return (b == 0 || b == 0xFF); 1.29 +} 1.30 + 1.31 +bool CEncoder::Create() 1.32 +{ 1.33 + if (!_mainStream.Create(1 << 16)) 1.34 + return false; 1.35 + if (!_callStream.Create(1 << 20)) 1.36 + return false; 1.37 + if (!_jumpStream.Create(1 << 20)) 1.38 + return false; 1.39 + if (!_rangeEncoder.Create(1 << 20)) 1.40 + return false; 1.41 + if (_buffer == 0) 1.42 + { 1.43 + _buffer = (Byte *)MidAlloc(kBufferSize); 1.44 + if (_buffer == 0) 1.45 + return false; 1.46 + } 1.47 + return true; 1.48 +} 1.49 + 1.50 +CEncoder::~CEncoder() 1.51 +{ 1.52 + ::MidFree(_buffer); 1.53 +} 1.54 + 1.55 +HRESULT CEncoder::Flush() 1.56 +{ 1.57 + RINOK(_mainStream.Flush()); 1.58 + RINOK(_callStream.Flush()); 1.59 + RINOK(_jumpStream.Flush()); 1.60 + _rangeEncoder.FlushData(); 1.61 + return _rangeEncoder.FlushStream(); 1.62 +} 1.63 + 1.64 +const UInt32 kDefaultLimit = (1 << 24); 1.65 + 1.66 +HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, 1.67 + const UInt64 **inSizes, 1.68 + UInt32 numInStreams, 1.69 + ISequentialOutStream **outStreams, 1.70 + const UInt64 ** /* outSizes */, 1.71 + UInt32 numOutStreams, 1.72 + ICompressProgressInfo *progress) 1.73 +{ 1.74 + if (numInStreams != 1 || numOutStreams != 4) 1.75 + return E_INVALIDARG; 1.76 + 1.77 + if (!Create()) 1.78 + return E_OUTOFMEMORY; 1.79 + 1.80 + bool sizeIsDefined = false; 1.81 + UInt64 inSize = 0; 1.82 + if (inSizes != NULL) 1.83 + if (inSizes[0] != NULL) 1.84 + { 1.85 + inSize = *inSizes[0]; 1.86 + if (inSize <= kDefaultLimit) 1.87 + sizeIsDefined = true; 1.88 + } 1.89 + 1.90 + ISequentialInStream *inStream = inStreams[0]; 1.91 + 1.92 + _mainStream.SetStream(outStreams[0]); 1.93 + _mainStream.Init(); 1.94 + _callStream.SetStream(outStreams[1]); 1.95 + _callStream.Init(); 1.96 + _jumpStream.SetStream(outStreams[2]); 1.97 + _jumpStream.Init(); 1.98 + _rangeEncoder.SetStream(outStreams[3]); 1.99 + _rangeEncoder.Init(); 1.100 + for (int i = 0; i < 256 + 2; i++) 1.101 + _statusEncoder[i].Init(); 1.102 + CCoderReleaser releaser(this); 1.103 + 1.104 + CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; 1.105 + { 1.106 + inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); 1.107 + } 1.108 + 1.109 + UInt32 nowPos = 0; 1.110 + UInt64 nowPos64 = 0; 1.111 + UInt32 bufferPos = 0; 1.112 + 1.113 + Byte prevByte = 0; 1.114 + 1.115 + UInt64 subStreamIndex = 0; 1.116 + UInt64 subStreamStartPos = 0; 1.117 + UInt64 subStreamEndPos = 0; 1.118 + 1.119 + for (;;) 1.120 + { 1.121 + UInt32 processedSize = 0; 1.122 + for (;;) 1.123 + { 1.124 + UInt32 size = kBufferSize - (bufferPos + processedSize); 1.125 + UInt32 processedSizeLoc; 1.126 + if (size == 0) 1.127 + break; 1.128 + RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); 1.129 + if (processedSizeLoc == 0) 1.130 + break; 1.131 + processedSize += processedSizeLoc; 1.132 + } 1.133 + UInt32 endPos = bufferPos + processedSize; 1.134 + 1.135 + if (endPos < 5) 1.136 + { 1.137 + // change it 1.138 + for (bufferPos = 0; bufferPos < endPos; bufferPos++) 1.139 + { 1.140 + Byte b = _buffer[bufferPos]; 1.141 + _mainStream.WriteByte(b); 1.142 + UInt32 index; 1.143 + if (b == 0xE8) 1.144 + index = prevByte; 1.145 + else if (b == 0xE9) 1.146 + index = 256; 1.147 + else if (IsJcc(prevByte, b)) 1.148 + index = 257; 1.149 + else 1.150 + { 1.151 + prevByte = b; 1.152 + continue; 1.153 + } 1.154 + _statusEncoder[index].Encode(&_rangeEncoder, 0); 1.155 + prevByte = b; 1.156 + } 1.157 + return Flush(); 1.158 + } 1.159 + 1.160 + bufferPos = 0; 1.161 + 1.162 + UInt32 limit = endPos - 5; 1.163 + while(bufferPos <= limit) 1.164 + { 1.165 + Byte b = _buffer[bufferPos]; 1.166 + _mainStream.WriteByte(b); 1.167 + if (!IsJ(prevByte, b)) 1.168 + { 1.169 + bufferPos++; 1.170 + prevByte = b; 1.171 + continue; 1.172 + } 1.173 + Byte nextByte = _buffer[bufferPos + 4]; 1.174 + UInt32 src = 1.175 + (UInt32(nextByte) << 24) | 1.176 + (UInt32(_buffer[bufferPos + 3]) << 16) | 1.177 + (UInt32(_buffer[bufferPos + 2]) << 8) | 1.178 + (_buffer[bufferPos + 1]); 1.179 + UInt32 dest = (nowPos + bufferPos + 5) + src; 1.180 + // if (Test86MSByte(nextByte)) 1.181 + bool convert; 1.182 + if (getSubStreamSize != NULL) 1.183 + { 1.184 + UInt64 currentPos = (nowPos64 + bufferPos); 1.185 + while (subStreamEndPos < currentPos) 1.186 + { 1.187 + UInt64 subStreamSize; 1.188 + HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); 1.189 + if (result == S_OK) 1.190 + { 1.191 + subStreamStartPos = subStreamEndPos; 1.192 + subStreamEndPos += subStreamSize; 1.193 + subStreamIndex++; 1.194 + } 1.195 + else if (result == S_FALSE || result == E_NOTIMPL) 1.196 + { 1.197 + getSubStreamSize.Release(); 1.198 + subStreamStartPos = 0; 1.199 + subStreamEndPos = subStreamStartPos - 1; 1.200 + } 1.201 + else 1.202 + return result; 1.203 + } 1.204 + if (getSubStreamSize == NULL) 1.205 + { 1.206 + if (sizeIsDefined) 1.207 + convert = (dest < inSize); 1.208 + else 1.209 + convert = Test86MSByte(nextByte); 1.210 + } 1.211 + else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) 1.212 + convert = Test86MSByte(nextByte); 1.213 + else 1.214 + { 1.215 + UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); 1.216 + convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); 1.217 + } 1.218 + } 1.219 + else if (sizeIsDefined) 1.220 + convert = (dest < inSize); 1.221 + else 1.222 + convert = Test86MSByte(nextByte); 1.223 + unsigned index = GetIndex(prevByte, b); 1.224 + if (convert) 1.225 + { 1.226 + _statusEncoder[index].Encode(&_rangeEncoder, 1); 1.227 + bufferPos += 5; 1.228 + COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; 1.229 + for (int i = 24; i >= 0; i -= 8) 1.230 + s.WriteByte((Byte)(dest >> i)); 1.231 + prevByte = nextByte; 1.232 + } 1.233 + else 1.234 + { 1.235 + _statusEncoder[index].Encode(&_rangeEncoder, 0); 1.236 + bufferPos++; 1.237 + prevByte = b; 1.238 + } 1.239 + } 1.240 + nowPos += bufferPos; 1.241 + nowPos64 += bufferPos; 1.242 + 1.243 + if (progress != NULL) 1.244 + { 1.245 + /* 1.246 + const UInt64 compressedSize = 1.247 + _mainStream.GetProcessedSize() + 1.248 + _callStream.GetProcessedSize() + 1.249 + _jumpStream.GetProcessedSize() + 1.250 + _rangeEncoder.GetProcessedSize(); 1.251 + */ 1.252 + RINOK(progress->SetRatioInfo(&nowPos64, NULL)); 1.253 + } 1.254 + 1.255 + UInt32 i = 0; 1.256 + while(bufferPos < endPos) 1.257 + _buffer[i++] = _buffer[bufferPos++]; 1.258 + bufferPos = i; 1.259 + } 1.260 +} 1.261 + 1.262 +STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, 1.263 + const UInt64 **inSizes, 1.264 + UInt32 numInStreams, 1.265 + ISequentialOutStream **outStreams, 1.266 + const UInt64 **outSizes, 1.267 + UInt32 numOutStreams, 1.268 + ICompressProgressInfo *progress) 1.269 +{ 1.270 + try 1.271 + { 1.272 + return CodeReal(inStreams, inSizes, numInStreams, 1.273 + outStreams, outSizes,numOutStreams, progress); 1.274 + } 1.275 + catch(const COutBufferException &e) { return e.ErrorCode; } 1.276 + catch(...) { return S_FALSE; } 1.277 +} 1.278 + 1.279 +#endif 1.280 + 1.281 +HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, 1.282 + const UInt64 ** /* inSizes */, 1.283 + UInt32 numInStreams, 1.284 + ISequentialOutStream **outStreams, 1.285 + const UInt64 ** /* outSizes */, 1.286 + UInt32 numOutStreams, 1.287 + ICompressProgressInfo *progress) 1.288 +{ 1.289 + if (numInStreams != 4 || numOutStreams != 1) 1.290 + return E_INVALIDARG; 1.291 + 1.292 + if (!_mainInStream.Create(1 << 16)) 1.293 + return E_OUTOFMEMORY; 1.294 + if (!_callStream.Create(1 << 20)) 1.295 + return E_OUTOFMEMORY; 1.296 + if (!_jumpStream.Create(1 << 16)) 1.297 + return E_OUTOFMEMORY; 1.298 + if (!_rangeDecoder.Create(1 << 20)) 1.299 + return E_OUTOFMEMORY; 1.300 + if (!_outStream.Create(1 << 16)) 1.301 + return E_OUTOFMEMORY; 1.302 + 1.303 + _mainInStream.SetStream(inStreams[0]); 1.304 + _callStream.SetStream(inStreams[1]); 1.305 + _jumpStream.SetStream(inStreams[2]); 1.306 + _rangeDecoder.SetStream(inStreams[3]); 1.307 + _outStream.SetStream(outStreams[0]); 1.308 + 1.309 + _mainInStream.Init(); 1.310 + _callStream.Init(); 1.311 + _jumpStream.Init(); 1.312 + _rangeDecoder.Init(); 1.313 + _outStream.Init(); 1.314 + 1.315 + for (int i = 0; i < 256 + 2; i++) 1.316 + _statusDecoder[i].Init(); 1.317 + 1.318 + CCoderReleaser releaser(this); 1.319 + 1.320 + Byte prevByte = 0; 1.321 + UInt32 processedBytes = 0; 1.322 + for (;;) 1.323 + { 1.324 + if (processedBytes >= (1 << 20) && progress != NULL) 1.325 + { 1.326 + /* 1.327 + const UInt64 compressedSize = 1.328 + _mainInStream.GetProcessedSize() + 1.329 + _callStream.GetProcessedSize() + 1.330 + _jumpStream.GetProcessedSize() + 1.331 + _rangeDecoder.GetProcessedSize(); 1.332 + */ 1.333 + const UInt64 nowPos64 = _outStream.GetProcessedSize(); 1.334 + RINOK(progress->SetRatioInfo(NULL, &nowPos64)); 1.335 + processedBytes = 0; 1.336 + } 1.337 + UInt32 i; 1.338 + Byte b = 0; 1.339 + const UInt32 kBurstSize = (1 << 18); 1.340 + for (i = 0; i < kBurstSize; i++) 1.341 + { 1.342 + if (!_mainInStream.ReadByte(b)) 1.343 + return Flush(); 1.344 + _outStream.WriteByte(b); 1.345 + if (IsJ(prevByte, b)) 1.346 + break; 1.347 + prevByte = b; 1.348 + } 1.349 + processedBytes += i; 1.350 + if (i == kBurstSize) 1.351 + continue; 1.352 + unsigned index = GetIndex(prevByte, b); 1.353 + if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) 1.354 + { 1.355 + UInt32 src = 0; 1.356 + CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; 1.357 + for (int i = 0; i < 4; i++) 1.358 + { 1.359 + Byte b0; 1.360 + if(!s.ReadByte(b0)) 1.361 + return S_FALSE; 1.362 + src <<= 8; 1.363 + src |= ((UInt32)b0); 1.364 + } 1.365 + UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; 1.366 + _outStream.WriteByte((Byte)(dest)); 1.367 + _outStream.WriteByte((Byte)(dest >> 8)); 1.368 + _outStream.WriteByte((Byte)(dest >> 16)); 1.369 + _outStream.WriteByte((Byte)(dest >> 24)); 1.370 + prevByte = (Byte)(dest >> 24); 1.371 + processedBytes += 4; 1.372 + } 1.373 + else 1.374 + prevByte = b; 1.375 + } 1.376 +} 1.377 + 1.378 +STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, 1.379 + const UInt64 **inSizes, 1.380 + UInt32 numInStreams, 1.381 + ISequentialOutStream **outStreams, 1.382 + const UInt64 **outSizes, 1.383 + UInt32 numOutStreams, 1.384 + ICompressProgressInfo *progress) 1.385 +{ 1.386 + try 1.387 + { 1.388 + return CodeReal(inStreams, inSizes, numInStreams, 1.389 + outStreams, outSizes,numOutStreams, progress); 1.390 + } 1.391 + catch(const CInBufferException &e) { return e.ErrorCode; } 1.392 + catch(const COutBufferException &e) { return e.ErrorCode; } 1.393 + catch(...) { return S_FALSE; } 1.394 +} 1.395 + 1.396 +}}