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