diff --git a/engine/NBCore/SmartStreams.hpp b/engine/NBCore/SmartStreams.hpp index e5fcd14..17bde86 100644 --- a/engine/NBCore/SmartStreams.hpp +++ b/engine/NBCore/SmartStreams.hpp @@ -4,14 +4,68 @@ #include #include +#include #include +#include #include -#include +#include +#include namespace nb { +template +class SmartStream; + +template +class SmartStream, Mixins...> : public virtual Mixins... { + using StreamType = std::basic_ostream; +protected: + StreamType* const _stream; + +public: + SmartStream(StreamType& stream) : _stream(&stream) {} + + StreamType* getStream() const { return _stream; } + + using Mixins::process...; + + template > + static void process(SmartStream& stream, const U& val, StreamFmt* fmtas=nullptr) { + *(stream._stream) << val; + } + + template + friend SmartStream& operator<<(SmartStream& stream, const U& val) { + SmartStream::process(stream, val); + return stream; + } +}; + +struct SmartText { + int x; +}; + +struct SmartStreamFormatter { + template + static void process(SmartStream& stream, const SmartText& val, StreamType* fmtas = nullptr) { + *(stream.getStream()) << val.x; + } +}; + +} +/*namespace nb { + using RGB = std::array; +class TerminalBufferController { + + template + friend void switchCoutBuf(T); +private: + static auto terminal_buffer = std::cout.rdbuf(); + TerminalBufferController(); +}; + std::string toANSI(const RGB& color) { return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+ ";"+std::to_string(color[2])+"m"; @@ -21,46 +75,116 @@ std::string toANSI(const unsigned int& color) { return "\x1b[38;5;"+std::to_string(color)+"m"; } -template -struct SmartText { - SmartText(const U& val) : msg(val) {} +template +void switchCoutBuf(T val) { - const U msg; +} + +/* class TextStream { + virtual void write(std::) +}; + +struct SmartTextBase { + virtual std::string toString(std::ostream&) const = 0; + virtual ~SmartTextBase() = default; +}; + +template +struct SmartText; + +template +struct SmartText : SmartTextBase { + explicit SmartText(const U& val) : msg(val) {} + + SmartText(const SmartText&) = default; template - void process(std::basic_ostream& stream) const; + std::string toString(std::basic_ostream& stream) const { + return static_cast(*this).toString(stream); + } + std::string toString(std::ostream& stream) const override { + return static_cast(*this).toString(stream); + } + + U msg; +}; + +template +struct SmartText : SmartTextBase { + explicit SmartText(const U& val) : msg(val) {} + + SmartText(const SmartText&) = default; + + template + std::string toString(std::basic_ostream& stream) const { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); + stream << msg; + stream.rdbuf(stream_buf); + return sstr.str(); + } + std::string toString(std::ostream& stream) const override { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); + stream << msg; + stream.rdbuf(stream_buf); + return sstr.str(); + } + + U msg; }; template -struct SmartText { +struct SmartText : SmartTextBase { template SmartText(char const(&val) [N]) : msg(val) {} SmartText(const std::string& val) : msg(val) {} SmartText(const char* val) : msg(val) {} - - const std::string msg; + + SmartText(const SmartText&) = default; template - void process(std::basic_ostream& stream) const; + std::string toString(std::basic_ostream& stream) const { + return static_cast(*this).toString(stream); + } + std::string toString(std::ostream& stream) const override { + return static_cast(*this).toString(stream); + } + + std::string msg; }; -template -template -void SmartText::process(std::basic_ostream& stream) const { - if (std::is_void::value) { - stream << msg; - } else { - static_cast(this)->process(stream); - } -} +template <> +struct SmartText : SmartTextBase { + template + SmartText(char const(&val) [N]) : msg(val) {} + SmartText(const std::string& val) : msg(val) {} + SmartText(const char* val) : msg(val) {} + + SmartText(const SmartText&) = default; -template -std::basic_ostream& operator<<(std::basic_ostream& stream, const SmartText& smt) { - if (std::is_void::value) { - stream << smt.msg; - } else { - static_cast(&smt)->process(stream); + template + std::string toString(std::basic_ostream& stream) const { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); + stream << msg; + stream.rdbuf(stream_buf); + return sstr.str(); } + std::string toString(std::ostream& stream) const override { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); + stream << msg; + stream.rdbuf(stream_buf); + return sstr.str(); + } + + std::string msg; +}; + +template +std::basic_ostream& operator<<(std::basic_ostream& stream, const SmartTextBase& smt) { + stream << smt.toString(stream); return stream; } @@ -74,19 +198,78 @@ struct TerminalColor : public SmartText> { explicit TerminalColor(const RGB& color, const U& val) : Base(val), colorSequence(toANSI(color)) { } + TerminalColor(const TerminalColor&) = default; + const std::string colorSequence; template - void process(std::basic_ostream& stream) const { + std::string toString(std::basic_ostream& stream) const { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); if (&stream == &std::cout) { stream << colorSequence << msg << "\x1b[0m"; } else { stream << msg; } + stream.rdbuf(stream_buf); + return sstr.str(); } }; - +template +std::vector> variadicToBaseVec(std::vector> vec, const U& val) { + static_assert(std::is_base_of::value, "Push value type must be base of vector base type."); + vec.push(static_cast>(std::make_shared(val))); + return vec; } +template +std::vector> variadicToBaseVec(std::vector> vec, const U&... val) { + vec.push(static_cast>(std::make_shared(val...))); + return variadicToBaseVec(vec, val...); +} + +struct SmartGroup : public SmartText>, SmartGroup> { + using SmartVec = std::vector>; + typedef SmartText Base; + using Base::msg; + + SmartGroup(const SmartGroup&) = default; + + template + explicit SmartGroup(const Types&... vals) + : Base(variadicToBaseVec({}, vals...)) {} + + template + void push(const T& val) { + msg = variadicToBaseVec(msg, val); + } + + template + SmartGroup operator+(const T& val) { + SmartGroup ret(*this); + ret.push(val); + return ret; + } + + template + std::string toString(std::basic_ostream& stream) const { + std::stringstream sstr; + auto stream_buf = stream.rdbuf(sstr.rdbuf()); + for (const std::shared_ptr& st : msg) { + stream << st; + } + stream.rdbuf(stream_buf); + return sstr.str(); + } + +}; + +template +SmartGroup operator+(const SmartText& lhs, const SmartText& rhs) { + return SmartGroup(lhs, rhs); +} + +} */ + #endif // _NB_SMARTSTREAM \ No newline at end of file diff --git a/engine/NBCore/tests/SmartStreamTest/main.cpp b/engine/NBCore/tests/SmartStreamTest/main.cpp index 35608cf..7b67419 100644 --- a/engine/NBCore/tests/SmartStreamTest/main.cpp +++ b/engine/NBCore/tests/SmartStreamTest/main.cpp @@ -10,7 +10,10 @@ int main() { - auto test = nb::TerminalColor(9, 2030); + nb::SmartStream stout(std::cout); + + stout << nb::SmartText{5} << "\ngoop\n"; +/* nb::SmartText test(100); std::cout << test; @@ -19,7 +22,7 @@ int main() { if (file.is_open()) { file << test; } - file.close(); + file.close(); */ return 0; } \ No newline at end of file