diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-12-18 13:59:50 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-12-18 13:59:50 +0100 |
| commit | 0c8e77b367ca617beb2c30cd7e032cd9b24aeea4 (patch) | |
| tree | 80d6b1ae257799a5af94526ea3108441e69f5c89 /libs | |
| parent | 6733428bee53a316ae925cc6378a793be467e86f (diff) | |
| download | teachos-0c8e77b367ca617beb2c30cd7e032cd9b24aeea4.tar.xz teachos-0c8e77b367ca617beb2c30cd7e032cd9b24aeea4.zip | |
kstd: finish integral formatting implementation
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/kstd/include/kstd/bits/format_context.hpp | 2 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/bits/formatter.hpp | 104 |
2 files changed, 62 insertions, 44 deletions
diff --git a/libs/kstd/include/kstd/bits/format_context.hpp b/libs/kstd/include/kstd/bits/format_context.hpp index 69f0629..b5c7d21 100644 --- a/libs/kstd/include/kstd/bits/format_context.hpp +++ b/libs/kstd/include/kstd/bits/format_context.hpp @@ -12,7 +12,7 @@ namespace kstd { using writer_function = void(void *, std::string_view); - writer_function writer; + writer_function * writer; void * user_data; constexpr auto push(std::string_view string) -> void diff --git a/libs/kstd/include/kstd/bits/formatter.hpp b/libs/kstd/include/kstd/bits/formatter.hpp index ce29b59..0fea5ef 100644 --- a/libs/kstd/include/kstd/bits/formatter.hpp +++ b/libs/kstd/include/kstd/bits/formatter.hpp @@ -12,6 +12,7 @@ #include <iterator> #include <string_view> #include <type_traits> +#include <utility> namespace kstd { @@ -31,7 +32,17 @@ namespace kstd auto format(T value, format_context & context) -> void { - using unsigned_T = std::make_unsigned<T>; + enum struct base + { + bin = 2, + oct = 8, + dec = 10, + hex = 16, + }; + + constexpr auto static maximum_digits = 80; + + using unsigned_T = std::make_unsigned_t<T>; auto absolute_value = static_cast<unsigned_T>(value); auto is_negative = false; @@ -50,31 +61,33 @@ namespace kstd case 'x': case 'X': case 'p': - return 16; + return base::hex; case 'b': case 'B': - return 2; + return base::bin; case 'o': - return 8; + return base::oct; default: - return 10; + return base::dec; } }(); - auto buffer = std::array<char, 80>{}; - auto digits = (base == 16) ? "0123456789abcdef" : "0123456789"; + auto buffer = std::array<char, maximum_digits>{}; + auto digits = (base == base::hex) ? "0123456789abcdef" : "0123456789"; auto current = buffer.rbegin(); if (absolute_value == 0) { - *std::next(current) = '0'; + *current = '0'; + std::advance(current, 1); } else { while (absolute_value != 0) { - *std::next(current) = digits[absolute_value % base]; - absolute_value /= base; + *current = digits[absolute_value % std::to_underlying(base)]; + std::advance(current, 1); + absolute_value /= std::to_underlying(base); } } @@ -82,19 +95,21 @@ namespace kstd auto prefix_length = 0uz; if (specs.alternative_form && value != 0) { - if (base == 16) + switch (base) { - prefix[1] = specs.type == 'X' ? 'X' : 'x'; - prefix_length = 2; - } - else if (base == 8) - { - prefix_length = 1; - } - else if (base == 2) - { - prefix[1] = specs.type == 'B' ? 'B' : 'b'; - prefix_length = 2; + case base::bin: + prefix[1] = specs.type == 'B' ? 'B' : 'b'; + prefix_length = 2; + break; + case base::oct: + prefix_length = 1; + break; + case base::hex: + prefix[1] = specs.type == 'X' ? 'X' : 'x'; + prefix_length = 2; + break; + default: + break; } } @@ -156,38 +171,41 @@ namespace kstd struct format_arg { + using formatting_function = std::string_view(void const *, std::string_view, format_context &); + void const * value; - auto (*format)(void const *, std::string_view, format_context &) -> std::string_view; + formatting_function * format; }; - template<typename T> - auto format_dispatcher(void const * val, std::string_view spec, format_context & ctx) -> std::string_view + struct format_args { - formatter<T> f; - auto const remainder = f.parse(spec); - f.format(*static_cast<T const *>(val), ctx); - return remainder; - } - - class format_args - { - format_arg const * args_; - std::size_t count_; - - public: - constexpr format_args(format_arg const * args, std::size_t count) - : args_(args) - , count_(count) + constexpr format_args(format_arg const * args, std::size_t number_of_args) + : m_args(args) + , m_number_of_args(number_of_args) {} - [[nodiscard]] constexpr auto get(std::size_t idx) const -> format_arg + [[nodiscard]] constexpr auto get(std::size_t index) const -> format_arg { - if (idx >= count_) + if (index >= m_number_of_args) return {.value = nullptr, .format = nullptr}; - return args_[idx]; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + return m_args[index]; } + + private: + format_arg const * m_args; + std::size_t m_number_of_args; }; + template<typename T> + auto format_dispatcher(void const * value, std::string_view format_spec, format_context & context) -> std::string_view + { + auto formatter_for_T = formatter<T>{}; + auto const remainder = formatter_for_T.parse(format_spec); + formatter_for_T.format(*static_cast<T const *>(value), context); + return remainder; + } + } // namespace kstd #endif
\ No newline at end of file |
