From 05da31900745c5225527d4a30472bdc0db2826e9 Mon Sep 17 00:00:00 2001 From: Liam Teale Date: Tue, 31 Dec 2024 17:15:41 -0800 Subject: [PATCH] prevent global sinks initializing before the sink list --- include/lemlog/logger/logger.hpp | 4 +- src/lemlog/logger/logger.cpp | 109 +++++++++++++++++++++++++++++-- src/main.cpp | 1 + 3 files changed, 106 insertions(+), 8 deletions(-) diff --git a/include/lemlog/logger/logger.hpp b/include/lemlog/logger/logger.hpp index 99afbed..ecf6100 100644 --- a/include/lemlog/logger/logger.hpp +++ b/include/lemlog/logger/logger.hpp @@ -128,8 +128,10 @@ class Helper { /** * @brief Send a message to all sinks * + * Sends a message to all sinks + * * @param level the logging level of the message - * @param format the message to be sent + * @param format the format of the message to be sent * @param args the arguments to be formatted into the message * * @b Example: diff --git a/src/lemlog/logger/logger.cpp b/src/lemlog/logger/logger.cpp index 8567070..5bda7fd 100644 --- a/src/lemlog/logger/logger.cpp +++ b/src/lemlog/logger/logger.cpp @@ -1,20 +1,115 @@ #include "lemlog/logger/logger.hpp" -#include namespace logger { +template +class Node; + +/** + * @brief Doubly linked list + * + * The linked list in the standard library cannot be initialized at compile + * time. If we were to use the stdlib implementation, we wouldn't be able to + * create sinks during static initialization, as the sinks may initialize before + * the list of sinks do + * + * @tparam T the element to store + */ +template +class List { + public: + void push_back(T value) { + if (exists(value)) return; + Node* const last = getLast(); + if (last == nullptr) { + m_first = new Node(value); + } else { + last->next = new Node(value); + } + } + + Node* getLast() { + if (m_first == nullptr) { + return nullptr; + } else { + Node* res = m_first; + while (res->next != nullptr) { + res = res->next; + } + return res; + } + } + + bool exists(T element) { + Node* ptr = m_first; + while (ptr != nullptr) { + if (ptr->value == element) return true; + } + return false; + } + + void erase(T element) { + Node* ptr = m_first; + while (ptr != nullptr) { + if (ptr->value == element) delete ptr; + } + } + + // Access operator + T& operator[](size_t index) const { + Node* last = m_first; + for (int i = 0; i < index; ++i) { + last = last->next; + } + return last->value; + } + + // Size getter + size_t size() const { + Node* last = m_first; + size_t s = 0; + while (last != nullptr) { + last = last->next; + ++s; + } + return s; + } + + const T* begin() const { return &m_first->value; } + + const T* end() const { return &(*this)[size()]; } + private: + Node* m_first = nullptr; +}; + +template +class Node { + friend List; + public: + Node(T value) + : value(value) {} + private: + ~Node() { + if (prev != nullptr) prev->next = this->next; + } + + T value; + Node* prev = nullptr; + Node* next = nullptr; +}; + // doubly linked list of all sinks -static std::list sinks; -static std::list whitelist; -static std::list blacklist; +static constinit List sinks; +static constinit List whitelist; +static constinit List blacklist; void addWhitelist(std::string s) { whitelist.push_back(s); } -void removeWhitelist(std::string s) { whitelist.remove(s); } +void removeWhitelist(std::string s) { whitelist.erase(s); } void addBlacklist(std::string s) { blacklist.push_back(s); } -void removeBlacklist(std::string s) { blacklist.remove(s); } +void removeBlacklist(std::string s) { blacklist.erase(s); } void log(Level level, std::string topic, std::string message) { // is the message a debug message? @@ -45,5 +140,5 @@ Helper::Helper(std::string topic) Sink::Sink() { sinks.push_back(this); } -Sink::~Sink() { sinks.remove(this); } +Sink::~Sink() { sinks.erase(this); } } // namespace logger diff --git a/src/main.cpp b/src/main.cpp index b025b24..8004a31 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,7 @@ void initialize() { logger::Helper test("test-topic"); test.log(logger::Level::INFO, "The value is {}", 42); + test.log(logger::Level::INFO, "hello!"); } /**