From d7987b33da950e5864d68727a578e89e71db8845 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 18 Dec 2014 16:48:48 +0300 Subject: [PATCH] Allow ContainerRWops to work with both const and non-const containers Analogus to how StreamRWops work. Also add more tests for ContainerRWops. --- SDL2pp/ContainerRWops.hh | 86 ++++++++++------------------------------ tests/test_rwops.cc | 22 +++++++++- 2 files changed, 42 insertions(+), 66 deletions(-) diff --git a/SDL2pp/ContainerRWops.hh b/SDL2pp/ContainerRWops.hh index bf49afe..7803564 100644 --- a/SDL2pp/ContainerRWops.hh +++ b/SDL2pp/ContainerRWops.hh @@ -24,16 +24,36 @@ #include +#include #include namespace SDL2pp { -template +template class ContainerRWops : public CustomRWops { protected: C& container_; size_t position_; +private: + template + typename std::enable_if::value, size_t>::type WriteHelper(const void* ptr, size_t size, size_t maxnum) { + if (position_ + size * maxnum > container_.size()) + container_.resize(position_ + size * maxnum); + + std::copy(reinterpret_cast(ptr), reinterpret_cast(ptr) + size * maxnum, container_.begin() + position_); + + position_ += size * maxnum; + + return maxnum; + } + + template + typename std::enable_if::value, size_t>::type WriteHelper(const void*, size_t, size_t) { + SDL_SetError("Can't write to read-only container"); + return 0; + } + public: ContainerRWops(C& container) : container_(container), position_(0) { } @@ -74,69 +94,7 @@ public: } virtual size_t Write(const void* ptr, size_t size, size_t maxnum) override { - if (position_ + size * maxnum > container_.size()) - container_.resize(position_ + size * maxnum); - - std::copy(reinterpret_cast(ptr), reinterpret_cast(ptr) + size * maxnum, container_.begin() + position_); - - position_ += size * maxnum; - - return maxnum; - } - - virtual int Close() override { - return 0; - } -}; - -template -class ConstContainerRWops : public CustomRWops { -protected: - const C& container_; - size_t position_; - -public: - ConstContainerRWops(const C& container) : container_(container), position_(0) { - } - - ConstContainerRWops(const ConstContainerRWops&) = default; - ConstContainerRWops& operator=(const ConstContainerRWops&) = delete; - ConstContainerRWops(ConstContainerRWops&&) noexcept = default; - ConstContainerRWops& operator=(ConstContainerRWops&&) = delete; - - virtual Sint64 Seek(Sint64 offset, int whence) override { - switch (whence) { - case RW_SEEK_SET: - position_ = offset; - break; - case RW_SEEK_CUR: - position_ = position_ + offset; - break; - case RW_SEEK_END: - position_ = container_.size() + offset; - break; - default: - throw std::logic_error("Unexpected whence value for ConstContainerRWops::Seek"); - } - return position_; - } - - virtual size_t Read(void* ptr, size_t size, size_t maxnum) override { - if (position_ + size > container_.size()) - return 0; - - int toread = std::min((container_.size() - position_), maxnum * size); - - std::copy(container_.begin() + position_, container_.begin() + position_ + toread, reinterpret_cast(ptr)); - - position_ += toread; - - return toread / size; - } - - virtual size_t Write(const void*, size_t, size_t) override { - SDL_SetError("Can't write to read-only container"); - return 0; + return WriteHelper(ptr, size, maxnum); } virtual int Close() override { diff --git a/tests/test_rwops.cc b/tests/test_rwops.cc index 7ae3858..9cc2a2a 100644 --- a/tests/test_rwops.cc +++ b/tests/test_rwops.cc @@ -119,7 +119,7 @@ BEGIN_TEST() { const std::vector buffer = { 'a', 'b', 'c', 'd' }; - RWops rw((ConstContainerRWops>(buffer))); + RWops rw((ContainerRWops>(buffer))); { // Read via C++ @@ -134,12 +134,30 @@ BEGIN_TEST() } { - // Write + // Write to const container fails char buf[4] = {0}; EXPECT_TRUE(rw.Write(buf, 1, 4) == 0); EXPECT_TRUE(rw.Write(buf, 4, 1) == 0); } + + { + // Write to non-const container + std::vector vec; + + RWops rw((ContainerRWops>(vec))); + + char buf[4] = {'a', 'b', 'c', 'd'}; + + EXPECT_TRUE(rw.Write(buf, 1, 4) == 4); + EXPECT_TRUE(rw.Write(buf, 4, 1) == 1); + + EXPECT_TRUE(rw.Seek(2, SEEK_SET) == 2); + EXPECT_TRUE(rw.Write(buf, 2, 2) == 2); + + EXPECT_TRUE(vec.size() == 8); + EXPECT_TRUE(std::string(vec.data(), 8) == "ababcdcd"); + } } // Test for StreamRWops