#include "MockOutputPath.h" #include "Utils/ObjStream.h" #include namespace { class MockFileBuffer final : public std::streambuf { public: MockFileBuffer() : m_pos(0u) { } std::vector data() { return std::move(m_data); } protected: int_type overflow(const int_type b) override { if (!std::char_traits::eq_int_type(b, std::char_traits::eof())) { m_data.insert(m_data.begin() + static_cast(m_pos), static_cast(b)); ++m_pos; } return b; } std::streamsize xsputn(const char* ptr, const std::streamsize count) override { const auto curSize = m_data.size(); const auto overrideCount = m_pos < curSize ? std::min(curSize - m_pos, static_cast(count)) : 0u; const auto insertCount = count - overrideCount; if (overrideCount > 0) { std::memcpy(&m_data[m_pos], ptr, overrideCount); m_pos += overrideCount; ptr += overrideCount; } if (insertCount > 0) { m_data.insert(m_data.begin() + static_cast(m_pos), ptr, ptr + insertCount); m_pos += static_cast(insertCount); } return count; } pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override { if (dir == std::ios::beg) return seekpos(off, mode); if (dir == std::ios::cur) return seekpos(static_cast(m_pos) + off, mode); if (off < static_cast(m_data.size())) return seekpos(static_cast(m_data.size()) - off, mode); return std::char_traits::eof(); } pos_type seekpos(const pos_type pos, std::ios_base::openmode) override { if (pos > m_data.size()) m_data.resize(static_cast(pos)); m_pos = static_cast(pos); return pos; } private: std::vector m_data; std::size_t m_pos; }; class MockFileWrapper final : public std::ostream { public: MockFileWrapper(std::string name, std::vector& files) : std::ostream(&m_buf), m_name(std::move(name)), m_files(files) { } ~MockFileWrapper() override { m_files.emplace_back(std::move(m_name), m_buf.data()); } private: MockFileBuffer m_buf; std::string m_name; std::vector& m_files; }; } // namespace MockOutputFile::MockOutputFile() = default; MockOutputFile::MockOutputFile(std::string name, std::vector data) : m_name(std::move(name)), m_data(std::move(data)) { } std::string MockOutputFile::AsString() const { return std::string(reinterpret_cast(m_data.data()), m_data.size()); } std::unique_ptr MockOutputPath::Open(const std::string& fileName) { return std::make_unique(fileName, m_files); } const MockOutputFile* MockOutputPath::GetMockedFile(const std::string& name) const { for (const auto& file : m_files) { if (file.m_name == name) return &file; } return nullptr; } const std::vector& MockOutputPath::GetMockedFileList() const { return m_files; }