aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-06-24 13:03:29 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-06-24 13:03:29 +0200
commit08bfe2af099f6acc78772e7b315a6cf922626b76 (patch)
tree81e67f61dfb185d2e53d28cd90c230dfa71caf62
parent3027e4c819814aac93ef1f993bde04acf3ee3f54 (diff)
downloadkernel-08bfe2af099f6acc78772e7b315a6cf922626b76.tar.xz
kernel-08bfe2af099f6acc78772e7b315a6cf922626b76.zip
kstd: implement kstd::formatted_size
-rw-r--r--.nvim.lua2
-rw-r--r--libs/kstd/CMakeLists.txt2
-rw-r--r--libs/kstd/kstd/bits/format/string.hpp8
-rw-r--r--libs/kstd/kstd/bits/format/vformat.cpp (renamed from libs/kstd/kstd/vformat.cpp)15
-rw-r--r--libs/kstd/kstd/bits/format/vformat.hpp41
-rw-r--r--libs/kstd/kstd/format36
-rw-r--r--libs/kstd/kstd/format.test.cpp68
7 files changed, 139 insertions, 33 deletions
diff --git a/.nvim.lua b/.nvim.lua
index 14ca59ca..0f8f5119 100644
--- a/.nvim.lua
+++ b/.nvim.lua
@@ -10,7 +10,7 @@ vim.g.load_doxygen_syntax = true
-- C++
vim.filetype.add({
pattern = {
- [".*/include/kstd/.*"] = function(path, _)
+ [".*/libs/kstd/kstd/.*"] = function(path, _)
if not path:match("%.[^/]+$") then
return "cpp"
end
diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt
index 5a957573..002fb548 100644
--- a/libs/kstd/CMakeLists.txt
+++ b/libs/kstd/CMakeLists.txt
@@ -18,7 +18,7 @@ add_library("kstd::lib" ALIAS "kstd")
target_sources("kstd" PRIVATE
"kstd/os/error.cpp"
"kstd/mutex.cpp"
- "kstd/vformat.cpp"
+ "kstd/bits/format/vformat.cpp"
)
file(GLOB_RECURSE KSTD_HEADERS
diff --git a/libs/kstd/kstd/bits/format/string.hpp b/libs/kstd/kstd/bits/format/string.hpp
index e7e40886..a2b298d4 100644
--- a/libs/kstd/kstd/bits/format/string.hpp
+++ b/libs/kstd/kstd/bits/format/string.hpp
@@ -72,8 +72,7 @@ namespace kstd
template<typename... Args>
struct format_string
{
- template<std::size_t Size>
- consteval format_string(char const (&str)[Size]) noexcept(false) // NOLINT
+ consteval format_string(std::string_view const & str) noexcept(false)
: str_view{str}
{
using namespace bits::format;
@@ -140,6 +139,11 @@ namespace kstd
}
}
+ template<std::size_t Size>
+ consteval format_string(char const (&str)[Size]) noexcept(false) // NOLINT
+ : format_string{std::string_view{str}}
+ {}
+
std::string_view str_view;
};
diff --git a/libs/kstd/kstd/vformat.cpp b/libs/kstd/kstd/bits/format/vformat.cpp
index b7c51218..1bf293a4 100644
--- a/libs/kstd/kstd/vformat.cpp
+++ b/libs/kstd/kstd/bits/format/vformat.cpp
@@ -206,4 +206,19 @@ namespace kstd::bits::format
return std::move(m_result);
}
+ auto size_recorder::push(std::string_view text) -> void
+ {
+ m_size += text.size();
+ }
+
+ auto size_recorder::push(char) -> void
+ {
+ ++m_size;
+ }
+
+ auto size_recorder::size() const noexcept -> std::size_t
+ {
+ return m_size;
+ }
+
} // namespace kstd::bits::format \ No newline at end of file
diff --git a/libs/kstd/kstd/bits/format/vformat.hpp b/libs/kstd/kstd/bits/format/vformat.hpp
index 994fae50..2db56d17 100644
--- a/libs/kstd/kstd/bits/format/vformat.hpp
+++ b/libs/kstd/kstd/bits/format/vformat.hpp
@@ -3,12 +3,13 @@
// IWYU pragma: private, include <kstd/format>
+#include <kstd/bits/basic_string.hpp>
#include <kstd/bits/format/args.hpp>
#include <kstd/bits/format/output_buffer.hpp>
#include <kstd/bits/format/string.hpp>
-#include <kstd/string>
#include <algorithm>
+#include <cstddef>
#include <iterator>
#include <string_view>
#include <type_traits>
@@ -29,13 +30,25 @@ namespace kstd
struct string_writer : output_buffer
{
- auto push(std::string_view text) -> void override;
- auto push(char character) -> void override;
+ auto push(std::string_view text) -> void final;
+ auto push(char character) -> void final;
- auto release() -> string &&;
+ auto release() -> basic_string<char> &&;
private:
- string m_result{};
+ basic_string<char> m_result{};
+ };
+
+ //! A buffer that merely records the size of the output written to it.
+ struct size_recorder : output_buffer
+ {
+ auto push(std::string_view text) -> void final;
+ auto push(char character) -> void final;
+
+ [[nodiscard]] auto size() const noexcept -> std::size_t;
+
+ private:
+ std::size_t m_size{};
};
template<std::output_iterator<char> Output>
@@ -72,7 +85,8 @@ namespace kstd
//! @param args The arguments for the format string.
//! @return A new string containing the result of the format operation.
template<typename... ArgumentTypes>
- auto format(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args) -> string
+ auto format(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
+ -> basic_string<char>
{
auto buffer = bits::format::string_writer{};
bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
@@ -94,6 +108,21 @@ namespace kstd
return buffer.iterator();
}
+ //! Determine the number of characters required to format the format string with the given arguments.
+ //!
+ //! @param format The format string.
+ //! @param args The arguments for the format string.
+ //! @tparam ArgumentTypes The type of the format string arguments.
+ //! @return The number of characters required to format @p format with @p args
+ template<typename... ArgumentTypes>
+ auto formatted_size(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
+ -> std::size_t
+ {
+ auto buffer = bits::format::size_recorder{};
+ bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
+ return buffer.size();
+ }
+
} // namespace kstd
#endif \ No newline at end of file
diff --git a/libs/kstd/kstd/format b/libs/kstd/kstd/format
index e04b79a9..5ed798db 100644
--- a/libs/kstd/kstd/format
+++ b/libs/kstd/kstd/format
@@ -1,22 +1,24 @@
#ifndef KSTD_FORMAT_HPP
#define KSTD_FORMAT_HPP
-#include <kstd/bits/format/arg.hpp> // IWYU pragma: export
-#include <kstd/bits/format/args.hpp> // IWYU pragma: export
-#include <kstd/bits/format/context.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/bool.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/byte.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/char.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/cstring.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/integral.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/ordering.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/pointer.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/range.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/string_view.hpp> // IWYU pragma: export
-#include <kstd/bits/format/output_buffer.hpp> // IWYU pragma: export
-#include <kstd/bits/format/parse_context.hpp> // IWYU pragma: export
-#include <kstd/bits/format/string.hpp> // IWYU pragma: export
-#include <kstd/bits/format/vformat.hpp> // IWYU pragma: export
+// IWYU pragma: begin_exports
+#include <kstd/bits/format/arg.hpp>
+#include <kstd/bits/format/args.hpp>
+#include <kstd/bits/format/context.hpp>
+#include <kstd/bits/format/formatter.hpp>
+#include <kstd/bits/format/formatter/bool.hpp>
+#include <kstd/bits/format/formatter/byte.hpp>
+#include <kstd/bits/format/formatter/char.hpp>
+#include <kstd/bits/format/formatter/cstring.hpp>
+#include <kstd/bits/format/formatter/integral.hpp>
+#include <kstd/bits/format/formatter/ordering.hpp>
+#include <kstd/bits/format/formatter/pointer.hpp>
+#include <kstd/bits/format/formatter/range.hpp>
+#include <kstd/bits/format/formatter/string_view.hpp>
+#include <kstd/bits/format/output_buffer.hpp>
+#include <kstd/bits/format/parse_context.hpp>
+#include <kstd/bits/format/string.hpp>
+#include <kstd/bits/format/vformat.hpp>
+// IWYU pragma: end_exports
#endif \ No newline at end of file
diff --git a/libs/kstd/kstd/format.test.cpp b/libs/kstd/kstd/format.test.cpp
index 624779af..6126605f 100644
--- a/libs/kstd/kstd/format.test.cpp
+++ b/libs/kstd/kstd/format.test.cpp
@@ -4,14 +4,17 @@
#include <iterator>
#include <sstream>
+#include <string_view>
+
+using namespace std::string_view_literals;
SCENARIO("Formatting to a new string", "[format]")
{
GIVEN("a format string without any placeholders")
{
- auto const & fmt = "This is a test";
+ constexpr auto fmt = "This is a test"sv;
- WHEN("calling format with without any arguments.")
+ WHEN("calling format without any arguments.")
{
auto result = kstd::format(fmt);
@@ -34,7 +37,7 @@ SCENARIO("Formatting to a new string", "[format]")
GIVEN("a format string with placeholders")
{
- auto const & fmt = "Here are some placeholders: {} {} {}";
+ constexpr auto fmt = "Here are some placeholders: {} {} {}"sv;
WHEN("calling format with the same number of arguments as there are placeholders")
{
@@ -64,9 +67,9 @@ SCENARIO("Formatting to an output iterator", "[format]")
GIVEN("a format string without any placeholders")
{
- auto const & fmt = "This is a test";
+ constexpr auto fmt = "This is a test"sv;
- WHEN("calling format with without any arguments.")
+ WHEN("calling format without any arguments.")
{
kstd::format_to(std::ostream_iterator<char>{buffer}, fmt);
@@ -89,7 +92,7 @@ SCENARIO("Formatting to an output iterator", "[format]")
GIVEN("a format string with placeholders")
{
- auto const & fmt = "Here are some placeholders: {} {} {}";
+ constexpr auto fmt = "Here are some placeholders: {} {} {}"sv;
WHEN("calling format with the same number of arguments as there are placeholders")
{
@@ -111,4 +114,57 @@ SCENARIO("Formatting to an output iterator", "[format]")
}
}
}
+}
+
+SCENARIO("Determining formatted size")
+{
+ GIVEN("a format string without any placeholders")
+ {
+ constexpr auto fmt = "This is a test"sv;
+
+ WHEN("calling formatted_size without any arguments")
+ {
+ auto const size = kstd::formatted_size(fmt);
+
+ THEN("the result is equal to the length of the format string")
+ {
+ REQUIRE(size == fmt.size());
+ }
+ }
+
+ WHEN("calling format with additional arguments")
+ {
+ auto const size = kstd::formatted_size(fmt, 1, 2, 3);
+
+ THEN("the result is equal to the length of the format string")
+ {
+ REQUIRE(size == fmt.size());
+ }
+ }
+ }
+
+ GIVEN("a format string with placeholders")
+ {
+ constexpr auto fmt = "Here are some placeholders: {} {} {}"sv;
+
+ WHEN("calling format with the same number of arguments as there are placeholders")
+ {
+ auto result = kstd::formatted_size(fmt, 1, true, 'a');
+
+ THEN("the result is the formatted length")
+ {
+ REQUIRE(result == std::string_view{"Here are some placeholders: 1 true a"}.size());
+ }
+ }
+
+ WHEN("calling format with too many arguments")
+ {
+ auto result = kstd::formatted_size(fmt, 2, false, 'b', 4, 5, 6);
+
+ THEN("the result is the formatted length")
+ {
+ REQUIRE(result == std::string_view{"Here are some placeholders: 2 false b"}.size());
+ }
+ }
+ }
} \ No newline at end of file