simple log system.

main
bog 2023-10-25 08:44:52 +02:00
parent e16b406e6e
commit 89956ddf6a
10 changed files with 208 additions and 1 deletions

View File

@ -6,3 +6,9 @@ build:
install: build
meson install -C build
check:
cppcheck --language=c++ --enable=all -q \
--suppress=missingInclude \
--suppress=missingIncludeSystem \
src

View File

@ -20,6 +20,11 @@ executable(
'mornelune',
sources: [
'src/main.cpp',
'src/Game.cpp',
'src/logs/Logs.cpp',
'src/logs/FileLogs.cpp',
],
dependencies: [
],

23
src/Game.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "Game.hpp"
namespace ml
{
/*explicit*/ Game::Game(std::shared_ptr<Logs> logs)
: m_logs { logs }
{
}
/*virtual*/ Game::~Game()
{
}
void Game::start()
{
m_logs->log(LEVEL_DEBUG, "game started");
}
void Game::stop()
{
m_logs->log(LEVEL_DEBUG, "game stopped");
}
}

26
src/Game.hpp Normal file
View File

@ -0,0 +1,26 @@
#ifndef ml_GAME_HPP
#define ml_GAME_HPP
#include "commons.hpp"
#include "logs/Logs.hpp"
namespace ml
{
/**
* Manage services and game state.
**/
class Game
{
public:
explicit Game(std::shared_ptr<Logs> logs);
virtual ~Game();
void start();
void stop();
private:
std::shared_ptr<Logs> m_logs;
};
}
#endif

24
src/commons.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef ml_COMMONS_HPP
#define ml_COMMONS_HPP
#include <stdexcept>
#include <string>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <fstream>
#define ML_GEN_ENUM(X) X
#define ML_GEN_STRING(X) #X
#define ML_ENUM(PREFIX, KINDS) \
enum PREFIX { KINDS(ML_GEN_ENUM) }; \
constexpr char const* PREFIX ## Str [] = { KINDS(ML_GEN_STRING) }
#define ML_ERROR(NAME) \
struct NAME : public std::runtime_error { \
explicit NAME (std::string const& what): std::runtime_error { what } \
{} \
}
#endif

19
src/logs/FileLogs.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "FileLogs.hpp"
namespace ml
{
/*explicit*/ FileLogs::FileLogs(std::filesystem::path const& path)
: Logs { m_file }
{
m_file.open(path, std::ios::app);
if (!m_file)
{
throw log_error {"cannot open log file '" + path.string() + "'"};
}
}
/*virtual*/ FileLogs::~FileLogs()
{
}
}

24
src/logs/FileLogs.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef ml_FILELOGS_HPP
#define ml_FILELOGS_HPP
#include "../commons.hpp"
#include "Logs.hpp"
namespace ml
{
/**
* Logs game activities into a file.
* @see Logs
**/
class FileLogs: public Logs
{
public:
explicit FileLogs(std::filesystem::path const& path);
virtual ~FileLogs();
private:
std::ofstream m_file;
};
}
#endif

40
src/logs/Logs.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "Logs.hpp"
namespace ml
{
/*explicit*/ Logs::Logs(std::ostream& out)
: m_out { out }
{
}
/*virtual*/ Logs::~Logs()
{
}
void Logs::log(LogLevel level, std::string const& message)
{
std::string level_str = (LogLevelStr[level] + std::strlen("LEVEL_"));
auto now = std::chrono::system_clock::now();
std::time_t now_t = std::chrono::system_clock::to_time_t(now);
auto time_str = std::put_time(std::localtime(&now_t), "%F %T");
std::string color = "";
switch (level)
{
case LEVEL_DEBUG: color = "34"; break;
default:
throw log_error {std::string("cannot find color for log level '")
+ (LogLevelStr[level] + std::strlen("LEVEL_"))
+ "'"};
}
m_out
<< time_str << " "
<< ("\033[" + color + "m[" + level_str + "]\033[0m ")
<< message
<< "\n";
}
}

29
src/logs/Logs.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef ml_LOGS_HPP
#define ml_LOGS_HPP
#include "../commons.hpp"
#define LOG_LEVELS(G) G(LEVEL_DEBUG)
namespace ml
{
ML_ENUM(LogLevel, LOG_LEVELS);
ML_ERROR(log_error);
/**
* Logs game activities into an output stream.
**/
class Logs
{
public:
explicit Logs(std::ostream& out);
virtual ~Logs();
void log(LogLevel level, std::string const& message);
private:
std::ostream& m_out;
};
}
#endif

View File

@ -1,8 +1,19 @@
#include <filesystem>
#include <iostream>
#include "conf.hpp"
#include "logs/FileLogs.hpp"
#include "Game.hpp"
int main(int, char**)
{
std::cout << "Mornelune v" << ML_VERSION << std::endl;
auto logs = std::make_shared<ml::FileLogs>
(std::filesystem::temp_directory_path() / "mornelune.log");
ml::Game game {logs};
game.start();
game.stop();
return 0;
}