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 
ReadBytes(Byte *buf, size_t size)99 size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
100 {
101   size_t num = 0;
102   for (;;)
103   {
104     const size_t rem = (size_t)(_bufLim - _buf);
105     if (size <= rem)
106     {
107       if (size != 0)
108       {
109         memcpy(buf, _buf, size);
110         _buf += size;
111         num += size;
112       }
113       return num;
114     }
115     if (rem != 0)
116     {
117       memcpy(buf, _buf, rem);
118       _buf += rem;
119       buf += rem;
120       num += rem;
121       size -= rem;
122     }
123     if (!ReadBlock())
124       return num;
125   }
126 
127   /*
128   if ((size_t)(_bufLim - _buf) >= size)
129   {
130     const Byte *src = _buf;
131     for (size_t i = 0; i < size; i++)
132       buf[i] = src[i];
133     _buf += size;
134     return size;
135   }
136   for (size_t i = 0; i < size; i++)
137   {
138     if (_buf >= _bufLim)
139       if (!ReadBlock())
140         return i;
141     buf[i] = *_buf++;
142   }
143   return size;
144   */
145 }
146 
Skip(size_t size)147 size_t CInBufferBase::Skip(size_t size)
148 {
149   size_t processed = 0;
150   for (;;)
151   {
152     const size_t rem = (size_t)(_bufLim - _buf);
153     if (rem >= size)
154     {
155       _buf += size;
156       return processed + size;
157     }
158     _buf += rem;
159     processed += rem;
160     size -= rem;
161     if (!ReadBlock())
162       return processed;
163   }
164 }
165