1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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;
}
}}
|