From c11367ac7accbbff694befc754132c3da8b76540 Mon Sep 17 00:00:00 2001 From: vng Date: Thu, 24 Nov 2011 23:21:39 +0300 Subject: [PATCH] Add ReaderStreamBuf and WriterStreamBuf for std::istream and std::ostream interfaces. --- coding/coding.pro | 2 ++ coding/coding_tests/reader_test.cpp | 34 ++++++++++++++++++++++++ coding/reader_streambuf.cpp | 40 +++++++++++++++++++++++++++++ coding/reader_streambuf.hpp | 26 +++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 coding/reader_streambuf.cpp create mode 100644 coding/reader_streambuf.hpp diff --git a/coding/coding.pro b/coding/coding.pro index f02f3c46f1..c740da9863 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -26,6 +26,7 @@ SOURCES += \ reader.cpp \ zip_reader.cpp \ mmap_reader.cpp \ + reader_streambuf.cpp \ HEADERS += \ internal/xmlparser.h \ @@ -79,3 +80,4 @@ HEADERS += \ read_write_utils.hpp \ file_reader_stream.hpp \ file_writer_stream.hpp \ + reader_streambuf.hpp \ diff --git a/coding/coding_tests/reader_test.cpp b/coding/coding_tests/reader_test.cpp index bb0b55a85b..225ae83335 100644 --- a/coding/coding_tests/reader_test.cpp +++ b/coding/coding_tests/reader_test.cpp @@ -6,6 +6,10 @@ #include "../file_reader.hpp" #include "../file_writer.hpp" #include "../buffer_reader.hpp" +#include "../reader_streambuf.hpp" + +#include "../../std/fstream.hpp" + namespace { @@ -97,3 +101,33 @@ UNIT_TEST(SharedMemReader) TEST_EQUAL(s1, "123", ()); TEST_EQUAL(s2, "123", ()); } + +UNIT_TEST(ReaderStreamBuf) +{ + string const name = "test.txt"; + + { + WriterStreamBuf buffer(new FileWriter(name)); + ostream s(&buffer); + s << "hey!" << '\n' << 1 << '\n' << 3.14 << '\n' << 0x0102030405060708ull << std::endl; + } + + { + ReaderStreamBuf buffer(new FileReader(name)); + istream s(&buffer); + + std::string str; + int i; + double d; + unsigned long long ull; + + s >> str >> i >> d >> ull; + + TEST_EQUAL(str, "hey!", ()); + TEST_EQUAL(i, 1, ()); + TEST_ALMOST_EQUAL(d, 3.14, ()); + TEST_EQUAL(ull, 0x0102030405060708ull, ()); + } + + FileWriter::DeleteFileX(name); +} diff --git a/coding/reader_streambuf.cpp b/coding/reader_streambuf.cpp new file mode 100644 index 0000000000..3cfaef1fc8 --- /dev/null +++ b/coding/reader_streambuf.cpp @@ -0,0 +1,40 @@ +#include "reader_streambuf.hpp" +#include "reader.hpp" + +#include "../std/algorithm.hpp" + + +ReaderStreamBuf::ReaderStreamBuf(Reader * p) +: m_p(p), m_pos(0), m_size(p->Size()) +{ +} + +ReaderStreamBuf::~ReaderStreamBuf() +{ + delete m_p; +} + +std::streamsize ReaderStreamBuf::xsgetn(char_type * s, std::streamsize n) +{ + uint64_t const count = min(static_cast(n), m_size - m_pos); + if (count > 0) + { + m_p->Read(m_pos, s, count); + m_pos += count; + } + return count; +} + +ReaderStreamBuf::int_type ReaderStreamBuf::underflow() +{ + std::streamsize s = xsgetn(m_buf, sizeof(m_buf)); + if (s > 0) + { + setg(m_buf, m_buf, m_buf + s); + return traits_type::to_int_type(m_buf[0]); + } + else + { + return traits_type::eof(); + } +} diff --git a/coding/reader_streambuf.hpp b/coding/reader_streambuf.hpp new file mode 100644 index 0000000000..c36e383461 --- /dev/null +++ b/coding/reader_streambuf.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "../std/iostream.hpp" + +class Reader; + +class ReaderStreamBuf : public std::streambuf +{ + Reader * m_p; + uint64_t m_pos, m_size; + +public: + typedef std::streambuf::traits_type traits_type; + typedef std::streambuf::char_type char_type; + typedef std::streambuf::int_type int_type; + + /// Takes the ownership of p. Reader should be allocated in dynamic memory. + ReaderStreamBuf(Reader * p); + virtual ~ReaderStreamBuf(); + +private: + virtual std::streamsize xsgetn(char_type * s, std::streamsize n); + virtual int_type underflow(); + + char m_buf[1]; +};