tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Lzma2Decoder.cpp (6353B)


      1 // Lzma2Decoder.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 // #include <stdio.h>
      6 
      7 #include "../../../C/Alloc.h"
      8 // #include "../../../C/CpuTicks.h"
      9 
     10 #include "../Common/StreamUtils.h"
     11 
     12 #include "Lzma2Decoder.h"
     13 
     14 namespace NCompress {
     15 namespace NLzma2 {
     16 
     17 CDecoder::CDecoder():
     18      _dec(NULL)
     19    , _inProcessed(0)
     20    , _prop(0xFF)
     21    , _finishMode(false)
     22    , _inBufSize(1 << 20)
     23    , _outStep(1 << 20)
     24    #ifndef _7ZIP_ST
     25    , _tryMt(1)
     26    , _numThreads(1)
     27    , _memUsage((UInt64)(sizeof(size_t)) << 28)
     28    #endif
     29 {}
     30 
     31 CDecoder::~CDecoder()
     32 {
     33  if (_dec)
     34    Lzma2DecMt_Destroy(_dec);
     35 }
     36 
     37 STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
     38 STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
     39 
     40 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
     41 {
     42  if (size != 1)
     43    return E_NOTIMPL;
     44  if (prop[0] > 40)
     45    return E_NOTIMPL;
     46  _prop = prop[0];
     47  return S_OK;
     48 }
     49 
     50 
     51 STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
     52 {
     53  _finishMode = (finishMode != 0);
     54  return S_OK;
     55 }
     56 
     57 
     58 
     59 #ifndef _7ZIP_ST
     60 
     61 static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
     62 {
     63  const UInt32 kMinSize = (UInt32)1 << 20;
     64  const UInt32 kMaxSize = (UInt32)1 << 28;
     65  UInt64 blockSize = (UInt64)dictSize << 2;
     66  if (blockSize < kMinSize) blockSize = kMinSize;
     67  if (blockSize > kMaxSize) blockSize = kMaxSize;
     68  if (blockSize < dictSize) blockSize = dictSize;
     69  blockSize += (kMinSize - 1);
     70  blockSize &= ~(UInt64)(kMinSize - 1);
     71  return blockSize;
     72 }
     73 
     74 #define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
     75 
     76 #endif
     77 
     78 #define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
     79  if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
     80 
     81 #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
     82  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
     83 
     84 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
     85    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
     86 {
     87  _inProcessed = 0;
     88 
     89  if (!_dec)
     90  {
     91    _dec = Lzma2DecMt_Create(
     92      // &g_AlignedAlloc,
     93      &g_Alloc,
     94      &g_MidAlloc);
     95    if (!_dec)
     96      return E_OUTOFMEMORY;
     97  }
     98 
     99  CLzma2DecMtProps props;
    100  Lzma2DecMtProps_Init(&props);
    101 
    102  props.inBufSize_ST = _inBufSize;
    103  props.outStep_ST = _outStep;
    104 
    105  #ifndef _7ZIP_ST
    106  {
    107    props.numThreads = 1;
    108    UInt32 numThreads = _numThreads;
    109 
    110    if (_tryMt && numThreads >= 1)
    111    {
    112      UInt64 useLimit = _memUsage;
    113      UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
    114      UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
    115      size_t expectedBlockSize = (size_t)expectedBlockSize64;
    116      size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
    117      if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
    118      {
    119        props.outBlockMax = expectedBlockSize;
    120        props.inBlockMax = inBlockMax;
    121        const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
    122        UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
    123        if (numThreads > okThreads)
    124          numThreads = (UInt32)okThreads;
    125        if (numThreads == 0)
    126          numThreads = 1;
    127        props.numThreads = numThreads;
    128      }
    129    }
    130  }
    131  #endif
    132 
    133  CSeqInStreamWrap inWrap;
    134  CSeqOutStreamWrap outWrap;
    135  CCompressProgressWrap progressWrap;
    136 
    137  inWrap.Init(inStream);
    138  outWrap.Init(outStream);
    139  progressWrap.Init(progress);
    140 
    141  SRes res;
    142 
    143  UInt64 inProcessed = 0;
    144  int isMT = False;
    145 
    146  #ifndef _7ZIP_ST
    147  isMT = _tryMt;
    148  #endif
    149 
    150  // UInt64 cpuTicks = GetCpuTicks();
    151 
    152  res = Lzma2DecMt_Decode(_dec, _prop, &props,
    153      &outWrap.vt, outSize, _finishMode,
    154      &inWrap.vt,
    155      &inProcessed,
    156      &isMT,
    157      progress ? &progressWrap.vt : NULL);
    158 
    159  /*
    160  cpuTicks = GetCpuTicks() - cpuTicks;
    161  printf("\n             ticks = %10I64u\n", cpuTicks / 1000000);
    162  */
    163 
    164 
    165  #ifndef _7ZIP_ST
    166  /* we reset _tryMt, only if p->props.numThreads was changed */
    167  if (props.numThreads > 1)
    168    _tryMt = isMT;
    169  #endif
    170 
    171  _inProcessed = inProcessed;
    172 
    173  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
    174  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
    175  RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
    176 
    177  if (res == SZ_OK && _finishMode)
    178  {
    179    if (inSize && *inSize != inProcessed)
    180      res = SZ_ERROR_DATA;
    181    if (outSize && *outSize != outWrap.Processed)
    182      res = SZ_ERROR_DATA;
    183  }
    184 
    185  return SResToHRESULT(res);
    186 }
    187 
    188 
    189 STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
    190 {
    191  *value = _inProcessed;
    192  return S_OK;
    193 }
    194 
    195 
    196 #ifndef _7ZIP_ST
    197 
    198 STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
    199 {
    200  _numThreads = numThreads;
    201  return S_OK;
    202 }
    203 
    204 STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage)
    205 {
    206  _memUsage = memUsage;
    207  return S_OK;
    208 }
    209 
    210 #endif
    211 
    212 
    213 #ifndef NO_READ_FROM_CODER
    214 
    215 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
    216 {
    217  CLzma2DecMtProps props;
    218  Lzma2DecMtProps_Init(&props);
    219  props.inBufSize_ST = _inBufSize;
    220  props.outStep_ST = _outStep;
    221 
    222  _inProcessed = 0;
    223 
    224  if (!_dec)
    225  {
    226    _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
    227    if (!_dec)
    228      return E_OUTOFMEMORY;
    229  }
    230 
    231  _inWrap.Init(_inStream);
    232 
    233  SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
    234 
    235  if (res != SZ_OK)
    236    return SResToHRESULT(res);
    237  return S_OK;
    238 }
    239 
    240 
    241 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
    242 STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
    243  
    244 
    245 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
    246 {
    247  if (processedSize)
    248    *processedSize = 0;
    249 
    250  size_t size2 = size;
    251  UInt64 inProcessed = 0;
    252 
    253  SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
    254 
    255  _inProcessed += inProcessed;
    256  if (processedSize)
    257    *processedSize = (UInt32)size2;
    258  if (res != SZ_OK)
    259    return SResToHRESULT(res);
    260  return S_OK;
    261 }
    262 
    263 #endif
    264 
    265 }}