1 // InBuffer.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/Alloc.h"
6
7 #include "InBuffer.h"
8
CInBufferBase()9 CInBufferBase::CInBufferBase() throw():
10 _buf(0),
11 _bufLim(0),
12 _bufBase(0),
13 _stream(0),
14 _processedSize(0),
15 _bufSize(0),
16 _wasFinished(false),
17 NumExtraBytes(0)
18 {}
19
Create(size_t bufSize)20 bool CInBuffer::Create(size_t bufSize) throw()
21 {
22 const unsigned kMinBlockSize = 1;
23 if (bufSize < kMinBlockSize)
24 bufSize = kMinBlockSize;
25 if (_bufBase != 0 && _bufSize == bufSize)
26 return true;
27 Free();
28 _bufSize = bufSize;
29 _bufBase = (Byte *)::MidAlloc(bufSize);
30 return (_bufBase != 0);
31 }
32
Free()33 void CInBuffer::Free() throw()
34 {
35 ::MidFree(_bufBase);
36 _bufBase = 0;
37 }
38
Init()39 void CInBufferBase::Init() throw()
40 {
41 _processedSize = 0;
42 _buf = _bufBase;
43 _bufLim = _buf;
44 _wasFinished = false;
45 #ifdef _NO_EXCEPTIONS
46 ErrorCode = S_OK;
47 #endif
48 NumExtraBytes = 0;
49 }
50
ReadBlock()51 bool CInBufferBase::ReadBlock()
52 {
53 #ifdef _NO_EXCEPTIONS
54 if (ErrorCode != S_OK)
55 return false;
56 #endif
57 if (_wasFinished)
58 return false;
59 _processedSize += (_buf - _bufBase);
60 _buf = _bufBase;
61 _bufLim = _bufBase;
62 UInt32 processed;
63 // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
64 HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
65 #ifdef _NO_EXCEPTIONS
66 ErrorCode = result;
67 #else
68 if (result != S_OK)
69 throw CInBufferException(result);
70 #endif
71 _bufLim = _buf + processed;
72 _wasFinished = (processed == 0);
73 return !_wasFinished;
74 }
75
ReadByte_FromNewBlock(Byte & b)76 bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
77 {
78 if (!ReadBlock())
79 {
80 NumExtraBytes++;
81 b = 0xFF;
82 return false;
83 }
84 b = *_buf++;
85 return true;
86 }
87
ReadByte_FromNewBlock()88 Byte CInBufferBase::ReadByte_FromNewBlock()
89 {
90 if (!ReadBlock())
91 {
92 NumExtraBytes++;
93 return 0xFF;
94 }
95 return *_buf++;
96 }
97
ReadBytes(Byte * buf,size_t size)98 size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
99 {
100 size_t num = 0;
101 for (;;)
102 {
103 const size_t rem = _bufLim - _buf;
104 if (size <= rem)
105 {
106 if (size != 0)
107 {
108 memcpy(buf, _buf, size);
109 _buf += size;
110 num += size;
111 }
112 return num;
113 }
114 if (rem != 0)
115 {
116 memcpy(buf, _buf, rem);
117 _buf += rem;
118 buf += rem;
119 num += rem;
120 size -= rem;
121 }
122 if (!ReadBlock())
123 return num;
124 }
125
126 /*
127 if ((size_t)(_bufLim - _buf) >= size)
128 {
129 const Byte *src = _buf;
130 for (size_t i = 0; i < size; i++)
131 buf[i] = src[i];
132 _buf += size;
133 return size;
134 }
135 for (size_t i = 0; i < size; i++)
136 {
137 if (_buf >= _bufLim)
138 if (!ReadBlock())
139 return i;
140 buf[i] = *_buf++;
141 }
142 return size;
143 */
144 }
145
Skip(size_t size)146 size_t CInBufferBase::Skip(size_t size)
147 {
148 size_t processed = 0;
149 for (;;)
150 {
151 size_t rem = (_bufLim - _buf);
152 if (rem >= size)
153 {
154 _buf += size;
155 return processed + size;
156 }
157 _buf += rem;
158 processed += rem;
159 size -= rem;
160 if (!ReadBlock())
161 return processed;
162 }
163 }
164