|
Loading...
Searching...
No Matches
Go to the documentation of this file.
37#define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
39template < typename T, typename... Tail>
102 unsigned brace_counter = 0;
103 for (; begin != end; ++begin) {
106 } else if (*begin == '}') {
107 if (brace_counter == 0u) break;
118template < typename Char>
121 parse_format_string<true>(format_str, counter);
125template < typename Char, typename PartHandler>
174 if (*it != '}') on_error( "missing '}' in format string");
186template < bool IS_CONSTEXPR, typename Char, typename PartHandler>
188 PartHandler handler) {
189 parse_format_string<IS_CONSTEXPR>(
194template < typename OutputIt, typename Context, typename Id>
197 Context& ctx, Id arg_id) {
205template < typename Context, typename OutputIt, typename CompiledFormat>
208 using char_type = typename Context::char_type;
211 Context ctx(out, args);
213 const auto& parts = cf.parts();
214 for ( auto part_it = std::begin(parts); part_it != std::end(parts);
216 const auto& part = *part_it;
217 const auto& value = part.val;
220 switch (part.part_kind) {
221 case format_part_t::kind::text: {
222 const auto text = value.str;
223 auto output = ctx.out();
224 auto&& it = reserve(output, text.size());
225 it = std::copy_n(text.begin(), text.size(), it);
226 ctx.advance_to(output);
230 case format_part_t::kind::arg_index:
232 detail::format_arg<OutputIt>(parse_ctx, ctx, value.arg_index);
235 case format_part_t::kind::arg_name:
237 detail::format_arg<OutputIt>(parse_ctx, ctx, value.str);
240 case format_part_t::kind::replacement: {
241 const auto& arg_id_value = value.repl.arg_id.val;
243 ? ctx.arg(arg_id_value.index)
244 : ctx.arg(arg_id_value.name);
246 auto specs = value.repl.specs;
248 handle_dynamic_spec<width_checker>(specs.width, specs.width_ref, ctx);
249 handle_dynamic_spec<precision_checker>(specs.precision,
250 specs.precision_ref, ctx);
262 ctx, nullptr, &specs),
274template < typename S, typename = void>
282 compile_format_string<false>(format_str,
296template < typename Char, unsigned N>
300 unsigned counter = 0;
306 parts[(*counter)++] = part;
308 } collector{parts. data, &counter};
309 compile_format_string<true>(format_str, collector);
311 parts. data[counter] =
317template < typename T> constexpr const T& constexpr_max( const T& a, const T& b) {
318 return (a < b) ? b : a;
334 static const unsigned num_format_parts = 1;
341 compile_to_parts<char_type, num_format_parts>(
342 detail::to_string_view(S()));
347template < typename S, typename... Args>
355 template < typename Context, typename OutputIt, typename CompiledFormat>
358 typename Context::iterator;
366#ifdef __cpp_if_constexpr
367template < typename... Args> struct type_list {};
370template < int N, typename T, typename... Args>
371constexpr const auto& get([[maybe_unused]] const T& first,
372 [[maybe_unused]] const Args&... rest) {
373 static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
374 if constexpr (N == 0)
377 return get<N - 1>(rest...);
380template < int N, typename> struct get_type_impl;
382template < int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {
386template < int N, typename T>
387using get_type = typename get_type_impl<N, T>::type;
389template < typename T> struct is_compiled_format : std::false_type {};
391template < typename Char> struct text {
395 template < typename OutputIt, typename... Args>
396 OutputIt format(OutputIt out, const Args&...) const {
397 return write<Char>(out, data);
401template < typename Char>
402struct is_compiled_format<text<Char>> : std::true_type {};
404template < typename Char>
407 return {{&s[pos], size}};
410template < typename Char> struct code_unit {
414 template < typename OutputIt, typename... Args>
415 OutputIt format(OutputIt out, const Args&...) const {
416 return write<Char>(out, value);
420template < typename Char>
421struct is_compiled_format<code_unit<Char>> : std::true_type {};
424template < typename Char, typename T, int N> struct field {
427 template < typename OutputIt, typename... Args>
428 OutputIt format(OutputIt out, const Args&... args) const {
430 const T& arg = get<N>(args...);
431 return write<Char>(out, arg);
435template < typename Char, typename T, int N>
436struct is_compiled_format<field<Char, T, N>> : std::true_type {};
439template < typename Char, typename T, int N> struct spec_field {
443 template < typename OutputIt, typename... Args>
444 OutputIt format(OutputIt out, const Args&... args) const {
446 const T& arg = get<N>(args...);
448 make_format_args<basic_format_context<OutputIt, Char>>(args...);
450 return fmt.format( arg, ctx);
454template < typename Char, typename T, int N>
455struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};
457template < typename L, typename R> struct concat {
462 template < typename OutputIt, typename... Args>
463 OutputIt format(OutputIt out, const Args&... args) const {
464 out = lhs.format(out, args...);
465 return rhs.format(out, args...);
469template < typename L, typename R>
470struct is_compiled_format<concat<L, R>> : std::true_type {};
472template < typename L, typename R>
473constexpr concat<L, R> make_concat(L lhs, R rhs) {
477struct unknown_format {};
479template < typename Char>
481 for ( size_t size = str. size(); pos != size; ++pos) {
482 if (str[pos] == '{' || str[pos] == '}') break;
487template < typename Args, size_t POS, int ID, typename S>
490template < typename Args, size_t POS, int ID, typename T, typename S>
491constexpr auto parse_tail(T head, S format_str) {
494 constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
499 return make_concat(head, tail);
505template < typename T, typename Char> struct parse_specs_result {
511template < typename T, typename Char>
513 size_t pos, int arg_id) {
517 auto end = f.parse(ctx);
523template < typename Args, size_t POS, int ID, typename S>
527 if constexpr (str[POS] == '{') {
528 if (POS + 1 == str. size())
530 if constexpr (str[POS + 1] == '{') {
531 return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
532 } else if constexpr (str[POS + 1] == '}') {
533 using type = get_type<ID, Args>;
534 return parse_tail<Args, POS + 2, ID + 1>(field<char_type, type, ID>(),
536 } else if constexpr (str[POS + 1] == ':') {
537 using type = get_type<ID, Args>;
538 constexpr auto result = parse_specs<type>(str, POS + 2, ID);
539 return parse_tail<Args, result.end, result.next_arg_id>(
540 spec_field<char_type, type, ID>{ result.fmt}, format_str);
542 return unknown_format();
544 } else if constexpr (str[POS] == '}') {
545 if (POS + 1 == str. size())
547 return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
549 constexpr auto end = parse_text(str, POS + 1);
550 if constexpr (end - POS > 1) {
551 return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
554 return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
560template < typename... Args, typename S,
563constexpr auto compile(S format_str) {
565 if constexpr (str. size() == 0) {
566 return detail::make_text(str, 0, 0);
572 detail::unknown_format>()) {
580template < typename... Args, typename S,
588template < typename... Args, typename Char, size_t N>
597template < typename... Args>
604# ifdef __cpp_if_constexpr
606template < typename CompiledFormat, typename... Args,
607 typename Char = typename CompiledFormat::char_type,
608 FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
610 const Args&... args) {
616template < typename OutputIt, typename CompiledFormat, typename... Args,
617 FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
618OutputIt format_to(OutputIt out, const CompiledFormat& cf,
619 const Args&... args) {
620 return cf.format(out, args...);
625template < typename CompiledFormat, typename... Args,
626 typename Char = typename CompiledFormat::char_type,
628 CompiledFormat>::value)>
629std::basic_string<Char> format( const CompiledFormat& cf, const Args&... args) {
633 make_format_args<context>(args...));
637template < typename S, typename... Args,
641#ifdef __cpp_if_constexpr
642 if constexpr (std::is_same<typename S::char_type, char>::value) {
644 if (str. size() == 2 && str[0] == '{' && str[1] == '}')
649 return format(compiled, std::forward<Args>(args)...);
652template < typename OutputIt, typename CompiledFormat, typename... Args,
654 CompiledFormat>::value)>
655OutputIt format_to(OutputIt out, const CompiledFormat& cf,
656 const Args&... args) {
657 using char_type = typename CompiledFormat::char_type;
659 return detail::cf::vformat_to<context>(out, cf,
660 make_format_args<context>(args...));
663template < typename OutputIt, typename S, typename... Args,
665OutputIt format_to(OutputIt out, const S&, const Args&... args) {
667 return format_to(out, compiled, args...);
670template < typename OutputIt, typename CompiledFormat, typename... Args>
672 const Args&... args) ->
673 typename std::enable_if<
675 typename CompiledFormat::char_type>::value &&
677 CompiledFormat>::value,
681 return {it.base(), it.count()};
684template < typename OutputIt, typename S, typename... Args,
687 const Args&... args) {
691 return {it.base(), it.count()};
694template < typename CompiledFormat, typename... Args>
FMT_CONSTEXPR int next_arg_id()
FMT_CONSTEXPR void remove_prefix(size_t n)
constexpr size_t size() const
constexpr const Char * data() const
FMT_CONSTEXPR void require_numeric_argument()
FMT_CONSTEXPR void check_sign()
FMT_CONSTEXPR void check_precision()
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
auto format_to_n(OutputIt out, size_t n, const CompiledFormat &cf, const Args &... args) -> typename std::enable_if< detail::is_output_iterator< OutputIt, typename CompiledFormat::char_type >::value &&std::is_base_of< detail::basic_compiled_format, CompiledFormat >::value, format_to_n_result< OutputIt > >::type
std::basic_string< Char > format(const CompiledFormat &cf, const Args &... args)
size_t formatted_size(const CompiledFormat &cf, const Args &... args)
OutputIt format_to(OutputIt out, const CompiledFormat &cf, const Args &... args)
FMT_DEPRECATED auto compile(const Args &... args) -> decltype(detail::compile(args...))
typename std::enable_if< B, T >::type enable_if_t
typename detail::char_t_impl< S >::type char_t
detail::named_arg< Char, T > arg(const Char *name, const T &arg)
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
#define FMT_BEGIN_NAMESPACE
#define FMT_ENABLE_IF(...)
FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
#define FMT_END_NAMESPACE
#define FMT_CONSTEXPR_DECL
auto vformat_to(OutputIt out, CompiledFormat &cf, basic_format_args< Context > args) -> typename Context::iterator
checked_ptr< typename Container::value_type > reserve(std::back_insert_iterator< Container > it, size_t n)
FMT_CONSTEXPR format_part_array< Char, N > compile_to_parts(basic_string_view< Char > format_str)
FMT_CONSTEXPR const Char * parse_format_specs(const Char *begin, const Char *end, SpecHandler &&handler)
const T & first(const T &value, const Tail &...)
FMT_CONSTEXPR std::make_unsigned< Int >::type to_unsigned(Int value)
FMT_CONSTEXPR void compile_format_string(basic_string_view< Char > format_str, PartHandler handler)
void format_arg(basic_format_parse_context< typename Context::char_type > &parse_ctx, Context &ctx, Id arg_id)
constexpr const T & constexpr_max(const T &a, const T &b)
constexpr auto compile(S format_str) -> detail::compiled_format< S, Args... >
FMT_CONSTEXPR unsigned count_parts(basic_string_view< Char > format_str)
FMT_NORETURN FMT_API void on_error(const char *message)
FMT_CONSTEXPR void on_text(const Char *begin, const Char *end)
FMT_CONSTEXPR void on_replacement_field(int, const Char *)
FMT_CONSTEXPR int on_arg_id()
FMT_CONSTEXPR void on_error(const char *)
FMT_CONSTEXPR int on_arg_id(basic_string_view< Char >)
FMT_CONSTEXPR int on_arg_id(int)
FMT_CONSTEXPR const Char * on_format_specs(int, const Char *begin, const Char *end)
|