48 it.
count_ +=
static_cast<size_t>(n);
55template <
typename Char,
typename InputIt>
58 return it + (end - begin);
87template <
typename OutputIt,
92template <
typename OutputIt>
106 if (this->count_++ < this->limit_) ++this->out_;
117 return this->count_ < this->limit_ ? *this->out_ : blackhole_;
121template <
typename OutputIt>
131 if (this->count_++ < this->limit_) *this->out_++ = val;
159#ifdef __cpp_if_constexpr
160# define FMT_COMPILE(s) \
161 FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)
163# define FMT_COMPILE(s) FMT_STRING(s)
166#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
167template <
typename Char,
size_t N,
168 fmt::detail_exported::fixed_string<Char, N> Str>
169struct udl_compiled_string : compiled_string {
172 return {Str.
data, N - 1};
177template <
typename T,
typename... Tail>
182#ifdef __cpp_if_constexpr
183template <
typename... Args>
struct type_list {};
186template <
int N,
typename T,
typename... Args>
187constexpr const auto&
get([[maybe_unused]]
const T&
first,
188 [[maybe_unused]]
const Args&... rest) {
189 static_assert(N < 1 +
sizeof...(Args),
"index is out of bounds");
190 if constexpr (N == 0)
193 return get<N - 1>(rest...);
196template <
typename Char,
typename... Args>
198 type_list<Args...>) {
202template <
int N,
typename>
struct get_type_impl;
204template <
int N,
typename... Args>
struct get_type_impl<N, type_list<Args...>> {
208template <
int N,
typename T>
209using get_type =
typename get_type_impl<N, T>::type;
213template <
typename Char>
struct text {
217 template <
typename OutputIt,
typename... Args>
218 constexpr OutputIt
format(OutputIt out,
const Args&...)
const {
219 return write<Char>(out,
data);
223template <
typename Char>
226template <
typename Char>
229 return {{&s[pos],
size}};
232template <
typename Char>
struct code_unit {
236 template <
typename OutputIt,
typename... Args>
237 constexpr OutputIt
format(OutputIt out,
const Args&...)
const {
238 return write<Char>(out,
value);
243template <
typename T,
int N,
typename... Args>
244constexpr const T& get_arg_checked(
const Args&... args) {
245 const auto&
arg = get<N>(args...);
253template <
typename Char>
257template <
typename Char,
typename T,
int N>
struct field {
260 template <
typename OutputIt,
typename... Args>
261 constexpr OutputIt
format(OutputIt out,
const Args&... args)
const {
262 return write<Char>(out, get_arg_checked<T, N>(args...));
266template <
typename Char,
typename T,
int N>
270template <
typename Char>
struct runtime_named_field {
274 template <
typename OutputIt,
typename T>
275 constexpr static bool try_format_argument(
280 if (arg_name ==
arg.name) {
281 out = write<Char>(out,
arg.value);
288 template <
typename OutputIt,
typename... Args>
289 constexpr OutputIt
format(OutputIt out,
const Args&... args)
const {
290 bool found = (try_format_argument(out,
name, args) || ...);
292 throw format_error(
"argument with specified name is not found");
298template <
typename Char>
299struct is_compiled_format<runtime_named_field<Char>> :
std::true_type {};
302template <
typename Char,
typename T,
int N>
struct spec_field {
306 template <
typename OutputIt,
typename... Args>
308 const Args&... args)
const {
310 fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...);
312 return fmt.format(get_arg_checked<T, N>(args...), ctx);
316template <
typename Char,
typename T,
int N>
319template <
typename L,
typename R>
struct concat {
324 template <
typename OutputIt,
typename... Args>
325 constexpr OutputIt
format(OutputIt out,
const Args&... args)
const {
326 out = lhs.format(out, args...);
327 return rhs.format(out, args...);
331template <
typename L,
typename R>
334template <
typename L,
typename R>
335constexpr concat<L, R> make_concat(L lhs, R rhs) {
339struct unknown_format {};
341template <
typename Char>
343 for (
size_t size = str.
size(); pos !=
size; ++pos) {
344 if (str[pos] ==
'{' || str[pos] ==
'}')
break;
349template <
typename Args,
size_t POS,
int ID,
typename S>
350constexpr auto compile_format_string(S format_str);
352template <
typename Args,
size_t POS,
int ID,
typename T,
typename S>
353constexpr auto parse_tail(
T head, S format_str) {
356 constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
361 return make_concat(head, tail);
367template <
typename T,
typename Char>
struct parse_specs_result {
373constexpr int manual_indexing_id = -1;
375template <
typename T,
typename Char>
377 size_t pos,
int next_arg_id) {
381 auto end = f.parse(ctx);
382 return {f, pos + fmt::detail::to_unsigned(end - str.
data()) + 1,
383 next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};
386template <
typename Char>
struct arg_id_handler {
389 constexpr int operator()() {
390 FMT_ASSERT(
false,
"handler cannot be used with automatic indexing");
393 constexpr int operator()(
int id) {
402 constexpr void on_error(
const char* message) {
throw format_error(message); }
405template <
typename Char>
struct parse_arg_id_result {
407 const Char* arg_id_end;
410template <
int ID,
typename Char>
411constexpr auto parse_arg_id(
const Char* begin,
const Char* end) {
414 return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};
417template <
typename T,
typename Enable =
void>
struct field_type {
426template <
typename T,
typename Args,
size_t END_POS,
int ARG_INDEX,
int NEXT_ID,
428constexpr auto parse_replacement_field_then_tail(S format_str) {
432 if constexpr (c ==
'}') {
433 return parse_tail<Args, END_POS + 1, NEXT_ID>(
434 field<char_type,
typename field_type<T>::type, ARG_INDEX>(),
436 }
else if constexpr (c ==
':') {
437 constexpr auto result = parse_specs<typename field_type<T>::type>(
438 str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);
439 return parse_tail<Args,
result.end,
result.next_arg_id>(
440 spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
448template <
typename Args,
size_t POS,
int ID,
typename S>
449constexpr auto compile_format_string(S format_str) {
452 if constexpr (str[POS] ==
'{') {
453 if constexpr (POS + 1 == str.
size())
455 if constexpr (str[POS + 1] ==
'{') {
456 return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
457 }
else if constexpr (str[POS + 1] ==
'}' || str[POS + 1] ==
':') {
458 static_assert(ID != manual_indexing_id,
459 "cannot switch from manual to automatic argument indexing");
460 constexpr auto next_id =
461 ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
462 return parse_replacement_field_then_tail<get_type<ID, Args>, Args,
463 POS + 1, ID, next_id>(
466 constexpr auto arg_id_result =
467 parse_arg_id<ID>(str.
data() + POS + 1, str.
data() + str.
size());
468 constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.
data();
470 arg_id_end_pos != str.
size() ? str[arg_id_end_pos] :
char_type();
471 static_assert(c ==
'}' || c ==
':',
"missing '}' in format string");
474 ID == manual_indexing_id || ID == 0,
475 "cannot switch from automatic to manual argument indexing");
476 constexpr auto arg_index = arg_id_result.arg_id.val.index;
477 return parse_replacement_field_then_tail<get_type<arg_index, Args>,
478 Args, arg_id_end_pos,
479 arg_index, manual_indexing_id>(
482 constexpr auto arg_index =
485 constexpr auto next_id =
486 ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
487 return parse_replacement_field_then_tail<
488 decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,
489 arg_index, next_id>(format_str);
491 if constexpr (c ==
'}') {
492 return parse_tail<Args, arg_id_end_pos + 1, ID>(
493 runtime_named_field<char_type>{arg_id_result.arg_id.val.name},
495 }
else if constexpr (c ==
':') {
496 return unknown_format();
501 }
else if constexpr (str[POS] ==
'}') {
502 if constexpr (POS + 1 == str.
size())
504 return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
506 constexpr auto end = parse_text(str, POS + 1);
507 if constexpr (
end - POS > 1) {
508 return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
511 return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
517template <
typename... Args,
typename S,
519constexpr auto compile(S format_str) {
521 if constexpr (str.
size() == 0) {
522 return detail::make_text(str, 0, 0);
525 detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
535#ifdef __cpp_if_constexpr
537template <
typename CompiledFormat,
typename... Args,
538 typename Char =
typename CompiledFormat::char_type,
539 FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
541 const Args&... args) {
547template <
typename OutputIt,
typename CompiledFormat,
typename... Args,
548 FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
550 const Args&... args) {
551 return cf.format(out, args...);
554template <
typename S,
typename... Args,
560 if constexpr (str.
size() == 2 && str[0] ==
'{' && str[1] ==
'}') {
562 if constexpr (detail::is_named_arg<
564 return fmt::to_string(
first.value);
566 return fmt::to_string(first);
570 constexpr auto compiled = detail::compile<Args...>(S());
572 detail::unknown_format>()) {
580template <
typename OutputIt,
typename S,
typename... Args,
583 constexpr auto compiled = detail::compile<Args...>(S());
585 detail::unknown_format>()) {
595template <
typename OutputIt,
typename S,
typename... Args,
598 const S& format_str, Args&&... args) {
601 return {it.base(), it.count()};
604template <
typename S,
typename... Args,
610template <
typename S,
typename... Args,
618template <
typename S,
typename... Args,
620void print(
const S& format_str,
const Args&... args) {
621 print(stdout, format_str, args...);
624#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
626template <detail_exported::fixed_
string Str>
627constexpr detail::udl_compiled_string<
629 sizeof(Str.data) /
sizeof(
decltype(Str.data[0])), Str>
T back_inserter(T... args)
void print(std::FILE *f, const S &format_str, const Args &... args)
FMT_MODULE_EXPORT_BEGIN format_to_n_result< OutputIt > format_to_n(OutputIt out, size_t n, const S &format_str, Args &&... args)
size_t formatted_size(const S &format_str, const Args &... args)
FMT_CONSTEXPR void remove_prefix(size_t n)
constexpr auto data() const -> const Char *
constexpr auto size() const -> size_t
auto size() const FMT_NOEXCEPT -> size_t
auto data() FMT_NOEXCEPT -> T *
counting_iterator operator++(int)
counting_iterator & operator++()
value_type operator*() const
friend counting_iterator operator+(counting_iterator it, difference_type n)
truncating_iterator operator++(int)
truncating_iterator(OutputIt out, size_t limit)
truncating_iterator_base< OutputIt >::value_type blackhole_
typename truncating_iterator_base< OutputIt >::value_type value_type
truncating_iterator & operator++()
value_type & operator*() const
truncating_iterator()=default
truncating_iterator & operator++(int)
truncating_iterator & operator=(T val)
truncating_iterator & operator*()
truncating_iterator()=default
truncating_iterator(OutputIt out, size_t limit)
truncating_iterator & operator++()
truncating_iterator_base()
truncating_iterator_base(OutputIt out, size_t limit)
typename std::iterator_traits< OutputIt >::value_type value_type
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
#define FMT_ASSERT(condition, message)
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
#define FMT_MODULE_EXPORT_BEGIN
#define FMT_BEGIN_NAMESPACE
#define FMT_ENABLE_IF(...)
FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char *begin, const Char *end, IDHandler &&handler) -> const Char *
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
constexpr int invalid_arg_index
#define FMT_END_NAMESPACE
#define FMT_MODULE_EXPORT_END
FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view< Char > name) -> int
FMT_FUNC void print(std::FILE *f, string_view text)
const T & first(const T &value, const Tail &...)
counting_iterator copy_str(InputIt begin, InputIt end, counting_iterator it)
SPDLOG_INLINE std::shared_ptr< logger > get(const std::string &name)
void operator=(const T &)