145 lines
3.7 KiB
C++
145 lines
3.7 KiB
C++
#pragma once
|
|
#ifndef _NB_SMARTSTREAM
|
|
#define _NB_SMARTSTREAM
|
|
|
|
#include <ostream>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace nb {
|
|
|
|
typedef std::pair<unsigned int, std::string> SmartTextKV;
|
|
|
|
//template<typename T=std::string>
|
|
struct SmartText {
|
|
std::string msg;
|
|
SmartTextKV kv = {0, ""};
|
|
};
|
|
|
|
typedef std::string (*SmartTextFormatter)(std::string, std::string);
|
|
|
|
typedef std::unordered_map<unsigned int, SmartTextFormatter> SmartFormatMap;
|
|
|
|
template <typename ST>
|
|
class SmartOStreamBase {
|
|
public:
|
|
virtual void process(const SmartText&) = 0;
|
|
|
|
static const SmartFormatMap Formatters;
|
|
|
|
protected:
|
|
SmartOStreamBase(ST& stream) : _ostream{&stream} {}
|
|
ST* _ostream;
|
|
|
|
};
|
|
|
|
template<typename ST, typename Derived>
|
|
class SmartOStreamBaseImpl;
|
|
|
|
template<typename ST, typename Derived = void>
|
|
class SmartOStream;
|
|
|
|
template<typename ST, typename STD, typename Derived>
|
|
class SmartOStreamBaseImpl<SmartOStream<ST, STD>, Derived> : public SmartOStreamBase<SmartOStream<ST, STD>>{
|
|
public:
|
|
using StreamType = SmartOStream<ST, STD>;
|
|
using Base = SmartOStreamBase<StreamType>;
|
|
using Base::process;
|
|
using Base::Formatters;
|
|
|
|
protected:
|
|
using Base::Base;
|
|
};
|
|
|
|
template<typename C, typename T, typename Derived>
|
|
class SmartOStreamBaseImpl<std::basic_ostream<C, T>, Derived> : public SmartOStreamBase<std::basic_ostream<C, T>> {
|
|
public:
|
|
using StreamType = std::basic_ostream<C, T>;
|
|
using Base = SmartOStreamBase<StreamType>;
|
|
using Base::process;
|
|
using Base::Formatters;
|
|
|
|
protected:
|
|
using Base::Base;
|
|
};
|
|
|
|
|
|
template<typename StreamType, typename Derived>
|
|
class SmartOStream : public SmartOStreamBaseImpl<StreamType, Derived> {
|
|
template <typename ST, typename D, typename U>
|
|
friend SmartOStream<ST, D>& operator<<(SmartOStream<ST, D>&, const U&);
|
|
public:
|
|
using Base = SmartOStreamBaseImpl<StreamType, Derived>;
|
|
SmartOStream(StreamType& stream) : Base(stream) {}
|
|
|
|
StreamType* getStream() const { return _ostream; }
|
|
|
|
template <typename X>
|
|
void process(const X& val) {
|
|
*_ostream << val;
|
|
}
|
|
|
|
virtual void process(const SmartText&);
|
|
|
|
static const SmartFormatMap Formatters;
|
|
|
|
protected:
|
|
using Base::_ostream;
|
|
|
|
static std::string defaultFormatter(std::string msg, std::string fmt) {
|
|
return msg;
|
|
}
|
|
};
|
|
|
|
template<typename ST, typename D>
|
|
const SmartFormatMap SmartOStream<ST, D>::Formatters = {
|
|
{0, defaultFormatter}
|
|
};
|
|
|
|
template <typename ST, typename D, typename U>
|
|
SmartOStream<ST, D>& operator<<(SmartOStream<ST, D>& stream, const U& msg) {
|
|
using Derived = typename std::conditional<std::is_void<D>::value, SmartOStream<ST, void>, D>::type;
|
|
static_cast<Derived*>(&stream)->process(msg);
|
|
return stream;
|
|
}
|
|
|
|
template<typename ST, typename D>
|
|
void SmartOStream<ST, D>::process(const SmartText& msg) {
|
|
using Derived = typename std::conditional<std::is_void<D>::value, SmartOStream<ST, void>, D>::type;
|
|
try {
|
|
*_ostream << Derived::Formatters.at(msg.kv.first)(msg.msg, msg.kv.second);
|
|
} catch (const std::out_of_range& e) {
|
|
*_ostream << Derived::Formatters.at(0)(msg.msg, msg.kv.second);
|
|
}
|
|
}
|
|
|
|
template<typename ST, typename D>
|
|
class SmartTerminal : public SmartOStream<ST, SmartTerminal<ST, D>> {
|
|
using Base = SmartOStream<ST, SmartTerminal<ST, D>>;
|
|
public:
|
|
using Base::Base;
|
|
|
|
static const SmartFormatMap Formatters;
|
|
|
|
enum FormatterCodes : unsigned int {
|
|
DEFAULT = 0,
|
|
COLOR,
|
|
CLEAR,
|
|
BOLD,
|
|
|
|
};
|
|
|
|
protected:
|
|
|
|
};
|
|
|
|
template<typename ST, typename D>
|
|
const SmartFormatMap SmartTerminal<ST, D>::Formatters = {
|
|
{SmartTerminal<ST, D>::DEFAULT, SmartOStream<ST, D>::defaultFormatter}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // _NB_SMARTSTREAM
|