39 std::string_view::const_iterator
pos;
41 explicit FmtCtx(std::string_view p);
43 bool parsing(std::string &args);
68 if (opt.
wide <= len) {
72 auto diff = opt.
wide - len;
76 builder << std::string(diff, opt.
wide_char);
79 builder << std::string(diff, opt.
wide_char);
83 builder << std::string(diff / 2, opt.
wide_char);
85 builder << std::string((diff % 2 == 1 ? (diff / 2 + 1) : (diff / 2)), opt.
wide_char);
100 }
else if (radix ==
'x') {
102 }
else if (radix ==
'o') {
104 }
else if (radix ==
'b') {
130 if (opt.
wide <= len) {
137 auto diff = opt.
wide - len;
144 builder << std::string(diff, opt.
wide_char);
147 builder << std::string(diff, opt.
wide_char);
154 builder << std::string(diff / 2, opt.
wide_char);
159 builder << std::string((diff % 2 == 1 ? (diff / 2 + 1) : (diff / 2)), opt.
wide_char);
165 template<
typename VALUE,
typename ENABLE =
void>
167 bool parse(
const std::string &) {
return false; }
185 bool parse(
const std::string &opt_str) {
194 template<
typename VALUE>
195 struct Formatter<VALUE, std::enable_if_t<std::is_integral_v<VALUE>>> {
198 bool parse(
const std::string &opt_str) {
207 template<
typename VALUE>
208 struct Formatter<VALUE, std::enable_if_t<std::is_floating_point_v<VALUE>>> {
211 bool parse(
const std::string &opt_str) {
216 if (std::isnan(value)) {
224 template<
typename VALUE>
225 struct Formatter<VALUE, std::enable_if_t<is_iterable_v<VALUE>>> {
230 bool parse(
const std::string &args) {
231 if (args.size() == 3) {
244 for (
auto &&item: value) {
251 formatter.format(ctx, item);
259template<typename C, std::enable_if_t<!is_pair<typename C::value_type>::value,
int> = 0>
261 constexpr char SPLIT_CH =
',';
262 constexpr char BEGIN_CH =
'[';
263 constexpr char END_CH =
']';
264 if (container.empty()) {
271 for (
const auto &item: container) {
275 ctx.
builder << SPLIT_CH <<
' ';
277 formatter.format(ctx, item);
283template<typename C, std::enable_if_t<is_pair<typename C::value_type>::value,
int> = 0>
284std::string
for_each(
const C &container) {
285 constexpr char SPLIT_CH =
',';
286 constexpr char BEGIN_CH =
'[';
287 constexpr char END_CH =
']';
288 constexpr char PAIR_BEGIN_CH =
'{';
289 constexpr char PAIR_END_CH =
'}';
290 if (container.empty()) {
294 auto key_formatter = overload::Formatter<std::decay_t<typename C::key_type>>();
295 auto value_formatter = overload::Formatter<std::decay_t<typename C::mapped_type>>();
297 ctx.builder << BEGIN_CH;
298 for (
auto &&[key, value]: container) {
302 ctx.builder << SPLIT_CH <<
' ';
304 ctx.builder << PAIR_BEGIN_CH;
305 key_formatter.format(ctx, key);
306 ctx.builder << SPLIT_CH <<
' ';
307 value_formatter.format(ctx, value);
308 ctx.builder << PAIR_END_CH;
310 ctx.builder << END_CH;
311 return ctx.builder.toString();
316 const char *p = pattern;
321 if (*p ==
'{' && *(p - 1) !=
'\\') {
331 std::string parsing_args;
332 auto status = ctx.
parsing(parsing_args);
337 if (!parsing_args.empty()) {
338 if (formatter.parse(parsing_args)) {
339 formatter.
format(ctx, std::forward<T>(arg));
341 ctx.
builder <<
"!{parsing failed}";
345 formatter.format(ctx, std::forward<T>(arg));
350template<
typename T,
typename... ARGS>
352 std::string parsing_args;
353 auto status = ctx.
parsing(parsing_args);
358 if (!parsing_args.empty()) {
359 if (formatter.parse(parsing_args)) {
360 formatter.
format(ctx, std::forward<T>(arg));
362 ctx.
builder <<
"!{parsing failed}";
364 Format(ctx, std::forward<ARGS>(args)...);
366 formatter.format(ctx, std::forward<T>(arg));
367 Format(ctx, std::forward<ARGS>(args)...);
375template<
typename... ARGS, std::enable_if_t<
sizeof...(ARGS) == 0,
int> = 0>
376std::string
fmt(std::string_view pattern, ARGS &&...) {
378 return "!{Mismatch in number of parameters}";
380 return {pattern.begin(), pattern.end()};
388template<
typename... ARGS, std::enable_if_t<
sizeof...(ARGS) != 0,
int> = 0>
389std::string
fmt(std::string_view pattern, ARGS &&...args) {
391 if (param !=
sizeof...(args)) {
392 return "!{Mismatch in number of parameters}";
395 Format(ctx, std::forward<ARGS>(args)...);