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(NULL),
11 _bufLim(NULL),
12 _bufBase(NULL),
13 _stream(NULL),
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 != NULL && _bufSize == bufSize)
26 return true;
27 Free();
28 _bufSize = bufSize;
29 _bufBase = (Byte *)::MidAlloc(bufSize);
30 return (_bufBase != NULL);
31 }
32
Free()33 void CInBuffer::Free() throw()
34 {
35 ::MidFree(_bufBase);
36 _bufBase = NULL;
37 }
38
Init()39 void CInBufferBase::Init() throw()
40 {
41 _processedSize = 0;
42 _buf = _bufBase;
43 _bufLim = _buf;
44 _wasFinished = false;
45 #ifdef Z7_NO_EXCEPTIONS
46 ErrorCode = S_OK;
47 #endif
48 NumExtraBytes = 0;
49 }
50
ReadBlock()51 bool CInBufferBase::ReadBlock()
52 {
53 #ifdef Z7_NO_EXCEPTIONS
54 if (ErrorCode != S_OK)
55 return false;
56 #endif
57 if (_wasFinished)
58 return false;
59 _processedSize += (size_t)(_buf - _bufBase);
60 _buf = _bufBase;
61 _bufLim = _bufBase;
62 UInt32 processed;
63 // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
64 const HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
65 #ifdef Z7_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 // 22.00: we don't increment (NumExtraBytes) here
81 // NumExtraBytes++;
82 b = 0xFF;
83 return false;
84 }
85 b = *_buf++;
86 return true;
87 }
88
ReadByte_FromNewBlock()89 Byte CInBufferBase::ReadByte_FromNewBlock()
90 {
91 if (!ReadBlock())
92 {
93 NumExtraBytes++;
94 return 0xFF;
95 }
96 return *_buf++;
97 }
98
ReadBytesPart(Byte * buf,size_t size)99 size_t CInBufferBase::ReadBytesPart(Byte *buf, size_t size)
100 {
101 if (size == 0)
102 return 0;
103 size_t rem = (size_t)(_bufLim - _buf);
104 if (rem == 0)
105 {
106 if (!ReadBlock())
107 return 0;
108 rem = (size_t)(_bufLim - _buf);
109 }
110 if (size > rem)
111 size = rem;
112 memcpy(buf, _buf, size);
113 _buf += size;
114 return size;
115 }
116
ReadBytes(Byte * buf,size_t size)117 size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
118 {
119 size_t num = 0;
120 for (;;)
121 {
122 const size_t rem = (size_t)(_bufLim - _buf);
123 if (size <= rem)
124 {
125 if (size != 0)
126 {
127 memcpy(buf, _buf, size);
128 _buf += size;
129 num += size;
130 }
131 return num;
132 }
133 if (rem != 0)
134 {
135 memcpy(buf, _buf, rem);
136 _buf += rem;
137 buf += rem;
138 num += rem;
139 size -= rem;
140 }
141 if (!ReadBlock())
142 return num;
143 }
144
145 /*
146 if ((size_t)(_bufLim - _buf) >= size)
147 {
148 const Byte *src = _buf;
149 for (size_t i = 0; i < size; i++)
150 buf[i] = src[i];
151 _buf += size;
152 return size;
153 }
154 for (size_t i = 0; i < size; i++)
155 {
156 if (_buf >= _bufLim)
157 if (!ReadBlock())
158 return i;
159 buf[i] = *_buf++;
160 }
161 return size;
162 */
163 }
164
Skip(size_t size)165 size_t CInBufferBase::Skip(size_t size)
166 {
167 size_t processed = 0;
168 for (;;)
169 {
170 const size_t rem = (size_t)(_bufLim - _buf);
171 if (rem >= size)
172 {
173 _buf += size;
174 return processed + size;
175 }
176 _buf += rem;
177 processed += rem;
178 size -= rem;
179 if (!ReadBlock())
180 return processed;
181 }
182 }
183