From de371a94a561b251821c110c69ed87e0a8fe39da Mon Sep 17 00:00:00 2001 From: Bob Polis Date: Sat, 25 Apr 2020 16:40:42 +0200 Subject: [PATCH] fixed and improved single buffer version, added seeking as well --- fdiobuf.cpp | 59 ++++++++++++++++++++++++++++++++++++++--------------- libscio.hpp | 9 ++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/fdiobuf.cpp b/fdiobuf.cpp index 7780d90..1529b99 100644 --- a/fdiobuf.cpp +++ b/fdiobuf.cpp @@ -28,23 +28,50 @@ std::streamsize sc::io::fdiobuf::xsgetn(char* s, std::streamsize n) { } std::streambuf::int_type sc::io::fdiobuf::overflow(std::streambuf::int_type c) { - if (c != EOF) { - int res; - if ((res = ::write(_fd, &c, 1)) != 1) { - return EOF; - } - else { - std::cerr << "write result = " << res << ", errno = " << errno << '\n'; - } - } - return c; + if (c != EOF) { + int res; + if ((res = ::write(_fd, &c, 1)) != 1) { + return EOF; + } + else { + std::cerr << "write result = " << res << ", errno = " << errno << '\n'; + } + } + _ch = c; + setp(&_ch, &_ch + 1); + return c; } std::streamsize sc::io::fdiobuf::xsputn(const char* s, std::streamsize num) { - int res = ::write(_fd, s, num); - if (res != num) { - std::cerr << "write result = " << res << ", errno = " << errno << '\n'; - return EOF; - } - return res; + int res = ::write(_fd, s, num); + if (res != num) { + std::cerr << "write result = " << res << ", errno = " << errno << '\n'; + return EOF; + } + return res; +} + +std::streambuf::pos_type sc::io::fdiobuf::seekoff(std::streambuf::off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode /*which*/) { + int whence; + switch (dir) { + case std::ios_base::beg: whence = SEEK_SET; break; + case std::ios_base::end: whence = SEEK_END; break; + case std::ios_base::cur: whence = SEEK_CUR; break; + default: throw std::runtime_error("invalid seekdir"); + } + return ::lseek(_fd, off, whence); +} + +std::streambuf::pos_type sc::io::fdiobuf::seekpos(std::streambuf::pos_type pos, + std::ios_base::openmode /*which*/) { + return ::lseek(_fd, pos, SEEK_SET); +} + +std::streambuf::int_type sc::io::fdiobuf::pbackfail(std::streambuf::int_type /*c*/) { + if (::lseek(_fd, -1, SEEK_CUR) == -1) { + return EOF; + } + return 0; } diff --git a/libscio.hpp b/libscio.hpp index 70480ad..e5ce3a1 100644 --- a/libscio.hpp +++ b/libscio.hpp @@ -40,6 +40,15 @@ namespace sc { // output int_type overflow(int_type c) override; std::streamsize xsputn(const char* s, std::streamsize num) override; + + // stream offset positioning + pos_type seekoff(off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which + = std::ios_base::in | std::ios_base::out) override; + pos_type seekpos(pos_type pos, std::ios_base::openmode which + = std::ios_base::in | std::ios_base::out) override; + int_type pbackfail(int_type c = EOF) override; }; class fdostream : public std::ostream {