Got SmartOStreams kinda working!
This commit is contained in:
parent
85875d8130
commit
95120f411e
@ -21,7 +21,7 @@ set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
|||||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
add_library(NBEvents ./src/NBEvents/Events.cpp)
|
add_library(NBEvents ./src/NBEvents/Events.cpp)
|
||||||
add_library(NBCore ./src/NBCoreUtils/Errors.cpp)
|
|
||||||
|
|
||||||
|
add_subdirectory(./src/NBCoreUtils)
|
||||||
add_subdirectory(./src/NBWindow ./NBWindows)
|
add_subdirectory(./src/NBWindow ./NBWindows)
|
||||||
add_subdirectory(./tests ./tests)
|
add_subdirectory(./tests ./tests)
|
||||||
75
include/DataSink.hpp
Normal file
75
include/DataSink.hpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _NB_DATASINK
|
||||||
|
#define _NB_DATASINK
|
||||||
|
|
||||||
|
namespace nb {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class SinkBase {
|
||||||
|
using InputType = T;
|
||||||
|
public:
|
||||||
|
virtual bool in(const T&) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SinkBase();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* template <typename T>
|
||||||
|
class Sink : public SinkBase {
|
||||||
|
public:
|
||||||
|
Sink& operator=(const Sink&) = 0;
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
virtual bool in(const U&) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Sink();
|
||||||
|
|
||||||
|
}; */
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class SourceBase {
|
||||||
|
using OutputType = T;
|
||||||
|
public:
|
||||||
|
SourceBase& operator=(const SourceBase&) = 0;
|
||||||
|
|
||||||
|
virtual bool out(T*) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SourceBase();
|
||||||
|
SinkBase<T>* _sink;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Pipe : public SinkBase<T>, public SourceBase<T>{
|
||||||
|
using Input = SourceBase<T>;
|
||||||
|
using Output = SinkBase<T>;
|
||||||
|
public:
|
||||||
|
Pipe(Sink<T>& sink) : Input::_sink{&sink} {}
|
||||||
|
|
||||||
|
bool in(const T&) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using Input::_sink;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* template <typename T>
|
||||||
|
class Source : SourceBase {
|
||||||
|
public:
|
||||||
|
Source& operator=(const Source&) = 0;
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
virtual bool out(const U&) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Source();
|
||||||
|
|
||||||
|
}; */
|
||||||
|
|
||||||
|
} // namespace nb
|
||||||
|
#endif // _NB_DATASINK
|
||||||
64
include/Logger.hpp
Normal file
64
include/Logger.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _NB_LOGGER
|
||||||
|
#define _NB_LOGGER
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <ostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "SmartStreams.hpp"
|
||||||
|
#include "ThreadSafeQueue.hpp"
|
||||||
|
|
||||||
|
namespace nb {
|
||||||
|
|
||||||
|
typedef std::chrono::time_point<
|
||||||
|
std::chrono::system_clock,
|
||||||
|
std::chrono::nanoseconds
|
||||||
|
> LoggerTimePoint;
|
||||||
|
|
||||||
|
struct LogEvent{
|
||||||
|
const LoggerTimePoint time;
|
||||||
|
const unsigned char lvl;
|
||||||
|
const std::string msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Logger {
|
||||||
|
typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&);
|
||||||
|
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
|
||||||
|
public:
|
||||||
|
Logger();
|
||||||
|
|
||||||
|
bool isRunning() const;
|
||||||
|
unsigned int count() const;
|
||||||
|
|
||||||
|
bool run();
|
||||||
|
bool stop();
|
||||||
|
LogEvent popProcess();
|
||||||
|
LogEvent popDelete();
|
||||||
|
void flush();
|
||||||
|
void deleteAll();
|
||||||
|
void msg(const std::string&, uint8_t lvl=0);
|
||||||
|
void warn(const std::string&, uint8_t lvl=1);
|
||||||
|
void warn(const std::exception&, uint8_t lvl=1);
|
||||||
|
void error(const std::string&, uint8_t lvl=0xFF);
|
||||||
|
void error(const std::exception&, uint8_t lvl=0xFF);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void process(const LogEvent&);
|
||||||
|
|
||||||
|
const LogProcessFunctionMap _function_map;
|
||||||
|
|
||||||
|
ThreadsafeQueue<LogEvent> _queue;
|
||||||
|
T* _ostream;
|
||||||
|
// std::condition_variable _cond;
|
||||||
|
// mutable std::mutex _mutex;
|
||||||
|
mutable std::mutex _runningMutex;
|
||||||
|
bool _running;
|
||||||
|
std::shared_ptr<std::thread> _runningThread = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nb
|
||||||
|
#endif // _NB_LOGGER
|
||||||
109
include/SmartStreams.hpp
Normal file
109
include/SmartStreams.hpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#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, typename Derived>
|
||||||
|
class SmartOStreamBaseImpl;
|
||||||
|
|
||||||
|
template<typename ST, typename Derived=void>
|
||||||
|
class SmartOStream;
|
||||||
|
|
||||||
|
template<typename ST, typename Derived>
|
||||||
|
class SmartOStreamBaseImpl {
|
||||||
|
public:
|
||||||
|
virtual void process(const SmartText&) = 0;
|
||||||
|
|
||||||
|
static const SmartFormatMap Formatters;
|
||||||
|
using StreamType = SmartOStream<ST>;
|
||||||
|
protected:
|
||||||
|
SmartOStreamBaseImpl(StreamType& stream) : _ostream(&stream) {}
|
||||||
|
StreamType* _ostream;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename C, typename T, typename Derived>
|
||||||
|
class SmartOStreamBaseImpl<std::basic_ostream<C, T>, Derived> {
|
||||||
|
public:
|
||||||
|
virtual void process(const SmartText&) = 0;
|
||||||
|
|
||||||
|
static const SmartFormatMap Formatters;
|
||||||
|
using StreamType = std::basic_ostream<C, T>;
|
||||||
|
protected:
|
||||||
|
SmartOStreamBaseImpl(StreamType& stream) : _ostream(&stream) {}
|
||||||
|
StreamType* _ostream;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
StreamType* getStream() const { return _ostream; }
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
|
void process(const X&);
|
||||||
|
|
||||||
|
void process(const SmartText&);
|
||||||
|
|
||||||
|
static const SmartFormatMap Formatters;
|
||||||
|
using Base = SmartOStreamBaseImpl<StreamType, Derived>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using Base::Base;
|
||||||
|
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) {
|
||||||
|
static_cast<D*>(&stream)->process(msg);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ST, typename D>
|
||||||
|
void SmartOStream<ST, D>::process(const SmartText& msg) {
|
||||||
|
try {
|
||||||
|
*_ostream << D::Formatters.at(msg.kv.first)(msg.msg, msg.kv.second);
|
||||||
|
} catch (const std::out_of_range& e) {
|
||||||
|
*_ostream << D::Formatters.at(0)(msg.msg, msg.kv.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ST, typename D>
|
||||||
|
template<typename X>
|
||||||
|
void SmartOStream<ST, D>::process(const X& msg) {
|
||||||
|
*_ostream << msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _NB_SMARTSTREAM
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
add_library(NBCore
|
||||||
|
Errors.cpp
|
||||||
|
)
|
||||||
87
src/NBCoreUtils/Logger.cpp
Normal file
87
src/NBCoreUtils/Logger.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "Logger.hpp"
|
||||||
|
|
||||||
|
namespace nb {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool Logger<>::isRunning() const {
|
||||||
|
std::lock_guard<std::mutex> lock(_runningMutex);
|
||||||
|
return _running;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Logger::count() const {
|
||||||
|
return _queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Logger::run() {
|
||||||
|
std::lock_guard<std::mutex> lock(_runningMutex);
|
||||||
|
if (!_running) {
|
||||||
|
_runningThread = std::make_shared<std::thread>([&]{
|
||||||
|
while(this->_running) {
|
||||||
|
this->flush();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return _running;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Logger::stop() {
|
||||||
|
std::lock_guard<std::mutex> lock(_runningMutex);
|
||||||
|
_running = false;
|
||||||
|
_runningThread->join();
|
||||||
|
return _running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::process(const LogEvent& event) {
|
||||||
|
uint8_t lvl = event.lvl;
|
||||||
|
try {
|
||||||
|
_ostream << _function_map.at(lvl)(event.time, event.msg).c_str();
|
||||||
|
} catch (std::out_of_range e) {
|
||||||
|
_ostream << _function_map[0](event.time, event.msg).c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEvent Logger::popProcess() {
|
||||||
|
std::shared_ptr<LogEvent> event;
|
||||||
|
_queue.pop(event);
|
||||||
|
process(*event);
|
||||||
|
return *event;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogEvent Logger::popDelete() {
|
||||||
|
std::shared_ptr<LogEvent> event;
|
||||||
|
_queue.pop(event);
|
||||||
|
process(*event);
|
||||||
|
return *event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::flush() {
|
||||||
|
while(_queue.size()) {
|
||||||
|
popProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::deleteAll() {
|
||||||
|
_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::msg(const std::string& _msg, uint8_t lvl) {
|
||||||
|
_queue.push(LogEvent{std::chrono::system_clock::now(), lvl, _msg});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::warn(const std::string& _msg, uint8_t lvl) {
|
||||||
|
msg(_msg, lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::warn(const std::exception& _err, uint8_t lvl) {
|
||||||
|
msg(_err.what(), lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::error(const std::string& _msg, uint8_t lvl) {
|
||||||
|
msg(_msg, lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::error(const std::exception& _err, uint8_t lvl) {
|
||||||
|
msg(_err.what(), lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,3 +14,4 @@ include(GoogleTest)
|
|||||||
set(GTEST_COLOR ON)
|
set(GTEST_COLOR ON)
|
||||||
|
|
||||||
add_subdirectory(./ErrorTest)
|
add_subdirectory(./ErrorTest)
|
||||||
|
add_subdirectory(./SmartStreamTest)
|
||||||
5
tests/SmartStreamTest/CMakeLists.txt
Normal file
5
tests/SmartStreamTest/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.26.0)
|
||||||
|
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
|
||||||
|
|
||||||
|
add_executable(SmartStreamTest main.cpp)
|
||||||
|
target_link_libraries(SmartStreamTest NBCore)
|
||||||
38
tests/SmartStreamTest/main.cpp
Normal file
38
tests/SmartStreamTest/main.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "SmartStreams.hpp"
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
class TestStream : public nb::SmartOStream<ST, TestStream<ST>> {
|
||||||
|
using Base = nb::SmartOStream<ST, TestStream<ST>>;
|
||||||
|
public:
|
||||||
|
TestStream(ST& stream) : Base(stream) {}
|
||||||
|
|
||||||
|
static const nb::SmartFormatMap Formatters;
|
||||||
|
// using Base::Formatters;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ST>
|
||||||
|
const nb::SmartFormatMap TestStream<ST>::Formatters = {
|
||||||
|
{0, [](std::string msg, std::string fmt){
|
||||||
|
return "[0] : " + msg;
|
||||||
|
}},
|
||||||
|
{1, [](std::string msg, std::string fmt){
|
||||||
|
return "\x1b[" + fmt + "m" + msg + "\x1b[0m";
|
||||||
|
}},
|
||||||
|
{2, [](std::string msg, std::string fmt){
|
||||||
|
return "\x1b[1m" + msg + "\x1b[0m";
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
auto tout = TestStream(std::cout);
|
||||||
|
tout << nb::SmartText{"Gloop!\n", {2, "32"}};
|
||||||
|
tout << 8989;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user