From 98c8fd5d39ee645922f071b6433308a813245500 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 24 Apr 2024 00:29:16 +0200 Subject: Add custom formatter & use it on Status --- deimos/core/base.h | 6 +++++- deimos/core/format.cpp | 3 +++ deimos/core/format.h | 39 +++++++++++++++++++++++++++++++-------- deimos/core/log.h | 6 +++--- deimos/core/status.cpp | 30 ++++++++++++++++++++++++++++-- deimos/core/status.h | 10 ++++++++++ deimos/core/std.h | 1 + deimos/core/temp_allocator.cpp | 2 +- 8 files changed, 82 insertions(+), 15 deletions(-) (limited to 'deimos/core') diff --git a/deimos/core/base.h b/deimos/core/base.h index f24991d..5cd3a40 100644 --- a/deimos/core/base.h +++ b/deimos/core/base.h @@ -78,6 +78,9 @@ constexpr void MemoryCopy(void* dst, const void* src, int64_t size) __builtin_memcpy(dst, src, (size_t)size); } +template +constexpr int64_t ArraySize(const T (&)[N]) { return N; } + template class Span { @@ -113,6 +116,7 @@ public: constexpr T* begin() const { return m_begin; } constexpr T* end() const { return m_begin + m_size; } // NOLINT constexpr int64_t size() const { return m_size; } + constexpr bool empty() const { return m_size == 0; } }; template @@ -141,8 +145,8 @@ public: {} constexpr const char* data() const { return m_begin; } - constexpr int64_t size() const { return m_size; } + constexpr bool empty() const { return m_size == 0; } }; inline Span AsBytes(StringView span) diff --git a/deimos/core/format.cpp b/deimos/core/format.cpp index af0a851..5f420e9 100644 --- a/deimos/core/format.cpp +++ b/deimos/core/format.cpp @@ -51,6 +51,9 @@ public: case FormatArg::kUnsignedInteger: PushUnsignedInteger(arg.integer); break; + case FormatArg::kCustom: + arg.custom.callback(m_writer, arg.custom.payload); + break; } } }; diff --git a/deimos/core/format.h b/deimos/core/format.h index 3424dc2..ba1a3e2 100644 --- a/deimos/core/format.h +++ b/deimos/core/format.h @@ -7,6 +7,14 @@ namespace deimos class IWriter; +struct CustomFormatter +{ + using Callback = void (*)(IWriter*, const void* payload); + + const void* payload; + Callback callback; +}; + struct FormatArg { enum Type : uint8_t @@ -14,42 +22,57 @@ struct FormatArg kInteger, kUnsignedInteger, kString, + kCustom, }; Type type; union { - int64_t integer; - uint64_t unsigned_integer; - StringView string; + int64_t integer; + uint64_t unsigned_integer; + StringView string; + CustomFormatter custom; }; - explicit FormatArg(std::signed_integral auto value) : + constexpr explicit FormatArg(std::signed_integral auto value) : type{kInteger}, integer{value} {} - explicit FormatArg(std::unsigned_integral auto value) : + constexpr explicit FormatArg(std::unsigned_integral auto value) : type{kUnsignedInteger}, unsigned_integer{value} {} - explicit FormatArg(StringView value) : + constexpr explicit FormatArg(StringView value) : type{kString}, string{value} {} + + template + constexpr explicit FormatArg(const T& payload, CustomFormatter::Callback callback) : + type{kCustom}, + custom{CustomFormatter{&payload, callback}} + {} }; template -concept Formattable = requires (T value) { FormatArg(value); }; +deimos::FormatArg DeimosMakeFormatArg(T&& value) + requires std::is_constructible_v +{ + return deimos::FormatArg(value); +} + +template +concept Formattable = std::same_as()))>; void FormatVa(IWriter*, gsl::czstring fmt, Span); template void Format(IWriter* writer, gsl::czstring fmt, Args&&... args) { - FormatVa(writer, fmt, { FormatArg(std::forward(args))... }); + FormatVa(writer, fmt, { DeimosMakeFormatArg(std::forward(args))... }); } } // namespace deimos diff --git a/deimos/core/log.h b/deimos/core/log.h index 9bb4dbb..260d9a4 100644 --- a/deimos/core/log.h +++ b/deimos/core/log.h @@ -50,19 +50,19 @@ public: template 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))... }); + LogVa(LogSeverity::kInfo, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward(args))... }); } template 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))... }); + LogVa(LogSeverity::kDebug, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward(args))... }); } template 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))... }); + LogVa(LogSeverity::kError, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward(args))... }); } }; diff --git a/deimos/core/status.cpp b/deimos/core/status.cpp index f472aac..efdd6df 100644 --- a/deimos/core/status.cpp +++ b/deimos/core/status.cpp @@ -9,6 +9,18 @@ static deimos::AllocatorApi* allocator_api; namespace deimos { +StringView StatusCodeToString(StatusCode code) +{ + switch (code) + { + case StatusCode::kOk: return StringView("OK"); + case StatusCode::kUnknown: return StringView("Unknown error"); + case StatusCode::kInvalidArgument: return StringView("Invalid argument"); + case StatusCode::kUnimplemented: return StringView("Unimplemented"); + case StatusCode::kInternal: return StringView("Internal error"); + } +} + struct StatusRep { Atomic ref_count; @@ -18,9 +30,9 @@ struct StatusRep Status::Status(StatusCode code, StringView message) { - if (code == StatusCode::kOk) + if (code == StatusCode::kOk || message.empty()) { - m_rep = CodeToRep(StatusCode::kOk); + m_rep = CodeToRep(code); } else { @@ -74,6 +86,20 @@ void Status::Unref() const } } +void Status::FormatStatus(IWriter* writer, const void* payload) +{ + const auto& status = *(const Status*)payload; // NOLINT + if (status.IsInline()) + { + Format(writer, "[$]", StatusCodeToString(status.code())); + } + else + { + auto* rep = std::bit_cast(status.m_rep); + Format(writer, "[$: $]", StatusCodeToString(rep->code), rep->message); + } +} + void InitializeStatus(ApiRegistry* api_registry) { allocator_api = api_registry->Get(); diff --git a/deimos/core/status.h b/deimos/core/status.h index bf34833..7350cc5 100644 --- a/deimos/core/status.h +++ b/deimos/core/status.h @@ -1,6 +1,7 @@ #pragma once #include "deimos/core/base.h" +#include "deimos/core/format.h" namespace deimos { @@ -15,6 +16,8 @@ enum class StatusCode : uint32_t kInternal, }; +StringView StatusCodeToString(StatusCode code); + class Status { uintptr_t m_rep; @@ -79,6 +82,13 @@ public: if (IsInline()) { return (StatusCode)(m_rep >> 1U); } return RepCode(); } + + static void FormatStatus(IWriter* writer, const void* payload); + + friend constexpr deimos::FormatArg DeimosMakeFormatArg(const Status& status) + { + return deimos::FormatArg(status, FormatStatus); + } }; inline Status UnknownError(StringView message = {}) diff --git a/deimos/core/std.h b/deimos/core/std.h index 4bb2983..0e0336e 100644 --- a/deimos/core/std.h +++ b/deimos/core/std.h @@ -24,6 +24,7 @@ template concept signed_integral = integral && __is_signed(T); template concept unsigned_integral = integral && __is_unsigned(T); template constexpr bool is_trivially_destructible_v = __is_trivially_destructible(T); +template constexpr bool is_constructible_v = __is_constructible(T, Args...); template constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T); template constexpr bool _is_same_helper = false; diff --git a/deimos/core/temp_allocator.cpp b/deimos/core/temp_allocator.cpp index 2f07bcc..d2b7900 100644 --- a/deimos/core/temp_allocator.cpp +++ b/deimos/core/temp_allocator.cpp @@ -41,7 +41,7 @@ public: if (new_current > m_commit_end) { const int64_t new_commit_size = AlignUp( - (uint64_t)(std::bit_cast(new_current) - std::bit_cast(m_base)), // NOLINT + (int64_t)(std::bit_cast(new_current) - std::bit_cast(m_base)), // NOLINT kPageSize); os_api->virtual_memory->Commit(m_base, new_commit_size); m_commit_end = OffsetBytes(m_base, new_commit_size); -- cgit