// Copyright 2025 Steven Le Rouzic // // SPDX-License-Identifier: BSD-3-Clause #include "asl/types/status.hpp" #include "asl/memory/allocator.hpp" #include "asl/strings/string.hpp" #include "asl/synchronization/atomic.hpp" #include "asl/formatting/format.hpp" #include "asl/strings/string_builder.hpp" // @Todo Use custom allocator using Allocator = asl::DefaultAllocator; // NOLINTNEXTLINE(*-non-const-global-variables) static Allocator g_allocator{}; namespace asl { struct StatusInternal { asl::string msg; asl::status_code code; asl::atomic ref_count; constexpr StatusInternal(asl::string&& msg_, asl::status_code code_) : msg{std::move(msg_)} , code{code_} { ASL_ASSERT(code != asl::status_code::ok); atomic_store(&ref_count, 1); } }; } // namespace asl asl::status::status(status_code code, string_view msg) : m_payload{alloc_new(g_allocator, msg, code)} {} asl::status::status(status_code code, string_view fmt, span args) { StringWriter sink{g_allocator}; format_internals::format(&sink, fmt, args); m_payload = alloc_new(g_allocator, std::move(sink).finish(), code); } asl::status_code asl::status::code_internal() const { ASL_ASSERT(!is_inline()); return m_payload->code; } asl::string_view asl::status::message_internal() const { ASL_ASSERT(!is_inline()); return m_payload->msg; } void asl::status::ref() { ASL_ASSERT(!is_inline()); atomic_fetch_increment(&m_payload->ref_count, memory_order::relaxed); } void asl::status::unref() { ASL_ASSERT(!is_inline()); if (atomic_fetch_decrement(&m_payload->ref_count, memory_order::release) == 1) { atomic_fence(memory_order::acquire); alloc_delete(g_allocator, m_payload); m_payload = nullptr; } } void asl::AslFormat(asl::Formatter& f, const asl::status& s) { string_view status_str{}; switch (s.code()) { case status_code::ok: status_str = "ok"_sv; break; case status_code::unknown: status_str = "unknown"_sv; break; case status_code::internal: status_str = "internal"_sv; break; case status_code::runtime: status_str = "runtime"_sv; break; case status_code::invalid_argument: status_str = "invalid_argument"_sv; break; default: status_str = ""_sv; break; } if (s.is_inline()) { format(f.writer(), "[{}]", status_str); } else { format(f.writer(), "[{}: {}]", status_str, s.message_internal()); } }