From 3795115641bf5c1d1a3d60313408ba462057ba18 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 13 Apr 2026 16:18:00 +0200 Subject: kstd/format: add support for char formatting --- .../include/kstd/bits/format/formatter/char.hpp | 94 ++++++++++++++++++++++ libs/kstd/include/kstd/format | 1 + libs/kstd/tests/src/format.cpp | 8 +- 3 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 libs/kstd/include/kstd/bits/format/formatter/char.hpp (limited to 'libs/kstd') diff --git a/libs/kstd/include/kstd/bits/format/formatter/char.hpp b/libs/kstd/include/kstd/bits/format/formatter/char.hpp new file mode 100644 index 0000000..ddfefe5 --- /dev/null +++ b/libs/kstd/include/kstd/bits/format/formatter/char.hpp @@ -0,0 +1,94 @@ +#ifndef KSTD_BITS_FORMAT_FORMATTER_CHAR_HPP +#define KSTD_BITS_FORMAT_FORMATTER_CHAR_HPP + +#include "../context.hpp" +#include "../error.hpp" +#include "../formatter.hpp" +#include "../parse_context.hpp" +#include "../specifiers.hpp" +#include "integral.hpp" + +#include + +namespace kstd +{ + + template<> + struct formatter : formatter + { + bits::format::specifiers specifiers{}; + + constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator + { + specifiers = bits::format::parse_format_specifiers(context); + + auto it = context.begin(); + auto const end = context.end(); + + if (specifiers.alternative_form || specifiers.zero_pad || specifiers.sign != bits::format::sign_mode::none) + { + bits::format::error("Invalid format specifiers for 'char'"); + } + + if (it != end && *it != '}') + { + if (*it == 'c' || *it == 'b' || *it == 'B' || *it == 'd' || *it == 'o' || *it == 'x' || *it == 'X') + { + specifiers.type = *it; + std::advance(it, 1); + } + else + { + bits::format::error("Invalid type specifier for char."); + } + } + + if (it != end && *it != '}') + { + bits::format::error("Missing terminating '}' in format string."); + } + + return it; + } + + auto format(char value, format_context & context) const -> void + { + if (specifiers.type == '\0' || specifiers.type == 'c') + { + auto final_width = 0uz; + + if (specifiers.mode == bits::format::width_mode::static_value) + { + final_width = specifiers.width_value; + } + else if (specifiers.mode == bits::format::width_mode::dynamic_argument_id) + { + auto const & arg = context.arg(specifiers.width_value); + final_width = bits::format::extrat_dynamic_width(arg); + } + + auto padding = + bits::format::calculate_format_padding(final_width, 1, specifiers.align, bits::format::alignment::left); + + for (auto i = 0uz; i < padding.left; ++i) + { + context.push(specifiers.fill); + } + + context.push(value); + + for (auto i = 0uz; i < padding.right; ++i) + { + context.push(specifiers.fill); + } + } + else + { + formatter::format(static_cast(value), context); + } + } + }; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/include/kstd/format b/libs/kstd/include/kstd/format index d11c221..047ea5c 100644 --- a/libs/kstd/include/kstd/format +++ b/libs/kstd/include/kstd/format @@ -7,6 +7,7 @@ #include "bits/format/formatter.hpp" // IWYU pragma: export #include "bits/format/formatter/bool.hpp" // IWYU pragma: export #include "bits/format/formatter/byte.hpp" // IWYU pragma: export +#include "bits/format/formatter/char.hpp" // IWYU pragma: export #include "bits/format/formatter/cstring.hpp" // IWYU pragma: export #include "bits/format/formatter/integral.hpp" // IWYU pragma: export #include "bits/format/formatter/ordering.hpp" // IWYU pragma: export diff --git a/libs/kstd/tests/src/format.cpp b/libs/kstd/tests/src/format.cpp index 4915e50..73c8102 100644 --- a/libs/kstd/tests/src/format.cpp +++ b/libs/kstd/tests/src/format.cpp @@ -40,21 +40,21 @@ SCENARIO("Formatting to a new string", "[format]") WHEN("calling format with the same number of arguments as there are placeholders") { - auto result = kstd::format(fmt, 1, true, -100); + auto result = kstd::format(fmt, 1, true, 'a'); THEN("the result is the formatted string") { - REQUIRE(result == "Here are some placeholders: 1 true -100"); + REQUIRE(result == "Here are some placeholders: 1 true a"); } } WHEN("calling format with too many arguments") { - auto result = kstd::format(fmt, 2, false, -200, 4, 5, 6); + auto result = kstd::format(fmt, 2, false, 'b', 4, 5, 6); THEN("the result is the formatted string") { - REQUIRE(result == "Here are some placeholders: 2 false -200"); + REQUIRE(result == "Here are some placeholders: 2 false b"); } } } -- cgit v1.2.3