Trying yet another scheme, back to a stream wrapper but with mixins this time.
This commit is contained in:
parent
0bb5bff559
commit
91ba24703a
@ -4,14 +4,68 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nb {
|
namespace nb {
|
||||||
|
|
||||||
|
template <typename StreamType, typename... Mixins>
|
||||||
|
class SmartStream;
|
||||||
|
|
||||||
|
template<typename C, typename T, typename... Mixins>
|
||||||
|
class SmartStream<std::basic_ostream<C, T>, Mixins...> : public virtual Mixins... {
|
||||||
|
using StreamType = std::basic_ostream<C, T>;
|
||||||
|
protected:
|
||||||
|
StreamType* const _stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SmartStream(StreamType& stream) : _stream(&stream) {}
|
||||||
|
|
||||||
|
StreamType* getStream() const { return _stream; }
|
||||||
|
|
||||||
|
using Mixins::process...;
|
||||||
|
|
||||||
|
template <typename U, typename StreamFmt=SmartStream<StreamType, Mixins...>>
|
||||||
|
static void process(SmartStream& stream, const U& val, StreamFmt* fmtas=nullptr) {
|
||||||
|
*(stream._stream) << val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ST, typename U, typename... Mixes>
|
||||||
|
friend SmartStream<ST, Mixes...>& operator<<(SmartStream<ST, Mixes...>& stream, const U& val) {
|
||||||
|
SmartStream<ST, Mixes...>::process(stream, val);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SmartText {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SmartStreamFormatter {
|
||||||
|
template <typename StreamType, typename... M>
|
||||||
|
static void process(SmartStream<StreamType, M...>& stream, const SmartText& val, StreamType* fmtas = nullptr) {
|
||||||
|
*(stream.getStream()) << val.x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
/*namespace nb {
|
||||||
|
|
||||||
using RGB = std::array<unsigned char, 3>;
|
using RGB = std::array<unsigned char, 3>;
|
||||||
|
|
||||||
|
class TerminalBufferController {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
friend void switchCoutBuf(T);
|
||||||
|
private:
|
||||||
|
static auto terminal_buffer = std::cout.rdbuf();
|
||||||
|
TerminalBufferController();
|
||||||
|
};
|
||||||
|
|
||||||
std::string toANSI(const RGB& color) {
|
std::string toANSI(const RGB& color) {
|
||||||
return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+
|
return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+
|
||||||
";"+std::to_string(color[2])+"m";
|
";"+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";
|
return "\x1b[38;5;"+std::to_string(color)+"m";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename Derived=void>
|
template <typename T>
|
||||||
struct SmartText {
|
void switchCoutBuf(T val) {
|
||||||
SmartText(const U& val) : msg(val) {}
|
|
||||||
|
|
||||||
const U msg;
|
}
|
||||||
|
|
||||||
|
/* class TextStream {
|
||||||
|
virtual void write(std::)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SmartTextBase {
|
||||||
|
virtual std::string toString(std::ostream&) const = 0;
|
||||||
|
virtual ~SmartTextBase() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U, typename Derived=void>
|
||||||
|
struct SmartText;
|
||||||
|
|
||||||
|
template <typename U, typename Derived>
|
||||||
|
struct SmartText<U, Derived> : SmartTextBase {
|
||||||
|
explicit SmartText(const U& val) : msg(val) {}
|
||||||
|
|
||||||
|
SmartText(const SmartText&) = default;
|
||||||
|
|
||||||
template<typename C, typename T>
|
template<typename C, typename T>
|
||||||
void process(std::basic_ostream<C,T>& stream) const;
|
std::string toString(std::basic_ostream<C,T>& stream) const {
|
||||||
|
return static_cast<const Derived&>(*this).toString(stream);
|
||||||
|
}
|
||||||
|
std::string toString(std::ostream& stream) const override {
|
||||||
|
return static_cast<const Derived&>(*this).toString(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
U msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct SmartText<U, void> : SmartTextBase {
|
||||||
|
explicit SmartText(const U& val) : msg(val) {}
|
||||||
|
|
||||||
|
SmartText(const SmartText&) = default;
|
||||||
|
|
||||||
|
template<typename C, typename T>
|
||||||
|
std::string toString(std::basic_ostream<C,T>& 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 <typename Derived>
|
template <typename Derived>
|
||||||
struct SmartText<std::string, Derived> {
|
struct SmartText<std::string, Derived> : SmartTextBase {
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
SmartText(char const(&val) [N]) : msg(val) {}
|
SmartText(char const(&val) [N]) : msg(val) {}
|
||||||
SmartText(const std::string& val) : msg(val) {}
|
SmartText(const std::string& val) : msg(val) {}
|
||||||
SmartText(const char* val) : msg(val) {}
|
SmartText(const char* val) : msg(val) {}
|
||||||
|
|
||||||
const std::string msg;
|
SmartText(const SmartText&) = default;
|
||||||
|
|
||||||
template<typename C, typename T>
|
template<typename C, typename T>
|
||||||
void process(std::basic_ostream<C,T>& stream) const;
|
std::string toString(std::basic_ostream<C,T>& stream) const {
|
||||||
|
return static_cast<const Derived&>(*this).toString(stream);
|
||||||
|
}
|
||||||
|
std::string toString(std::ostream& stream) const override {
|
||||||
|
return static_cast<const Derived&>(*this).toString(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename U, typename Derived>
|
template <>
|
||||||
template <typename C, typename T>
|
struct SmartText<std::string, void> : SmartTextBase {
|
||||||
void SmartText<U,Derived>::process(std::basic_ostream<C,T>& stream) const {
|
template <std::size_t N>
|
||||||
if (std::is_void<Derived>::value) {
|
SmartText(char const(&val) [N]) : msg(val) {}
|
||||||
stream << msg;
|
SmartText(const std::string& val) : msg(val) {}
|
||||||
} else {
|
SmartText(const char* val) : msg(val) {}
|
||||||
static_cast<Derived*>(this)->process(stream);
|
|
||||||
}
|
SmartText(const SmartText&) = default;
|
||||||
}
|
|
||||||
|
|
||||||
template<typename C, typename T, typename U, typename D>
|
template<typename C, typename T>
|
||||||
std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& stream, const SmartText<U,D>& smt) {
|
std::string toString(std::basic_ostream<C,T>& stream) const {
|
||||||
if (std::is_void<D>::value) {
|
std::stringstream sstr;
|
||||||
stream << smt.msg;
|
auto stream_buf = stream.rdbuf(sstr.rdbuf());
|
||||||
} else {
|
stream << msg;
|
||||||
static_cast<const D*>(&smt)->process(stream);
|
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<typename C, typename T>
|
||||||
|
std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& stream, const SmartTextBase& smt) {
|
||||||
|
stream << smt.toString(stream);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,19 +198,78 @@ struct TerminalColor : public SmartText<U, TerminalColor<U>> {
|
|||||||
explicit TerminalColor(const RGB& color, const U& val)
|
explicit TerminalColor(const RGB& color, const U& val)
|
||||||
: Base(val), colorSequence(toANSI(color)) { }
|
: Base(val), colorSequence(toANSI(color)) { }
|
||||||
|
|
||||||
|
TerminalColor(const TerminalColor&) = default;
|
||||||
|
|
||||||
const std::string colorSequence;
|
const std::string colorSequence;
|
||||||
|
|
||||||
template <typename C, typename T>
|
template <typename C, typename T>
|
||||||
void process(std::basic_ostream<C, T>& stream) const {
|
std::string toString(std::basic_ostream<C, T>& stream) const {
|
||||||
|
std::stringstream sstr;
|
||||||
|
auto stream_buf = stream.rdbuf(sstr.rdbuf());
|
||||||
if (&stream == &std::cout) {
|
if (&stream == &std::cout) {
|
||||||
stream << colorSequence << msg << "\x1b[0m";
|
stream << colorSequence << msg << "\x1b[0m";
|
||||||
} else {
|
} else {
|
||||||
stream << msg;
|
stream << msg;
|
||||||
}
|
}
|
||||||
|
stream.rdbuf(stream_buf);
|
||||||
|
return sstr.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
std::vector<std::shared_ptr<T>> variadicToBaseVec(std::vector<std::shared_ptr<T>> vec, const U& val) {
|
||||||
|
static_assert(std::is_base_of<T, U>::value, "Push value type must be base of vector base type.");
|
||||||
|
vec.push(static_cast<std::shared_ptr<T>>(std::make_shared(val)));
|
||||||
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... U>
|
||||||
|
std::vector<std::shared_ptr<T>> variadicToBaseVec(std::vector<std::shared_ptr<T>> vec, const U&... val) {
|
||||||
|
vec.push(static_cast<std::shared_ptr<T>>(std::make_shared(val...)));
|
||||||
|
return variadicToBaseVec<T, U...>(vec, val...);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SmartGroup : public SmartText<std::vector<std::shared_ptr<SmartTextBase>>, SmartGroup> {
|
||||||
|
using SmartVec = std::vector<std::shared_ptr<SmartTextBase>>;
|
||||||
|
typedef SmartText<SmartVec, SmartGroup> Base;
|
||||||
|
using Base::msg;
|
||||||
|
|
||||||
|
SmartGroup(const SmartGroup&) = default;
|
||||||
|
|
||||||
|
template<typename... Types>
|
||||||
|
explicit SmartGroup(const Types&... vals)
|
||||||
|
: Base(variadicToBaseVec<SmartTextBase, Types...>({}, vals...)) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push(const T& val) {
|
||||||
|
msg = variadicToBaseVec(msg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
SmartGroup operator+(const T& val) {
|
||||||
|
SmartGroup ret(*this);
|
||||||
|
ret.push(val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C, typename T>
|
||||||
|
std::string toString(std::basic_ostream<C, T>& stream) const {
|
||||||
|
std::stringstream sstr;
|
||||||
|
auto stream_buf = stream.rdbuf(sstr.rdbuf());
|
||||||
|
for (const std::shared_ptr<SmartTextBase>& st : msg) {
|
||||||
|
stream << st;
|
||||||
|
}
|
||||||
|
stream.rdbuf(stream_buf);
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename lU, typename lD, typename rU, typename rD>
|
||||||
|
SmartGroup operator+(const SmartText<lU, lD>& lhs, const SmartText<rU, rD>& rhs) {
|
||||||
|
return SmartGroup(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
#endif // _NB_SMARTSTREAM
|
#endif // _NB_SMARTSTREAM
|
||||||
@ -10,7 +10,10 @@
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
auto test = nb::TerminalColor(9, 2030);
|
nb::SmartStream<decltype(std::cout), nb::SmartStreamFormatter> stout(std::cout);
|
||||||
|
|
||||||
|
stout << nb::SmartText{5} << "\ngoop\n";
|
||||||
|
/* nb::SmartText test(100);
|
||||||
|
|
||||||
std::cout << test;
|
std::cout << test;
|
||||||
|
|
||||||
@ -19,7 +22,7 @@ int main() {
|
|||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
file << test;
|
file << test;
|
||||||
}
|
}
|
||||||
file.close();
|
file.close(); */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user