From d4fe74b5a82ef21e7216a19369c637323101c12c Mon Sep 17 00:00:00 2001 From: pfeatherstone <45853521+pfeatherstone@users.noreply.github.com> Date: Thu, 17 Sep 2020 01:37:36 +0100 Subject: [PATCH] vectorstream updates: added seekoff and seekpos (#2179) * [DLIB] added seekpos and seekoff functions. These are necessary for functions in iostream base class to work properly. e.g. seekg. Note that in seekoff, you do NOT want to check the validity of read_pos after it has been updated. dlib::vectorstream and std::iostream work together to set EOF and/or badbit. Doing something like seekg(10000) should not throw even if the underlying buffer has 2 bytes. You should check if EOF is set and possibly call clear(). We have removed seekg from dlib::vectorstream as this adds confusion. Now std::iostream::seekg is called which somewhere down the callstack will call seekpos and/or seekoff. So there should be no diverging functionality between calling seekg on dlib::vectorstream& or std::iostream& when there is a cast. * [DLIB] vectorstream unit test is updated to run identical tests on dlib::vectorstream& and std::iostream& * [DLIB] only support read pointers and delete copy and move semantics * [DLIB] explicit tests for seekg() in different directions * [DLIB] - no need to delete the move constructor and move assign operator. This is implicitly done by deleting the copy constructor and copy assign operator. * [DLIB] - remove leftover comments. no need - use more idiomatic notation Co-authored-by: pf --- dlib/test/vectorstream.cpp | 81 +++++++++++++++++++++++++++----- dlib/vectorstream/vectorstream.h | 41 ++++++++++++---- 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/dlib/test/vectorstream.cpp b/dlib/test/vectorstream.cpp index a955961a2..6d101fff3 100644 --- a/dlib/test/vectorstream.cpp +++ b/dlib/test/vectorstream.cpp @@ -21,16 +21,10 @@ namespace logger dlog("test.vectorstream"); - -// ---------------------------------------------------------------------------------------- - - void test1() + + template + void test1_variant(std::vector& buf, stream& s) { - print_spinner(); - - std::vector buf; - vectorstream s(buf); - for (int i = -1000; i <= 1000; ++i) { char ch = i; @@ -59,7 +53,7 @@ namespace DLIB_TEST(s.get() == EOF); s.clear(); - s.seekg(6); + s.seekg(6); //Let iostream decide which path to take. In theory it could decide to use any. for (int i = -1000+6; i <= 1000; ++i) { @@ -71,13 +65,58 @@ namespace DLIB_TEST(s.peek() == EOF); DLIB_TEST(s.get() == EOF); + + s.clear(); + s.seekg(6, std::ios_base::beg); + for (int i = -1000+6; i <= 1000; ++i) + { + DLIB_TEST(s.peek() != EOF); + char ch1 = i; + char ch2 = s.get(); + DLIB_TEST(ch1 == ch2); + } + + DLIB_TEST(s.peek() == EOF); + DLIB_TEST(s.get() == EOF); + + s.clear(); + s.seekg(1000, std::ios_base::beg); //read_pos should be 1000 + DLIB_TEST(s.good()); //yep, still good + DLIB_TEST(s.peek() == char(0)); //read_pos should still be 1000 + s.seekg(6, std::ios_base::cur); //read_pos should be 1006 + + for (int i = 6; i <= 1000; ++i) + { + DLIB_TEST(s.peek() != EOF); + char ch1 = i; + char ch2 = s.get(); + DLIB_TEST(ch1 == ch2); + } + + DLIB_TEST(s.peek() == EOF); + DLIB_TEST(s.get() == EOF); + + s.clear(); + s.seekg(-6, std::ios_base::end); //read_pos should be 1995 + + for (int i = 995; i <= 1000; ++i) + { + DLIB_TEST(s.peek() != EOF); + char ch1 = i; + char ch2 = s.get(); + DLIB_TEST(ch1 == ch2); + } + + DLIB_TEST(s.peek() == EOF); + DLIB_TEST(s.get() == EOF); + std::string temp; temp = "one two three!"; + s.clear(); s.seekg(0); buf.clear(); - s.clear(); serialize(temp, s); std::string temp2; @@ -119,6 +158,26 @@ namespace DLIB_TEST(s.good() == false); } +// ---------------------------------------------------------------------------------------- + + void test1() + { + print_spinner(); + + { + std::vector buf; + vectorstream s1(buf); + test1_variant(buf, s1); + } + + { + vector buf; + dlib::vectorstream s1(buf); + std::iostream& s2 = s1; + test1_variant(buf, s2); + } + } + // ---------------------------------------------------------------------------------------- class test_vectorstream : public tester diff --git a/dlib/vectorstream/vectorstream.h b/dlib/vectorstream/vectorstream.h index a1b7b8b07..8f39debc6 100644 --- a/dlib/vectorstream/vectorstream.h +++ b/dlib/vectorstream/vectorstream.h @@ -11,7 +11,7 @@ #include #include #include "../algs.h" - +#include "../assert.h" #ifdef _MSC_VER // Disable the warning about inheriting from std::iostream 'via dominance' since this warning is a warning about @@ -43,6 +43,32 @@ namespace dlib { read_pos = pos; } + + pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out ) + { + DLIB_ASSERT(mode == std::ios_base::in, "vectorstream does not support std::ios_base::out"); + switch (dir) + { + case std::ios_base::beg: + read_pos = off; + break; + case std::ios_base::cur: + read_pos += off; + break; + case std::ios_base::end: + read_pos = buffer.size() + off; + break; + default: + break; + } + return pos_type(read_pos); + } // ------------------------ OUTPUT FUNCTIONS ------------------------ @@ -120,15 +146,10 @@ namespace dlib std::iostream(&buf), buf(buffer) {} - - std::istream& seekg ( - std::streampos pos - ) - { - buf.seekg(pos); - return *this; - } - + + vectorstream(const vectorstream& ori) = delete; + vectorstream(vectorstream&& item) = delete; + private: vector_streambuf buf; };