1// OutBuffer.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/Alloc.h"
6
7#include "OutBuffer.h"
8
9bool COutBuffer::Create(UInt32 bufferSize)
10{
11  const UInt32 kMinBlockSize = 1;
12  if (bufferSize < kMinBlockSize)
13    bufferSize = kMinBlockSize;
14  if (_buffer != 0 && _bufferSize == bufferSize)
15    return true;
16  Free();
17  _bufferSize = bufferSize;
18  _buffer = (Byte *)::MidAlloc(bufferSize);
19  return (_buffer != 0);
20}
21
22void COutBuffer::Free()
23{
24  ::MidFree(_buffer);
25  _buffer = 0;
26}
27
28void COutBuffer::SetStream(ISequentialOutStream *stream)
29{
30  _stream = stream;
31}
32
33void COutBuffer::Init()
34{
35  _streamPos = 0;
36  _limitPos = _bufferSize;
37  _pos = 0;
38  _processedSize = 0;
39  _overDict = false;
40  #ifdef _NO_EXCEPTIONS
41  ErrorCode = S_OK;
42  #endif
43}
44
45UInt64 COutBuffer::GetProcessedSize() const
46{
47  UInt64 res = _processedSize + _pos - _streamPos;
48  if (_streamPos > _pos)
49    res += _bufferSize;
50  return res;
51}
52
53
54HRESULT COutBuffer::FlushPart()
55{
56  // _streamPos < _bufferSize
57  UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);
58  HRESULT result = S_OK;
59  #ifdef _NO_EXCEPTIONS
60  result = ErrorCode;
61  #endif
62  if (_buffer2 != 0)
63  {
64    memmove(_buffer2, _buffer + _streamPos, size);
65    _buffer2 += size;
66  }
67
68  if (_stream != 0
69      #ifdef _NO_EXCEPTIONS
70      && (ErrorCode == S_OK)
71      #endif
72     )
73  {
74    UInt32 processedSize = 0;
75    result = _stream->Write(_buffer + _streamPos, size, &processedSize);
76    size = processedSize;
77  }
78  _streamPos += size;
79  if (_streamPos == _bufferSize)
80    _streamPos = 0;
81  if (_pos == _bufferSize)
82  {
83    _overDict = true;
84    _pos = 0;
85  }
86  _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;
87  _processedSize += size;
88  return result;
89}
90
91HRESULT COutBuffer::Flush()
92{
93  #ifdef _NO_EXCEPTIONS
94  if (ErrorCode != S_OK)
95    return ErrorCode;
96  #endif
97
98  while(_streamPos != _pos)
99  {
100    HRESULT result = FlushPart();
101    if (result != S_OK)
102      return result;
103  }
104  return S_OK;
105}
106
107void COutBuffer::FlushWithCheck()
108{
109  HRESULT result = Flush();
110  #ifdef _NO_EXCEPTIONS
111  ErrorCode = result;
112  #else
113  if (result != S_OK)
114    throw COutBufferException(result);
115  #endif
116}
117