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   if ((size_t)(_bufLim - _buf) >= size)
101   {
102     const Byte *src = _buf;
103     for (size_t i = 0; i < size; i++)
104       buf[i] = src[i];
105     _buf += size;
106     return size;
107   }
108   for (size_t i = 0; i < size; i++)
109   {
110     if (_buf >= _bufLim)
111       if (!ReadBlock())
112         return i;
113     buf[i] = *_buf++;
114   }
115   return size;
116 }
117 
Skip(size_t size)118 size_t CInBufferBase::Skip(size_t size)
119 {
120   size_t processed = 0;
121   for (;;)
122   {
123     size_t rem = (_bufLim - _buf);
124     if (rem >= size)
125     {
126       _buf += size;
127       return processed + size;
128     }
129     _buf += rem;
130     processed += rem;
131     size -= rem;
132     if (!ReadBlock())
133       return processed;
134   }
135 }
136