aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-18 13:59:50 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-18 13:59:50 +0100
commit0c8e77b367ca617beb2c30cd7e032cd9b24aeea4 (patch)
tree80d6b1ae257799a5af94526ea3108441e69f5c89 /libs
parent6733428bee53a316ae925cc6378a793be467e86f (diff)
downloadteachos-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.hpp2
-rw-r--r--libs/kstd/include/kstd/bits/formatter.hpp104
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