1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
#pragma once
#include "itextstream.h"
#include <algorithm>
#ifdef min
#undef min
#endif
namespace stream
{
class BufferInputStream :
public TextInputStream
{
private:
const char* _begin;
const char* _read;
const char* _end;
public:
BufferInputStream(const char* buffer, std::size_t length) :
_begin(buffer),
_read(buffer),
_end(buffer + length)
{}
std::size_t read(char* buffer, std::size_t length) override
{
std::size_t count = std::min(std::size_t(_end - _read), length);
const char* end = _read + count;
while (_read != end)
{
*buffer++ = *_read++;
}
return count;
}
// greebo: Override default std::streambuf::seekoff() method to provide buffer positioning capabilities
virtual std::streampos seekoff(std::streamoff off,
std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override
{
if (way == std::ios_base::beg)
{
const char* newPos = _begin + off;
// Force streambuf underflow
setg(_buffer, _buffer, _buffer);
if (newPos > _end || newPos < _begin)
{
return std::streampos(-1); // error
}
_read = newPos;
}
else if (way == std::ios_base::cur)
{
const char* newPos = _read + off;
if (newPos > _end || newPos < _begin)
{
return std::streampos(-1); // error
}
else
{
// success, check if we need to invalidate our controlled input sequence
if (gptr() + off > egptr() || gptr() + off < eback())
{
setg(_buffer, _buffer, _buffer);
}
}
_read = newPos;
}
else if (way == std::ios_base::end)
{
const char* newPos = _end + off;
// Force streambuf underflow
setg(_buffer, _buffer, _buffer);
if (newPos > _end || newPos < _begin)
{
return std::streampos(-1); // error
}
_read = newPos;
}
return std::streampos(_read - _begin);
}
};
}
|