Skip to content

Commit

Permalink
Use SFINAE to turn generic reader into writer and seekable
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexMax committed Dec 10, 2023
1 parent ab4740f commit d61cc5d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
36 changes: 30 additions & 6 deletions include/lexio/bufreader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@
namespace LexIO
{

template <typename T>
/**
* @brief Turn any Reader into a BufferedReader, backed by a buffer allocated
* with ::new[] and ::delete[].
*
* @tparam READER Reader type to wrap
*/
template <typename READER, typename = std::enable_if_t<IsReaderV<READER>>>
class GenericBufReader
{
T m_wrapped;
READER m_wrapped;
uint8_t *m_buffer = nullptr;
size_t m_allocSize = 0;
size_t m_size = 0;
Expand All @@ -33,7 +39,7 @@ class GenericBufReader
GenericBufReader() = delete;

GenericBufReader(const GenericBufReader &other)
: m_wrapped(other.m_wrapped), m_buffer(new uint8_t[other.m_allocSize]), m_allocSize(other.m_allocSize),
: m_wrapped(other.m_wrapped), m_buffer(::new uint8_t[other.m_allocSize]), m_allocSize(other.m_allocSize),
m_size(other.m_size)
{
std::copy(&other.m_buffer[0], &other.m_buffer[m_size], m_buffer);
Expand All @@ -46,8 +52,8 @@ class GenericBufReader
other.m_buffer = nullptr;
}

GenericBufReader(T &&wrapped) : m_wrapped(wrapped) {}
~GenericBufReader() { delete[] m_buffer; }
GenericBufReader(READER &&wrapped) : m_wrapped(wrapped) {}
~GenericBufReader() { ::delete[] m_buffer; }

GenericBufReader &operator=(const GenericBufReader &other)
{
Expand Down Expand Up @@ -102,7 +108,7 @@ class GenericBufReader

// Read into the buffer.
const size_t wanted = count - m_size;
const size_t actual = LexIO::Read<T>(&m_buffer[m_size], wanted, m_wrapped);
const size_t actual = Read<READER>(&m_buffer[m_size], wanted, m_wrapped);
m_size += actual;
return BufferView{m_buffer, m_size};
}
Expand All @@ -116,6 +122,24 @@ class GenericBufReader
std::copy(&m_buffer[count], &m_buffer[m_size], &m_buffer[0]);
m_size -= count;
}

template <typename = std::enable_if_t<IsWriterV<READER>>>
size_t LexWrite(const uint8_t *src, const size_t count)
{
return Write<READER>(m_wrapped, src, count);
}

template <typename = std::enable_if_t<IsWriterV<READER>>>
void LexFlush()
{
Flush<READER>(m_wrapped);
}

template <typename = std::enable_if_t<IsSeekableV<READER>>>
size_t LexSeek(const SeekPos pos)
{
return Seek<READER>(m_wrapped, pos);
}
};

} // namespace LexIO
4 changes: 4 additions & 0 deletions tests/test_bufreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ static LexIO::VectorStream GetStream()

using VectorBufReader = LexIO::GenericBufReader<LexIO::VectorStream>;

static_assert(LexIO::IsBufferedReaderV<VectorBufReader>, "VectorBufReader is not a BufferedReader");
static_assert(LexIO::IsWriterV<VectorBufReader>, "VectorBufReader is not a Writer");
static_assert(LexIO::IsSeekableV<VectorBufReader>, "VectorBufReader is not a Seekable");

TEST_CASE("FillBuffer, single call")
{
auto stream = GetStream();
Expand Down

0 comments on commit d61cc5d

Please sign in to comment.