aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter.hpp73
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/range.hpp32
-rw-r--r--libs/kstd/include/kstd/format1
3 files changed, 106 insertions, 0 deletions
diff --git a/libs/kstd/include/kstd/bits/format/formatter.hpp b/libs/kstd/include/kstd/bits/format/formatter.hpp
index f391c8e..096168d 100644
--- a/libs/kstd/include/kstd/bits/format/formatter.hpp
+++ b/libs/kstd/include/kstd/bits/format/formatter.hpp
@@ -3,6 +3,14 @@
// IWYU pragma: private, include <kstd/format>
+#include "context.hpp"
+#include "error.hpp"
+#include "parse_context.hpp"
+
+#include <algorithm>
+#include <iterator>
+#include <string_view>
+
namespace kstd
{
@@ -14,6 +22,71 @@ namespace kstd
auto operator=(formatter const &) -> formatter & = delete;
};
+ template<typename ValueType>
+ struct range_formatter
+ {
+ constexpr auto set_separator(std::string_view sep) -> void
+ {
+ m_separator = sep;
+ }
+
+ constexpr auto set_brackets(std::string_view opening, std::string_view closing)
+ {
+ m_prefix = opening;
+ m_suffix = closing;
+ }
+
+ constexpr auto parse(format_parse_context & context)
+ {
+ auto it = context.begin();
+ auto const end = context.end();
+
+ if (it != end && *it == 'n')
+ {
+ set_brackets("", "");
+ std::advance(it, 1);
+ }
+
+ if (it != end && *it == ':')
+ {
+ std::advance(it, 1);
+ context.advance_to(it);
+ it = m_inner_formatter.parse(context);
+ }
+
+ if (it != end && *it != '}')
+ {
+ bits::format::error("Invalid formate specifier for range");
+ }
+
+ return it;
+ }
+
+ template<typename Range>
+ auto format(Range const & range, format_context & context)
+ {
+ context.push(m_prefix);
+
+ auto is_first = true;
+ std::ranges::for_each(range, [&](auto const & element) {
+ if (!is_first)
+ {
+ context.push(m_separator);
+ }
+ m_inner_formatter.format(element, context);
+ is_first = false;
+ });
+
+ context.push(m_suffix);
+ }
+
+ private:
+ kstd::formatter<ValueType> m_inner_formatter{};
+ std::string_view m_separator{", "};
+ std::string_view m_prefix{"["};
+ std::string_view m_suffix{"]"};
+ };
+
} // namespace kstd
#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/range.hpp b/libs/kstd/include/kstd/bits/format/formatter/range.hpp
new file mode 100644
index 0000000..54ee7fb
--- /dev/null
+++ b/libs/kstd/include/kstd/bits/format/formatter/range.hpp
@@ -0,0 +1,32 @@
+#ifndef KSTD_BITS_FORMAT_FORMATTER_RANGE_HPP
+#define KSTD_BITS_FORMAT_FORMATTER_RANGE_HPP
+
+#include "../formatter.hpp"
+
+#include <concepts>
+#include <ranges>
+#include <string_view>
+#include <type_traits>
+
+namespace kstd
+{
+ namespace bits::format
+ {
+ template<typename T>
+ concept iterable = requires(T const & t) {
+ t.begin();
+ t.end();
+ };
+
+ template<typename T>
+ concept formattable_range = iterable<T> && !std::same_as<std::remove_cvref_t<T>, std::string_view> &&
+ !std::same_as<std::decay_t<T>, char *> && !std::same_as<std::decay_t<T>, char const *>;
+ } // namespace bits::format
+
+ template<bits::format::formattable_range Range>
+ struct formatter<Range> : range_formatter<std::ranges::range_value_t<Range>>
+ {
+ };
+} // namespace kstd
+
+#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/format b/libs/kstd/include/kstd/format
index 76aaed8..946ed69 100644
--- a/libs/kstd/include/kstd/format
+++ b/libs/kstd/include/kstd/format
@@ -10,6 +10,7 @@
#include "bits/format/formatter/integral.hpp" // IWYU pragma: export
#include "bits/format/formatter/ordering.hpp" // IWYU pragma: export
#include "bits/format/formatter/pointer.hpp" // IWYU pragma: export
+#include "bits/format/formatter/range.hpp" // IWYU pragma: export
#include "bits/format/formatter/string_view.hpp" // IWYU pragma: export
#include "bits/format/parse_context.hpp" // IWYU pragma: export
#include "bits/format/string.hpp" // IWYU pragma: export