diff options
Diffstat (limited to 'kapi')
| -rw-r--r-- | kapi/kapi/system.hpp | 102 |
1 files changed, 78 insertions, 24 deletions
diff --git a/kapi/kapi/system.hpp b/kapi/kapi/system.hpp index 80233507..d8a306d3 100644 --- a/kapi/kapi/system.hpp +++ b/kapi/kapi/system.hpp @@ -6,8 +6,8 @@ #include <array> #include <cstddef> +#include <iterator> #include <source_location> -#include <span> #include <string_view> #include <type_traits> @@ -17,25 +17,76 @@ namespace kapi::system //! @addtogroup kapi-system-kernel-defined //! @{ - template<typename... FormatArguments> - struct panic_format_string + namespace detail { - kstd::format_string<FormatArguments...> format; - std::source_location location; - - template<std::size_t Size> - consteval panic_format_string(char const (&format)[Size], // NOLINT - std::source_location location = std::source_location::current()) - : format{format} - , location{location} - {} - - consteval panic_format_string(std::string_view format, - std::source_location location = std::source_location::current()) - : format{format} - , location{location} - {} - }; + template<typename... FormatArguments> + struct panic_format_string + { + kstd::format_string<FormatArguments...> format; + std::source_location location; + + template<std::size_t Size> + consteval panic_format_string(char const (&format)[Size], // NOLINT + std::source_location location = std::source_location::current()) + : format{format} + , location{location} + {} + + consteval panic_format_string(std::string_view format, + std::source_location location = std::source_location::current()) + : format{format} + , location{location} + {} + }; + + struct panic_buffer + { + ~panic_buffer(); + + void append(char character); + void flush(); + + private: + std::array<char, 16> m_buffer{}; + std::size_t m_written{}; + }; + + struct panic_iterator + { + using iterator_category = std::output_iterator_tag; + using iterator_concept = std::output_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = void; + using pointer = void; + using reference = void; + + explicit panic_iterator(panic_buffer & buffer); + + auto operator*() noexcept -> panic_iterator &; + auto operator=(char character) -> panic_iterator &; + auto operator++() -> panic_iterator &; + auto operator++(int) -> panic_iterator; + + private: + panic_buffer * m_buffer; + }; + + } // namespace detail + + //! Initiate panic processing. + //! + //! @param location The location where the panic occurred. + auto panic_start(std::source_location location) -> void; + + //! Write panic output. + //! + //! @param message The message to write. + auto panic_write(std::string_view message) -> void; + + //! Finish panic processing + //! + //! @param location The location where the panic occurred. + [[noreturn]] auto panic_finish(std::source_location location) -> void; //! Terminate kernel execution with the given error message. //! @@ -61,14 +112,17 @@ namespace kapi::system auto memory_initialized() -> void; //! @} // end group platform-defined - // + template<typename... FormatArguments> - [[noreturn]] auto panic(panic_format_string<std::type_identity_t<FormatArguments>...> format, + [[noreturn]] auto panic(detail::panic_format_string<std::type_identity_t<FormatArguments>...> format, FormatArguments &&... arguments) { - auto buffer = std::array<char, 512uz>{}; - auto [_, length] = kstd::format_to(std::span{buffer}, format.format, std::forward<FormatArguments>(arguments)...); - panic(std::string_view{buffer.data(), length}, format.location); + panic_start(format.location); + { + auto buffer = detail::panic_buffer{}; + kstd::format_to(detail::panic_iterator{buffer}, format.format, std::forward<FormatArguments>(arguments)...); + } + panic_finish(format.location); } } // namespace kapi::system |
