diff options
Diffstat (limited to 'CPP/7zip/Compress/BZip2Original/BZip2Encoder.cpp')
-rwxr-xr-x | CPP/7zip/Compress/BZip2Original/BZip2Encoder.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/BZip2Original/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Original/BZip2Encoder.cpp new file mode 100755 index 00000000..bcd7dec0 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Original/BZip2Encoder.cpp @@ -0,0 +1,120 @@ +// 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; + for (;;) + { + 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; +} + +}} |