mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 00:07:00 -06:00
121 lines
3.0 KiB
C++
Executable File
121 lines
3.0 KiB
C++
Executable File
// BZip2Encoder.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "BZip2Encoder.h"
|
|
|
|
#include "../../../Common/Alloc.h"
|
|
#include "Original/bzlib.h"
|
|
|
|
namespace NCompress {
|
|
namespace NBZip2 {
|
|
|
|
static const UInt32 kBufferSize = (1 << 20);
|
|
|
|
CEncoder::~CEncoder()
|
|
{
|
|
BigFree(m_InBuffer);
|
|
}
|
|
|
|
struct CBZip2Compressor: public bz_stream
|
|
{
|
|
int Init(int blockSize100k, int verbosity, int small)
|
|
{ return BZ2_bzCompressInit(this, blockSize100k, verbosity, small); }
|
|
int Compress(int action ) { return BZ2_bzCompress(this, action ); }
|
|
int End() { return BZ2_bzCompressEnd(this); }
|
|
UInt64 GetTotalIn() const { return (UInt64(total_in_hi32) << 32) + total_in_lo32; }
|
|
UInt64 GetTotalOut() const { return (UInt64(total_out_hi32) << 32) + total_out_lo32; }
|
|
};
|
|
|
|
class CBZip2CompressorReleaser
|
|
{
|
|
CBZip2Compressor *m_Compressor;
|
|
public:
|
|
CBZip2CompressorReleaser(CBZip2Compressor *compressor): m_Compressor(compressor) {}
|
|
void Disable() { m_Compressor = NULL; }
|
|
~CBZip2CompressorReleaser() { if (m_Compressor != NULL) m_Compressor->End(); }
|
|
};
|
|
|
|
|
|
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
|
|
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
|
ICompressProgressInfo *progress)
|
|
{
|
|
if (m_InBuffer == 0)
|
|
{
|
|
m_InBuffer = (Byte *)BigAlloc(kBufferSize * 2);
|
|
if (m_InBuffer == 0)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
Byte *outBuffer = m_InBuffer + kBufferSize;
|
|
|
|
CBZip2Compressor bzStream;
|
|
bzStream.bzalloc = NULL;
|
|
bzStream.bzfree = NULL;
|
|
bzStream.opaque = NULL;
|
|
|
|
int result = bzStream.Init(9, 0, 0);
|
|
switch(result)
|
|
{
|
|
case BZ_OK:
|
|
break;
|
|
case BZ_MEM_ERROR:
|
|
return E_OUTOFMEMORY;
|
|
default:
|
|
return E_FAIL;
|
|
}
|
|
CBZip2CompressorReleaser releaser(&bzStream);
|
|
bzStream.avail_in = 0;
|
|
while (true)
|
|
{
|
|
if (bzStream.avail_in == 0)
|
|
{
|
|
bzStream.next_in = (char *)m_InBuffer;
|
|
UInt32 processedSize;
|
|
RINOK(inStream->Read(m_InBuffer, kBufferSize, &processedSize));
|
|
bzStream.avail_in = processedSize;
|
|
}
|
|
|
|
bzStream.next_out = (char *)outBuffer;
|
|
bzStream.avail_out = kBufferSize;
|
|
bool askFinish = (bzStream.avail_in == 0);
|
|
result = bzStream.Compress(askFinish ? BZ_FINISH : BZ_RUN);
|
|
UInt32 numBytesToWrite = kBufferSize - bzStream.avail_out;
|
|
if (numBytesToWrite > 0)
|
|
{
|
|
UInt32 processedSize;
|
|
RINOK(outStream->Write(outBuffer, numBytesToWrite, &processedSize));
|
|
if (numBytesToWrite != processedSize)
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (result == BZ_STREAM_END)
|
|
break;
|
|
switch(result)
|
|
{
|
|
case BZ_RUN_OK:
|
|
if (!askFinish)
|
|
break;
|
|
return E_FAIL;
|
|
case BZ_FINISH_OK:
|
|
if (askFinish)
|
|
break;
|
|
return E_FAIL;
|
|
case BZ_MEM_ERROR:
|
|
return E_OUTOFMEMORY;
|
|
default:
|
|
return E_FAIL;
|
|
}
|
|
if (progress != NULL)
|
|
{
|
|
UInt64 totalIn = bzStream.GetTotalIn();
|
|
UInt64 totalOut = bzStream.GetTotalOut();
|
|
RINOK(progress->SetRatioInfo(&totalIn, &totalOut));
|
|
}
|
|
}
|
|
// result = bzStream.End();
|
|
return S_OK;
|
|
}
|
|
|
|
}}
|