#pragma once #include #include #include #include class log_stream { public: log_stream(): m_active(false), m_buffer(), m_log_lines() {} void log_lines(int n) { m_log_lines = n; } std::string get_log() { return m_buffer.str(); } // log to buffer void activate() { m_active = true; } // log to plain console void deactivate() { m_active = false; } template log_stream& operator<<(const T& arg) { if (m_active) { m_buffer << arg; trim_buffer(); } else { std::cout << arg; } return *this; } log_stream& operator<<( std::basic_ostream& (*func) (std::basic_ostream&) ) { if (m_active) { m_buffer << *func; trim_buffer(); } else { std::cout << *func; } return *this; } private: void trim_buffer() { std::string s = m_buffer.str(); size_t pos = s.npos; for (int i = 0; i <= m_log_lines; ++i) { pos = s.rfind("\n", pos); if (pos == s.npos) { // too few lines return; } if (pos > 0) { --pos; } } m_buffer.str(s.substr((pos <= (s.size() - 2)) ? pos + 2 : pos)); } bool m_active; std::stringstream m_buffer; int m_log_lines; }; extern log_stream log_cout;