Skip to content

Commit 64dd024

Browse files
committed
Refactor project & change to single stream logging
1 parent b1eadf5 commit 64dd024

18 files changed

+489
-200
lines changed

.github/workflows/ci.yml

-4
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ jobs:
2323
- { name: Release, flags: -DCMAKE_BUILD_TYPE=Release }
2424

2525
steps:
26-
- name: Install Linux Dependencies
27-
if: runner.os == 'Linux'
28-
run: sudo apt-get update && sudo apt-get install libxrandr-dev libxcursor-dev libxi-dev libudev-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libfreetype-dev
29-
3026
- name: Checkout
3127
uses: actions/checkout@v4
3228

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake-build-debug/
1+
build/
22
out/
33
.idea/
4-
.DS_STORE
4+
.DS_STORE

CMakeLists.txt

+30-11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
cmake_minimum_required(VERSION 3.25)
22
project(logger)
3-
43
set(CMAKE_CXX_STANDARD 20)
54

6-
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/lib/)
7-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/bin/)
8-
include_directories(src)
5+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/lib/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_BUILD_TYPE})
6+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/bin/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_BUILD_TYPE})
7+
include_directories(src include)
98

109
add_library(
11-
logger STATIC
12-
src/logger.cpp
13-
src/logger.hpp
10+
logger STATIC
11+
src/Logger.cpp
12+
include/Logger.hpp
13+
include/Time.hpp
14+
src/Time.cpp
15+
include/Format.hpp
16+
src/Format.cpp
17+
include/Log.hpp
18+
src/Log.cpp
19+
include/Convert.hpp
20+
src/Convert.cpp
21+
include/StringOps.hpp
22+
src/StringOps.cpp
1423
)
1524

1625
add_executable(
17-
example
18-
src/logger.cpp
19-
src/logger.hpp
20-
src/example/example.cpp
26+
example
27+
src/Logger.cpp
28+
include/Logger.hpp
29+
src/example/example.cpp
30+
include/Time.hpp
31+
src/Time.cpp
32+
include/Format.hpp
33+
src/Format.cpp
34+
include/Log.hpp
35+
src/Log.cpp
36+
include/Convert.hpp
37+
src/Convert.cpp
38+
include/StringOps.hpp
39+
src/StringOps.cpp
2140
)

include/Convert.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <sstream>
5+
#include <string>
6+
7+
namespace SSBL {
8+
template<typename T>
9+
std::string GenericToString(const T &generic) {
10+
std::stringstream ss;
11+
ss << generic;
12+
return ss.str();
13+
}
14+
15+
std::optional<size_t> CharToSize(char character);
16+
} // namespace SSBL

include/Format.hpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include "Convert.hpp"
4+
#include "StringOps.hpp"
5+
#include <sstream>
6+
#include <string>
7+
8+
namespace SSBL {
9+
10+
std::string WithPadding(const std::string &string);
11+
12+
bool ContainsPlaceholder(const std::string &string);
13+
std::string IndexPlaceholders(const std::string &string);
14+
15+
template<typename T>
16+
std::string Format(const std::string &string, const T &value, const size_t insertNumber) {
17+
if (!ContainsPlaceholder(string))
18+
return string + GenericToString(value);
19+
20+
std::string out = IndexPlaceholders(string);
21+
const std::string placeholder = "{" + std::to_string(insertNumber) + "}";
22+
23+
out = ReplaceAll(out, placeholder, GenericToString(value));
24+
out = ReplaceAll(out, "\n", "");
25+
26+
if (const size_t pos = out.find('\n'); pos != std::string::npos)
27+
out.replace(pos, 1, "");
28+
29+
return out;
30+
}
31+
32+
} // namespace SSBL

include/Log.hpp

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
namespace SSBL {
6+
enum class Level : unsigned {
7+
None = 0b0000,
8+
Info = 0b0001,
9+
Warning = 0b0010,
10+
Error = 0b0100,
11+
Fatal = 0b1000,
12+
All = 0b1111
13+
};
14+
15+
constexpr Level operator|(Level a, Level b) {
16+
return static_cast<Level>(static_cast<char>(a) | static_cast<char>(b));
17+
}
18+
19+
constexpr Level operator&(Level a, Level b) {
20+
return static_cast<Level>(static_cast<char>(a) & static_cast<char>(b));
21+
}
22+
23+
constexpr Level operator~(Level level) {
24+
return static_cast<Level>(~static_cast<char>(level));
25+
}
26+
27+
enum class Config : unsigned {
28+
None = 0b00,
29+
Color = 0b01,
30+
Timestamp = 0b10,
31+
All = 0b11
32+
};
33+
34+
constexpr Config operator|(Config a, Config b) {
35+
return static_cast<Config>(static_cast<char>(a) | static_cast<char>(b));
36+
}
37+
38+
constexpr Config operator&(Config a, Config b) {
39+
return static_cast<Config>(static_cast<char>(a) & static_cast<char>(b));
40+
}
41+
42+
constexpr Config operator~(Config level) {
43+
return static_cast<Config>(~static_cast<char>(level));
44+
}
45+
46+
std::string ToLog(const std::string &string, Level level, Config config);
47+
std::string LogLevelToString(Level level);
48+
} // namespace SSBL

include/Logger.hpp

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#pragma once
2+
3+
#include "Format.hpp"
4+
#include "Log.hpp"
5+
#include <fstream>
6+
#include <iostream>
7+
#include <sstream>
8+
9+
namespace SSBL {
10+
class Logger {
11+
public:
12+
Logger &Log(Level level = Level::Info);
13+
Logger &LogToFile(const std::string &filePath, Level level = Level::Info);
14+
15+
template<typename T>
16+
Logger &operator<<(const T &stream) {
17+
if (!IsLevelIncluded(m_level))
18+
return *this;
19+
20+
m_stream.str(Format(m_stream.str(), GenericToString(stream), insertCount));
21+
insertCount++;
22+
23+
if (Contains(GenericToString(stream), "\n")) {
24+
Send(m_stream.str());
25+
Flush();
26+
}
27+
28+
return *this;
29+
}
30+
31+
void SetOutStream(std::ostream *messageOutStream, std::ostream *errorOutStream);
32+
void SetConfig(const Config &config);
33+
void SetLevelMask(Level level);
34+
bool IsLevelIncluded(Level level) const;
35+
36+
private:
37+
std::ostream *m_msgOutStream = &std::cout;
38+
std::ostream *m_errOutStream = &std::cerr;
39+
std::optional<std::ofstream> m_fileOutStream;
40+
41+
std::ostringstream m_stream;
42+
size_t insertCount = 0;
43+
44+
Config m_config = Config::Timestamp;
45+
Level m_levelMask = Level::All;
46+
Level m_level = Level::Info;
47+
48+
void Send(const std::string &string);
49+
void Flush();
50+
51+
void SetColor();
52+
void ResetColor() const;
53+
54+
#if _WIN32
55+
int GetColor() const;
56+
#else
57+
std::string GetColor() const;
58+
#endif
59+
};
60+
} // namespace SSBL

include/StringOps.hpp

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
6+
namespace SSBL {
7+
bool Contains(const std::string &string, const std::string &query);
8+
std::vector<size_t> FindAll(const std::string &string, const std::string &query);
9+
std::string ReplaceAll(
10+
const std::string &string, const std::string &substring, const std::string &replacement);
11+
} // namespace SSBL

include/Time.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
namespace SSBL {
6+
std::string GetTimestamp();
7+
} // namespace SSBL

src/Convert.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "Convert.hpp"
2+
3+
namespace SSBL {
4+
std::optional<size_t> CharToSize(const char character) {
5+
if (character >= '0' && character <= '9')
6+
return character - '0';
7+
8+
return std::nullopt;
9+
}
10+
} // namespace SSBL

src/Format.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "Format.hpp"
2+
#include "Convert.hpp"
3+
#include "Logger.hpp"
4+
5+
namespace SSBL {
6+
7+
std::string WithPadding(const std::string &string) {
8+
return '[' + string + "] ";
9+
}
10+
11+
bool ContainsPlaceholder(const std::string &string) {
12+
return Contains(string, "{") && Contains(string, "}");
13+
}
14+
15+
std::string IndexPlaceholders(const std::string &string) {
16+
std::string processedStr = string;
17+
size_t pos = processedStr.find("{}", 0);
18+
size_t placeholderNum = 0;
19+
20+
while (pos != std::string::npos) {
21+
if (!CharToSize(processedStr[pos]).has_value()) {
22+
processedStr
23+
.replace(pos + placeholderNum, 2, '{' + GenericToString(placeholderNum + 1) + '}');
24+
placeholderNum++;
25+
}
26+
27+
pos = string.find("{}", pos + 1);
28+
}
29+
30+
return processedStr;
31+
}
32+
33+
} // namespace SSBL

src/Log.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "Log.hpp"
2+
#include "Format.hpp"
3+
#include "Time.hpp"
4+
#include <string>
5+
6+
namespace SSBL {
7+
8+
std::string ToLog(const std::string &string, const Level level, const Config config) {
9+
std::string log;
10+
11+
if (static_cast<bool>(config & Config::Timestamp))
12+
log += WithPadding(GetTimestamp());
13+
14+
log += WithPadding(LogLevelToString(level));
15+
log += string;
16+
17+
if (log.back() != '\n')
18+
log += '\n';
19+
20+
return log;
21+
}
22+
23+
std::string LogLevelToString(const Level level) {
24+
std::string str{};
25+
26+
switch (level) {
27+
case Level::Info:
28+
str = "INF";
29+
break;
30+
case Level::Warning:
31+
str = "WRN";
32+
break;
33+
case Level::Error:
34+
str = "ERR";
35+
break;
36+
case Level::Fatal:
37+
str = "FTL";
38+
break;
39+
default:
40+
str = "UNK";
41+
break;
42+
}
43+
44+
return str;
45+
}
46+
} // namespace SSBL

0 commit comments

Comments
 (0)