7 #include "arg_router/parsing/token_type.hpp"
9 #include "arg_router/utility/tuple_iterator.hpp"
11 #include <boost/mp11/algorithm.hpp>
12 #include <boost/mp11/list.hpp>
55 template <std::
size_t Start,
typename J>
57 static constexpr std::size_t start = Start;
61 template <
typename Str,
typename PHs, std::
size_t Current>
62 [[nodiscard]]
static constexpr
auto placeholders_impl() noexcept
64 constexpr
auto start = Str::get().find(
"{", Current);
65 constexpr
auto end = Str::get().find(
"}", Current + 1);
67 if constexpr ((start != std::string_view::npos) && (end != std::string_view::npos)) {
68 return placeholders_impl<
70 boost::mp11::mp_push_back<
73 AR_STRING_SV(Str::get().substr(start + 1, end - start - 1))>>,
80 template <
typename PH>
82 static constexpr
bool value = PH::joining::size() > 0;
85 template <
typename Str>
86 using generate_placeholders = std::decay_t<decltype(placeholders_impl<Str, std::tuple<>, 0>())>;
88 using initial_placeholders = generate_placeholders<S>;
98 if constexpr ((std::tuple_size_v<initial_placeholders>) > 0) {
99 return fmt<S>(tokens);
100 }
else if (!tokens.empty()) {
101 using greedy_appended =
typename S::template append_t<AR_STRING(
": {, }")>;
102 return fmt<greedy_appended>(tokens);
105 return string{S::get()};
111 [[nodiscard]]
static constexpr
bool placeholder_check() noexcept
113 if constexpr ((std::tuple_size_v<initial_placeholders>) > 1) {
114 constexpr
auto greedy_count =
115 boost::mp11::mp_count_if<initial_placeholders, is_greedy>::value;
116 static_assert(greedy_count <= 1,
117 "Can only be one greedy entry in the formatted string");
119 if constexpr (greedy_count == 1) {
120 return is_greedy<boost::mp11::mp_back<initial_placeholders>>::value;
126 static_assert(placeholder_check(),
"Greedy entry must be last in the formatted string");
128 template <
typename Str>
129 [[nodiscard]]
static string fmt(
const vector<parsing::token_type>& tokens)
131 using std::to_string;
132 using placeholders = generate_placeholders<Str>;
134 constexpr
auto bracket_width = std::size_t{2};
136 auto str =
string{Str::get()};
141 auto offset = std::size_t{0};
143 auto it = tokens.begin();
144 utility::tuple_type_iterator<placeholders>([&](
auto i) {
145 using PH = std::tuple_element_t<i, placeholders>;
149 constexpr
auto joining_str = PH::joining::get();
150 if (it != tokens.end()) {
152 auto pos = PH::start + offset;
153 str.replace(pos, joining_str.size() + bracket_width, next_str);
156 offset += next_str.size() - bracket_width;
158 if constexpr (!joining_str.empty()) {
160 pos += next_str.size();
161 for (; it != std::end(tokens); ++it) {
163 str.insert(pos, next_str);
164 pos += next_str.size();
169 str.replace(PH::start + offset, joining_str.size() + bracket_width,
"");
170 offset -= bracket_width;
constexpr std::string_view to_string(prefix_type prefix) noexcept
std::vector< T, config::allocator< T > > vector