tor-browser

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

LzmaEncoder.cpp (4777B)


      1 // LzmaEncoder.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../C/Alloc.h"
      6 
      7 #include "../Common/CWrappers.h"
      8 #include "../Common/StreamUtils.h"
      9 
     10 #include "LzmaEncoder.h"
     11 
     12 namespace NCompress {
     13 namespace NLzma {
     14 
     15 CEncoder::CEncoder()
     16 {
     17  _encoder = NULL;
     18  _encoder = LzmaEnc_Create(&g_AlignedAlloc);
     19  if (!_encoder)
     20    throw 1;
     21 }
     22 
     23 CEncoder::~CEncoder()
     24 {
     25  if (_encoder)
     26    LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc);
     27 }
     28 
     29 static inline wchar_t GetUpperChar(wchar_t c)
     30 {
     31  if (c >= 'a' && c <= 'z')
     32    c -= 0x20;
     33  return c;
     34 }
     35 
     36 static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
     37 {
     38  wchar_t c = GetUpperChar(*s++);
     39  if (c == L'H')
     40  {
     41    if (GetUpperChar(*s++) != L'C')
     42      return 0;
     43    int numHashBytesLoc = (int)(*s++ - L'0');
     44    if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
     45      return 0;
     46    if (*s != 0)
     47      return 0;
     48    *btMode = 0;
     49    *numHashBytes = numHashBytesLoc;
     50    return 1;
     51  }
     52 
     53  if (c != L'B')
     54    return 0;
     55  if (GetUpperChar(*s++) != L'T')
     56    return 0;
     57  int numHashBytesLoc = (int)(*s++ - L'0');
     58  if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
     59    return 0;
     60  if (*s != 0)
     61    return 0;
     62  *btMode = 1;
     63  *numHashBytes = numHashBytesLoc;
     64  return 1;
     65 }
     66 
     67 #define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;
     68 
     69 HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
     70 {
     71  if (propID == NCoderPropID::kMatchFinder)
     72  {
     73    if (prop.vt != VT_BSTR)
     74      return E_INVALIDARG;
     75    return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
     76  }
     77  
     78  if (propID > NCoderPropID::kReduceSize)
     79    return S_OK;
     80  
     81  if (propID == NCoderPropID::kReduceSize)
     82  {
     83    if (prop.vt == VT_UI8)
     84      ep.reduceSize = prop.uhVal.QuadPart;
     85    else
     86      return E_INVALIDARG;
     87    return S_OK;
     88  }
     89 
     90  if (prop.vt != VT_UI4)
     91    return E_INVALIDARG;
     92  UInt32 v = prop.ulVal;
     93  switch (propID)
     94  {
     95    case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break;
     96    SET_PROP_32(kLevel, level)
     97    SET_PROP_32(kNumFastBytes, fb)
     98    SET_PROP_32(kMatchFinderCycles, mc)
     99    SET_PROP_32(kAlgorithm, algo)
    100    SET_PROP_32(kDictionarySize, dictSize)
    101    SET_PROP_32(kPosStateBits, pb)
    102    SET_PROP_32(kLitPosBits, lp)
    103    SET_PROP_32(kLitContextBits, lc)
    104    SET_PROP_32(kNumThreads, numThreads)
    105    default: return E_INVALIDARG;
    106  }
    107  return S_OK;
    108 }
    109 
    110 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
    111    const PROPVARIANT *coderProps, UInt32 numProps)
    112 {
    113  CLzmaEncProps props;
    114  LzmaEncProps_Init(&props);
    115 
    116  for (UInt32 i = 0; i < numProps; i++)
    117  {
    118    const PROPVARIANT &prop = coderProps[i];
    119    PROPID propID = propIDs[i];
    120    switch (propID)
    121    {
    122      case NCoderPropID::kEndMarker:
    123        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break;
    124      default:
    125        RINOK(SetLzmaProp(propID, prop, props));
    126    }
    127  }
    128  return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
    129 }
    130 
    131 
    132 STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
    133    const PROPVARIANT *coderProps, UInt32 numProps)
    134 {
    135  for (UInt32 i = 0; i < numProps; i++)
    136  {
    137    const PROPVARIANT &prop = coderProps[i];
    138    PROPID propID = propIDs[i];
    139    if (propID == NCoderPropID::kExpectedDataSize)
    140      if (prop.vt == VT_UI8)
    141        LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
    142  }
    143  return S_OK;
    144 }
    145 
    146 
    147 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
    148 {
    149  Byte props[LZMA_PROPS_SIZE];
    150  size_t size = LZMA_PROPS_SIZE;
    151  RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));
    152  return WriteStream(outStream, props, size);
    153 }
    154 
    155 
    156 #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
    157  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
    158 
    159 STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
    160    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
    161 {
    162  CSeqInStreamWrap inWrap;
    163  CSeqOutStreamWrap outWrap;
    164  CCompressProgressWrap progressWrap;
    165 
    166  inWrap.Init(inStream);
    167  outWrap.Init(outStream);
    168  progressWrap.Init(progress);
    169 
    170  SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt,
    171      progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc);
    172 
    173  _inputProcessed = inWrap.Processed;
    174 
    175  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
    176  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
    177  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
    178  
    179  return SResToHRESULT(res);
    180 }
    181 
    182 }}