Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BZip2Encoder.cpp « BZip2Original « Compress « 7zip « CPP - github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bcd7dec0096b60a006944f43c223712592e1b122 (plain)
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;
}

}}