NBEngine/engine/NBCore/SmartStreams.hpp
2026-01-14 03:05:10 -06:00

330 lines
9.5 KiB
C++

#pragma once
#ifndef _NB_SMARTSTREAM
#define _NB_SMARTSTREAM
#include <array>
#include <iostream>
#include <memory>
#include <string>
#include <sstream>
#include <type_traits>
#include <utility>
#include <vector>
namespace nb {
template <typename StreamType, typename... Mixins>
class SmartStream;
template<typename StreamFormat, typename U, typename Mix>
struct MixinHasProcess {
protected:
template <typename M>
static auto test(int)->decltype(
M::process(std::declval<StreamFormat&>(), std::declval<const U&>()),
std::true_type{}
);
template <typename>
static std::false_type test(...);
public:
static const bool value = decltype(test<Mix>(0))::value;
};
template<typename StreamFormat, typename U, typename... Mixins>
struct PackHasProcess;
template<typename StreamFormat, typename U, typename Mix>
struct PackHasProcess<StreamFormat, U, Mix> {
static const bool value = MixinHasProcess<StreamFormat, U, Mix>::value;
using type = typename std::conditional<
value,
Mix,
void
>::type;
};
template<typename StreamFormat, typename U, typename Mix1, typename... Mixins>
struct PackHasProcess<StreamFormat, U, Mix1, Mixins...> {
protected:
static const bool base_value = MixinHasProcess<StreamFormat, U, Mix1>::value;
public:
static const bool value = std::conditional<
base_value,
std::true_type,
typename PackHasProcess<StreamFormat, U, Mixins...>::value
>::type::value;
using type = typename std::conditional<
base_value,
Mix1,
typename PackHasProcess<StreamFormat, U, Mixins...>::type
>::type;
};
template<typename ST, typename... Mixins>
class SmartStream<ST, Mixins...> : public virtual Mixins... {
using StreamType = typename std::conditional<
std::is_base_of<std>::value
>::type;
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 typename std::enable_if<PackHasProcess<StreamFmt, U, Mixins...>::value, void>::type
toStream(SmartStream& stream, const U& val, const StreamFmt* fmtas=nullptr) {
PackHasProcess<StreamFmt, U, Mixins...>::type::process(stream, val);
}
template <typename U, typename StreamFmt=SmartStream<StreamType, Mixins...>>
static typename std::enable_if<!PackHasProcess<StreamFmt, U, Mixins...>::value, void>::type
toStream(SmartStream& stream, const U& val, const 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...>::toStream(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>;
class TerminalBufferController {
template <typename T>
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";
}
std::string toANSI(const unsigned int& color) {
return "\x1b[38;5;"+std::to_string(color)+"m";
}
template <typename T>
void switchCoutBuf(T val) {
}
/* 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>
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>
struct SmartText<std::string, Derived> : SmartTextBase {
template <std::size_t N>
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<typename C, typename T>
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 <>
struct SmartText<std::string, void> : SmartTextBase {
template <std::size_t N>
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<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();
}
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;
}
template <typename U>
struct TerminalColor : public SmartText<U, TerminalColor<U>> {
typedef SmartText<U, TerminalColor<U>> Base;
using Base::msg;
explicit TerminalColor(unsigned int color, const U& val)
: Base(val), colorSequence(toANSI(color)) { }
explicit TerminalColor(const RGB& color, const U& val)
: Base(val), colorSequence(toANSI(color)) { }
TerminalColor(const TerminalColor&) = default;
const std::string colorSequence;
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());
if (&stream == &std::cout) {
stream << colorSequence << msg << "\x1b[0m";
} else {
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