38 std::string_view::const_iterator
pos;
40 explicit FmtCtx(std::string_view p);
42 bool parsing(std::string &args);
67 if (opt.
wide <= len) {
71 auto diff = opt.
wide - len;
75 builder << std::string(diff, opt.
wide_char);
78 builder << std::string(diff, opt.
wide_char);
82 builder << std::string(diff / 2, opt.
wide_char);
84 builder << std::string((diff % 2 == 1 ? (diff / 2 + 1) : (diff / 2)), opt.
wide_char);
99 }
else if (radix ==
'x') {
101 }
else if (radix ==
'o') {
103 }
else if (radix ==
'b') {
129 if (opt.
wide <= len) {
136 auto diff = opt.
wide - len;
143 builder << std::string(diff, opt.
wide_char);
146 builder << std::string(diff, opt.
wide_char);
153 builder << std::string(diff / 2, opt.
wide_char);
158 builder << std::string((diff % 2 == 1 ? (diff / 2 + 1) : (diff / 2)), opt.
wide_char);
164 template<
typename VALUE,
typename ENABLE =
void>
166 bool parse(
const std::string &) {
return false; }
184 bool parse(
const std::string &opt_str) {
193 template<
typename VALUE>
194 struct Formatter<VALUE, std::enable_if_t<std::is_integral_v<VALUE>>> {
197 bool parse(
const std::string &opt_str) {
206 template<
typename VALUE>
207 struct Formatter<VALUE, std::enable_if_t<std::is_floating_point_v<VALUE>>> {
210 bool parse(
const std::string &opt_str) {
215 if (std::isnan(value)) {
223 template<
typename VALUE>
224 struct Formatter<VALUE, std::enable_if_t<is_iterable_v<VALUE>>> {
229 bool parse(
const std::string &args) {
230 if (args.size() == 3) {
243 for (
auto &&item: value) {
250 formatter.format(ctx, item);
258template<typename C, std::enable_if_t<!is_pair<typename C::value_type>::value,
int> = 0>
260 constexpr char SPLIT_CH =
',';
261 constexpr char BEGIN_CH =
'[';
262 constexpr char END_CH =
']';
263 if (container.empty()) {
270 for (
const auto &item: container) {
274 ctx.
builder << SPLIT_CH <<
' ';
276 formatter.format(ctx, item);
282template<typename C, std::enable_if_t<is_pair<typename C::value_type>::value,
int> = 0>
283std::string
for_each(
const C &container) {
284 constexpr char SPLIT_CH =
',';
285 constexpr char BEGIN_CH =
'[';
286 constexpr char END_CH =
']';
287 constexpr char PAIR_BEGIN_CH =
'{';
288 constexpr char PAIR_END_CH =
'}';
289 if (container.empty()) {
293 auto key_formatter = overload::Formatter<std::decay_t<typename C::key_type>>();
294 auto value_formatter = overload::Formatter<std::decay_t<typename C::mapped_type>>();
296 ctx.builder << BEGIN_CH;
297 for (
auto &&[key, value]: container) {
301 ctx.builder << SPLIT_CH <<
' ';
303 ctx.builder << PAIR_BEGIN_CH;
304 key_formatter.format(ctx, key);
305 ctx.builder << SPLIT_CH <<
' ';
306 value_formatter.format(ctx, value);
307 ctx.builder << PAIR_END_CH;
309 ctx.builder << END_CH;
310 return ctx.builder.toString();
315 const char *p = pattern;
320 if (*p ==
'{' && *(p - 1) !=
'\\') {
330 std::string parsing_args;
331 auto status = ctx.
parsing(parsing_args);
336 if (!parsing_args.empty()) {
337 if (formatter.parse(parsing_args)) {
338 formatter.
format(ctx, std::forward<T>(arg));
340 ctx.
builder <<
"!{parsing failed}";
344 formatter.format(ctx, std::forward<T>(arg));
349template<
typename T,
typename... ARGS>
351 std::string parsing_args;
352 auto status = ctx.
parsing(parsing_args);
357 if (!parsing_args.empty()) {
358 if (formatter.parse(parsing_args)) {
359 formatter.
format(ctx, std::forward<T>(arg));
361 ctx.
builder <<
"!{parsing failed}";
363 Format(ctx, std::forward<ARGS>(args)...);
365 formatter.format(ctx, std::forward<T>(arg));
366 Format(ctx, std::forward<ARGS>(args)...);
374template<
typename... ARGS, std::enable_if_t<
sizeof...(ARGS) == 0,
int> = 0>
375std::string
fmt(std::string_view pattern, ARGS &&...) {
377 return "!{Mismatch in number of parameters}";
379 return {pattern.begin(), pattern.end()};
387template<
typename... ARGS, std::enable_if_t<
sizeof...(ARGS) != 0,
int> = 0>
388std::string
fmt(std::string_view pattern, ARGS &&...args) {
390 if (param !=
sizeof...(args)) {
391 return "!{Mismatch in number of parameters}";
394 Format(ctx, std::forward<ARGS>(args)...);