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 {