NBEngine/engine/NBCore/SmartStreams.hpp
2025-12-27 03:49:34 -06:00

92 lines
2.3 KiB
C++

#pragma once
#ifndef _NB_SMARTSTREAM
#define _NB_SMARTSTREAM
#include <array>
#include <iostream>
#include <string>
#include <type_traits>
#include <unordered_map>
namespace nb {
using RGB = std::array<unsigned char, 3>;
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 U, typename Derived=void>
struct SmartText {
SmartText(const U& val) : msg(val) {}
const U msg;
template<typename C, typename T>
void process(std::basic_ostream<C,T>& stream) const;
};
template <typename Derived>
struct SmartText<std::string, Derived> {
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) {}
const std::string msg;
template<typename C, typename T>
void process(std::basic_ostream<C,T>& stream) const;
};
template <typename U, typename Derived>
template <typename C, typename T>
void SmartText<U,Derived>::process(std::basic_ostream<C,T>& stream) const {
if (std::is_void<Derived>::value) {
stream << msg;
} else {
static_cast<Derived*>(this)->process(stream);
}
}
template<typename C, typename T, typename U, typename D>
std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& stream, const SmartText<U,D>& smt) {
if (std::is_void<D>::value) {
stream << smt.msg;
} else {
static_cast<const D*>(&smt)->process(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)) { }
const std::string colorSequence;
template <typename C, typename T>
void process(std::basic_ostream<C, T>& stream) const {
if (&stream == &std::cout) {
stream << colorSequence << msg << "\x1b[0m";
} else {
stream << msg;
}
}
};
}
#endif // _NB_SMARTSTREAM