9#include "../microfmt.hpp"
18template <
typename T,
typename =
void>
struct is_range : std::false_type {};
22 T, std::void_t<decltype(std::begin(std::declval<const T &>())), decltype(std::end(std::declval<const T &>()))>>
27template <
size_t N>
struct fixed_string {
31 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE
34 constexpr fixed_string(
const char (&str)[N + 1]) noexcept {
35 for (
size_t i = 0; i < N; ++i) {
41 RELOCO_END_UNSAFE_BUFFER_USAGE
43 [[nodiscard]]
constexpr microfmt::string_view view() const & noexcept RELOCO_LIFETIMEBOUND {
44 return microfmt::string_view(buf, N);
47 [[nodiscard]]
constexpr microfmt::string_view view() const && = delete;
50template <
size_t N> fixed_string(const
char (&)[N]) -> fixed_string<N - 1>;
59template <
typename It,
typename Sentinel = It>
struct RELOCO_POINTER
join_view {
62 microfmt::string_view delimiter{
", "};
71template <
typename It,
typename Sentinel, detail::fixed_
string Delim, detail::fixed_
string ElemSpec>
83template <
typename It,
typename Sentinel,
84 std::enable_if_t<!std::is_convertible_v<Sentinel, microfmt::string_view>,
int> = 0>
85[[nodiscard]]
constexpr auto join(It first, Sentinel last, microfmt::string_view delimiter =
", ") noexcept {
89template <typename Range, std::enable_if_t<detail::is_range<Range>::value,
int> = 0>
90[[nodiscard]]
constexpr auto join(
const Range &range, microfmt::string_view delimiter =
", ") noexcept {
93 return join_view<
decltype(begin(range)),
decltype(end(range))>{begin(range), end(range), delimiter};
96template <
typename Range,
98 !std::is_lvalue_reference_v<Range> && detail::is_range<std::remove_reference_t<Range>>::value,
int> = 0>
99[[nodiscard]]
constexpr auto join(Range &&, microfmt::string_view =
", ") noexcept = delete;
103template <detail::fixed_string Delim, detail::fixed_string ElemSpec =
"",
typename Range,
104 std::enable_if_t<detail::is_range<Range>::value,
int> = 0>
105[[nodiscard]]
constexpr auto join_as(
const Range &range)
noexcept {
108 return join_as_view<
decltype(begin(range)),
decltype(end(range)), Delim, ElemSpec>{begin(range), end(range)};
111template <detail::fixed_string Delim, detail::fixed_string ElemSpec =
"",
typename Range,
113 !std::is_lvalue_reference_v<Range> && detail::is_range<std::remove_reference_t<Range>>::value,
int> = 0>
114[[nodiscard]]
constexpr auto join_as(Range &&) noexcept = delete;
116template <detail::fixed_string Delim, detail::fixed_string ElemSpec = "", typename It, typename Sentinel,
117 std::enable_if_t<!std::is_convertible_v<Sentinel,
microfmt::string_view>,
int> = 0>
118[[nodiscard]] constexpr auto join_as(It first, Sentinel last) noexcept {
119 return join_as_view<It, Sentinel, Delim, ElemSpec>{first, last};
128 microfmt::string_view elem_spec{
""};
133 using ValueType = std::remove_cv_t<std::remove_reference_t<decltype(*std::declval<It>())>>;
137 element_fmt.
parse(elem_ctx);
139 bool is_first =
true;
140 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
142 for (
auto it = jv.first; it != jv.last; ++it) {
144 out.write(jv.delimiter);
147 element_fmt.
format(*it, out);
149 RELOCO_END_UNSAFE_BUFFER_USAGE;
158template <
typename It,
typename Sentinel, detail::fixed_
string Delim, detail::fixed_
string ElemSpec>
159struct formatter<join_as_view<It, Sentinel, Delim, ElemSpec>> {
160 microfmt::string_view runtime_spec{
""};
162 constexpr void parse(format_parse_context &ctx)
noexcept { runtime_spec = ctx.spec(); }
164 void format(
const join_as_view<It, Sentinel, Delim, ElemSpec> &jv,
const sink &out)
const noexcept {
165 using ValueType = std::remove_cv_t<std::remove_reference_t<decltype(*std::declval<It>())>>;
167 constexpr microfmt::string_view ct_elem_spec = ElemSpec.view();
168 const microfmt::string_view effective_spec = !ct_elem_spec.empty() ? ct_elem_spec : runtime_spec;
170 detail::element_formatter<ValueType> element_fmt;
171 format_parse_context elem_ctx(effective_spec);
172 element_fmt.parse(elem_ctx);
174 bool is_first =
true;
175 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
177 for (
auto it = jv.first; it != jv.last; ++it) {
179 out.write(Delim.view());
182 element_fmt.format(*it, out);
185 RELOCO_END_UNSAFE_BUFFER_USAGE;
Definition microfmt.hpp:881
RELOCO_END_UNSAFE_CODE auto format(microfmt::string_view fmt_str, const Args &...args) noexcept
Definition fmt.hpp:178
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
constexpr joined_span_view< T > join(span< const T > items, microfmt::string_view delim=", ") noexcept
Definition format_helpers.hpp:239
It first
Definition ranges.hpp:60
Sentinel last
Definition ranges.hpp:61