summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-04-04 22:05:06 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-04-04 22:05:06 +0200
commitf3ba19b162a89b2081c0598b4a0bf126146e3671 (patch)
treee6c82af3ad5c7ea5e11aa6381822bfc8e68dd5fd
parent3320960992afe36f4b6306130c6327e084c381b2 (diff)
Add logging system
-rw-r--r--deimos/core/BUILD5
-rw-r--r--deimos/core/api_registry.cpp2
-rw-r--r--deimos/core/base.h10
-rw-r--r--deimos/core/format.h5
-rw-r--r--deimos/core/hash.h2
-rw-r--r--deimos/core/io.cpp18
-rw-r--r--deimos/core/io.h20
-rw-r--r--deimos/core/log.cpp82
-rw-r--r--deimos/core/log.h71
-rw-r--r--main/main.cpp10
10 files changed, 216 insertions, 9 deletions
diff --git a/deimos/core/BUILD b/deimos/core/BUILD
index fcedb22..08f1ada 100644
--- a/deimos/core/BUILD
+++ b/deimos/core/BUILD
@@ -8,6 +8,7 @@ cc_library(
"hash.h",
"id_name.h",
"io.h",
+ "log.h",
"os.h",
"std.h",
"format.h",
@@ -15,8 +16,10 @@ cc_library(
srcs = [
"allocator.cpp",
"api_registry.cpp",
- "os_win32.cpp",
"format.cpp",
+ "io.cpp",
+ "log.cpp",
+ "os_win32.cpp",
],
visibility = ["//:__subpackages__"],
)
diff --git a/deimos/core/api_registry.cpp b/deimos/core/api_registry.cpp
index 1489484..24ea201 100644
--- a/deimos/core/api_registry.cpp
+++ b/deimos/core/api_registry.cpp
@@ -8,6 +8,7 @@ namespace deimos
AllocatorApi* BootstrapAllocatorApi();
void RegisterOsApi(ApiRegistry*);
+void RegisterLogApi(ApiRegistry*);
struct ApiEntry
{
@@ -56,6 +57,7 @@ ApiRegistry* InitializeGlobalApiRegistry()
api_registry->Set(g_allocator_api);
RegisterOsApi(api_registry);
+ RegisterLogApi(api_registry);
return api_registry;
}
diff --git a/deimos/core/base.h b/deimos/core/base.h
index 21cad3d..4bcb7c7 100644
--- a/deimos/core/base.h
+++ b/deimos/core/base.h
@@ -53,6 +53,14 @@ struct SourceLocation
{}
};
+template<typename T> T Min(T a, T b) { return (a < b) ? a : b; }
+template<typename T> T Max(T a, T b) { return (a > b) ? a : b; }
+
+constexpr void MemoryCopy(void* dst, const void* src, int64_t size)
+{
+ __builtin_memcpy(dst, src, (size_t)size);
+}
+
template<typename T>
class Span
{
@@ -79,7 +87,7 @@ public:
template<typename U>
requires std::convertible_to<U*, T*>
- constexpr Span(const Span<U>& other) : // NOLINT
+ constexpr Span(const Span<U>& other) : // NOLINT(*-explicit-conversions)
m_begin{other.begin()},
m_size{other.size()}
{}
diff --git a/deimos/core/format.h b/deimos/core/format.h
index 98d9001..be2e4bf 100644
--- a/deimos/core/format.h
+++ b/deimos/core/format.h
@@ -37,6 +37,11 @@ struct FormatArg
unsigned_integer{value}
{}
+ explicit FormatArg(Span<const char> value) :
+ type{kString},
+ string{value}
+ {}
+
explicit FormatArg(gsl::czstring value) :
type{kString},
string{value, (int64_t)__builtin_strlen(value)}
diff --git a/deimos/core/hash.h b/deimos/core/hash.h
index f0eeafd..3198541 100644
--- a/deimos/core/hash.h
+++ b/deimos/core/hash.h
@@ -43,8 +43,6 @@ constexpr uint64_t MurmurHash3_Fmix64(uint64_t k)
constexpr uint128_t MurmurHash3_x64_128(const char* key, uint64_t len)
{
- if consteval { return { 12, 12 }; }
-
// NOLINTBEGIN
const uint64_t nblocks = len / 16;
diff --git a/deimos/core/io.cpp b/deimos/core/io.cpp
new file mode 100644
index 0000000..7764ee2
--- /dev/null
+++ b/deimos/core/io.cpp
@@ -0,0 +1,18 @@
+#include "deimos/core/io.h"
+
+namespace deimos
+{
+
+void BufferWriter::Write(Span<const std::byte> to_write)
+{
+ Expects(m_written <= m_size);
+
+ int64_t n_to_write = Min(to_write.size(), m_size - m_written);
+ MemoryCopy(m_buffer + m_written, to_write.data(), n_to_write); // NOLINT
+ m_written += n_to_write;
+
+ Ensures(m_written <= m_size);
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/io.h b/deimos/core/io.h
index 90caadc..12de30e 100644
--- a/deimos/core/io.h
+++ b/deimos/core/io.h
@@ -17,5 +17,25 @@ public:
virtual void Write(Span<const std::byte>) = 0;
};
+class BufferWriter : public IWriter
+{
+ std::byte* m_buffer;
+ int64_t m_size;
+ int64_t m_written = 0;
+
+public:
+ explicit BufferWriter(Span<std::byte> buffer) :
+ m_buffer{buffer.begin()},
+ m_size{buffer.size()}
+ {}
+
+ void Write(Span<const std::byte>) override;
+
+ constexpr Span<const std::byte> GetWritten() const
+ {
+ return { m_buffer, m_written };
+ }
+};
+
} // namespace deimos
diff --git a/deimos/core/log.cpp b/deimos/core/log.cpp
new file mode 100644
index 0000000..befe4b7
--- /dev/null
+++ b/deimos/core/log.cpp
@@ -0,0 +1,82 @@
+#include "deimos/core/log.h"
+#include "deimos/core/api_registry.h"
+#include "deimos/core/allocator.h"
+#include "deimos/core/os.h"
+
+namespace deimos
+{
+
+class DefaultLogger : public ILogger
+{
+ OsConsoleWriter m_writer;
+
+ static const char* SeverityToStr(LogSeverity s)
+ {
+ switch (s)
+ {
+ case LogSeverity::kInfo: return "INFO ";
+ case LogSeverity::kDebug: return "DEBUG";
+ case LogSeverity::kError: return "ERROR";
+ }
+ }
+
+ static const char* SeverityToColor(LogSeverity s)
+ {
+ switch (s)
+ {
+ case LogSeverity::kInfo: return "";
+ case LogSeverity::kDebug: return "\033[2m";
+ case LogSeverity::kError: return "\033[91m";
+ }
+ }
+
+public:
+ explicit DefaultLogger(OsConsoleApi* os_console_api) :
+ m_writer(os_console_api, OsConsoleType::kStdOut)
+ {}
+
+ // @Todo Use string views
+ void Log(LogSeverity severity, const SourceLocation& location, Span<const char> msg) override
+ {
+ Format(&m_writer, "$[ $ ] $:$: $\033[0m\n", SeverityToColor(severity),
+ SeverityToStr(severity), location.file, location.line, msg);
+ }
+};
+
+class LogApiImpl : public LogApi
+{
+ ILogger* m_default_logger;
+
+public:
+ explicit LogApiImpl(ILogger* default_logger) :
+ m_default_logger{default_logger}
+ {}
+
+ void LogVa(
+ LogSeverity severity,
+ const SourceLocation& location,
+ gsl::czstring msg,
+ Span<const FormatArg> args) override
+ {
+ std::byte buffer[1024];
+ BufferWriter message_writer({&buffer[0], 1024});
+ FormatVa(&message_writer, msg, args);
+
+ auto written = message_writer.GetWritten();
+ m_default_logger->Log(severity, location, {(const char*)written.data(), written.size()});
+ }
+};
+
+void RegisterLogApi(ApiRegistry* api_registry)
+{
+ auto* allocator = api_registry->Get<AllocatorApi>()->system;
+ auto* os_console_api = api_registry->Get<OsApi>()->console;
+
+ auto* default_logger = allocator->New<DefaultLogger>(os_console_api);
+ auto* log_api = allocator->New<LogApiImpl>(default_logger);
+
+ api_registry->Set(log_api);
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/log.h b/deimos/core/log.h
new file mode 100644
index 0000000..cf92391
--- /dev/null
+++ b/deimos/core/log.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "deimos/core/base.h"
+#include "deimos/core/id_name.h"
+#include "deimos/core/format.h"
+
+namespace deimos
+{
+
+enum class LogSeverity
+{
+ kInfo,
+ kDebug,
+ kError,
+};
+
+class ILogger
+{
+public:
+ ILogger() = default;
+ deimos_NO_COPY_MOVE(ILogger);
+ virtual ~ILogger() = default;
+
+ // @Todo Use string view
+ virtual void Log(LogSeverity, const SourceLocation&, Span<const char>) = 0;
+};
+
+// Just a helper to pass a SourceLocation without having to write {} to logging functions.
+struct LogSourceLocation
+{
+ gsl::czstring fmt;
+ SourceLocation source_location;
+
+ // NOLINTNEXTLINE(*-explicit-conversions)
+ LogSourceLocation(gsl::czstring fmt_, const SourceLocation& source_location_ = {}) :
+ fmt{fmt_}, source_location{source_location_}
+ {}
+};
+
+class LogApi
+{
+public:
+ static constexpr IdName kApiName{"deimos::LogApi"};
+
+ LogApi() = default;
+ deimos_NO_COPY_MOVE(LogApi);
+ virtual ~LogApi() = default;
+
+ virtual void LogVa(LogSeverity, const SourceLocation&, gsl::czstring msg, Span<const FormatArg>) = 0;
+
+ template<Formattable... Args>
+ void LogInfo(const LogSourceLocation& fmt_source_location, Args&&... args)
+ {
+ LogVa(LogSeverity::kInfo, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ }
+
+ template<Formattable... Args>
+ void LogDebug(const LogSourceLocation& fmt_source_location, Args&&... args)
+ {
+ LogVa(LogSeverity::kDebug, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ }
+
+ template<Formattable... Args>
+ void LogError(const LogSourceLocation& fmt_source_location, Args&&... args)
+ {
+ LogVa(LogSeverity::kError, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ }
+};
+
+} // namespace deimos
+
diff --git a/main/main.cpp b/main/main.cpp
index 10a7dc4..03c2097 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1,16 +1,16 @@
#include <deimos/core/api_registry.h>
-#include <deimos/core/os.h>
-#include <deimos/core/format.h>
+#include <deimos/core/log.h>
using namespace deimos;
int main(int /* argc */, char* /* argv */[])
{
auto* api_registry = InitializeGlobalApiRegistry();
- auto* os_api = api_registry->Get<OsApi>();
+ auto* log_api = api_registry->Get<LogApi>();
- OsConsoleWriter writer(os_api->console, OsConsoleType::kStdOut);
- Format(&writer, "Hello, $!", "world");
+ log_api->LogInfo("Hello, world!");
+ log_api->LogDebug("Hello, $!", "world");
+ log_api->LogError("This is an error OMG $ $ $", 1, 2, 3);
return 0;
}