mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
170 lines
4.1 KiB
C++
170 lines
4.1 KiB
C++
// (C) 2017 Tino Reichardt
|
|
|
|
#include "StdAfx.h"
|
|
#include "BrotliEncoder.h"
|
|
#include "BrotliDecoder.h"
|
|
|
|
#ifndef EXTRACT_ONLY
|
|
namespace NCompress {
|
|
namespace NBROTLI {
|
|
|
|
CEncoder::CEncoder():
|
|
_processedIn(0),
|
|
_processedOut(0),
|
|
_inputSize(0),
|
|
_numThreads(NWindows::NSystem::GetNumberOfProcessors()),
|
|
_Long(-1),
|
|
_WindowLog(-1),
|
|
_ctx(NULL),
|
|
unpackSize(0)
|
|
{
|
|
_props.clear();
|
|
}
|
|
|
|
CEncoder::~CEncoder()
|
|
{
|
|
if (_ctx)
|
|
BROTLIMT_freeCCtx(_ctx);
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps)
|
|
{
|
|
_props.clear();
|
|
|
|
for (UInt32 i = 0; i < numProps; i++)
|
|
{
|
|
const PROPVARIANT & prop = coderProps[i];
|
|
PROPID propID = propIDs[i];
|
|
UInt32 v = (UInt32)prop.ulVal;
|
|
switch (propID)
|
|
{
|
|
case NCoderPropID::kLevel:
|
|
{
|
|
if (prop.vt != VT_UI4)
|
|
return E_INVALIDARG;
|
|
|
|
_props._level = static_cast < Byte > (prop.ulVal);
|
|
Byte mylevel = static_cast < Byte > (BROTLIMT_LEVEL_MAX);
|
|
if (_props._level > mylevel)
|
|
_props._level = mylevel;
|
|
|
|
break;
|
|
}
|
|
case NCoderPropID::kNumThreads:
|
|
{
|
|
SetNumberOfThreads(v);
|
|
break;
|
|
}
|
|
case NCoderPropID::kLong:
|
|
{
|
|
/* like --long in zstd cli program */
|
|
_Long = 1;
|
|
if (v == 0) {
|
|
if (prop.vt == VT_EMPTY) {
|
|
// m0=brotli:long -> long=default
|
|
_WindowLog = BROTLI_MAX_WINDOW_BITS; //BROTLI_DEFAULT_WINDOW;
|
|
} else {
|
|
// m0=brotli:long=0 -> long=auto
|
|
_WindowLog = 0;
|
|
}
|
|
} else if (v < BROTLI_MIN_WINDOW_BITS) {
|
|
// m0=brotli:long=9 -> long=10
|
|
_WindowLog = BROTLI_MIN_WINDOW_BITS;
|
|
} else if (v > BROTLI_LARGE_MAX_WINDOW_BITS) {
|
|
// m0=brotli:long=33 -> long=max
|
|
_WindowLog = BROTLI_LARGE_MAX_WINDOW_BITS;
|
|
} else {
|
|
// m0=brotli:long=15 -> long=value
|
|
_WindowLog = v;
|
|
}
|
|
break;
|
|
}
|
|
case NCoderPropID::kWindowLog:
|
|
{
|
|
if (v < BROTLI_MIN_WINDOW_BITS) v = BROTLI_MIN_WINDOW_BITS;
|
|
if (v > BROTLI_MAX_WINDOW_BITS) v = BROTLI_MAX_WINDOW_BITS;
|
|
_WindowLog = v;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream * outStream)
|
|
{
|
|
return WriteStream(outStream, &_props, sizeof (_props));
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
|
|
ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,
|
|
const UInt64 * /*outSize */, ICompressProgressInfo *progress)
|
|
{
|
|
BROTLIMT_RdWr_t rdwr;
|
|
size_t result;
|
|
HRESULT res = S_OK;
|
|
|
|
_processedIn = 0;
|
|
_processedOut = 0;
|
|
|
|
struct BrotliStream Rd;
|
|
Rd.inStream = inStream;
|
|
Rd.outStream = outStream;
|
|
Rd.processedIn = &_processedIn;
|
|
Rd.processedOut = &_processedOut;
|
|
|
|
struct BrotliStream Wr;
|
|
// if (_processedIn == 0)
|
|
Wr.progress = progress;
|
|
// else
|
|
// Wr.progress = 0;
|
|
Wr.inStream = inStream;
|
|
Wr.outStream = outStream;
|
|
Wr.processedIn = &_processedIn;
|
|
Wr.processedOut = &_processedOut;
|
|
|
|
/* 1) setup read/write functions */
|
|
rdwr.fn_read = ::BrotliRead;
|
|
rdwr.fn_write = ::BrotliWrite;
|
|
rdwr.arg_read = (void *)&Rd;
|
|
rdwr.arg_write = (void *)&Wr;
|
|
|
|
/* 2) create compression context, if needed */
|
|
if (!_ctx)
|
|
_ctx = BROTLIMT_createCCtx(_numThreads, unpackSize, _props._level, _inputSize,
|
|
_WindowLog >= 0 ? _WindowLog : BROTLI_MAX_WINDOW_BITS);
|
|
if (!_ctx)
|
|
return S_FALSE;
|
|
|
|
/* 4) compress */
|
|
result = BROTLIMT_compressCCtx(_ctx, &rdwr);
|
|
if (BROTLIMT_isError(result)) {
|
|
if (result == (size_t)-BROTLIMT_error_canceled)
|
|
return E_ABORT;
|
|
return E_FAIL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)
|
|
{
|
|
const UInt32 kNumThreadsMax = BROTLIMT_THREAD_MAX;
|
|
if (numThreads < 0) numThreads = 0;
|
|
if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;
|
|
// if single-threaded, retain artificial number set in BrotliHandler (always prefer .br format):
|
|
if (_numThreads == 0 && numThreads == 1) {
|
|
numThreads = 0;
|
|
}
|
|
_numThreads = numThreads;
|
|
return S_OK;
|
|
}
|
|
|
|
}}
|
|
#endif
|