diff options
| -rw-r--r-- | libs/kstd/include/kstd/bits/format/formatter.hpp | 73 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/bits/format/formatter/range.hpp | 32 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/format | 1 |
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 |
