diff options
Diffstat (limited to 'matching/include/spdlog/fmt/bundled/printf.h')
-rw-r--r-- | matching/include/spdlog/fmt/bundled/printf.h | 855 |
1 files changed, 0 insertions, 855 deletions
diff --git a/matching/include/spdlog/fmt/bundled/printf.h b/matching/include/spdlog/fmt/bundled/printf.h deleted file mode 100644 index 6f2715d..0000000 --- a/matching/include/spdlog/fmt/bundled/printf.h +++ /dev/null @@ -1,855 +0,0 @@ -// Formatting library for C++ -// -// Copyright (c) 2012 - 2016, Victor Zverovich -// All rights reserved. -// -// For the license information refer to format.h. - -#ifndef FMT_PRINTF_H_ -#define FMT_PRINTF_H_ - -#include <algorithm> // std::fill_n -#include <limits> // std::numeric_limits - -#include "ostream.h" - -FMT_BEGIN_NAMESPACE -namespace internal { - -// An iterator that produces a null terminator on *end. This simplifies parsing -// and allows comparing the performance of processing a null-terminated string -// vs string_view. -template <typename Char> -class null_terminating_iterator { - public: - typedef std::ptrdiff_t difference_type; - typedef Char value_type; - typedef const Char* pointer; - typedef const Char& reference; - typedef std::random_access_iterator_tag iterator_category; - - null_terminating_iterator() : ptr_(0), end_(0) {} - - FMT_CONSTEXPR null_terminating_iterator(const Char *ptr, const Char *end) - : ptr_(ptr), end_(end) {} - - template <typename Range> - FMT_CONSTEXPR explicit null_terminating_iterator(const Range &r) - : ptr_(r.begin()), end_(r.end()) {} - - FMT_CONSTEXPR null_terminating_iterator &operator=(const Char *ptr) { - assert(ptr <= end_); - ptr_ = ptr; - return *this; - } - - FMT_CONSTEXPR Char operator*() const { - return ptr_ != end_ ? *ptr_ : Char(); - } - - FMT_CONSTEXPR null_terminating_iterator operator++() { - ++ptr_; - return *this; - } - - FMT_CONSTEXPR null_terminating_iterator operator++(int) { - null_terminating_iterator result(*this); - ++ptr_; - return result; - } - - FMT_CONSTEXPR null_terminating_iterator operator--() { - --ptr_; - return *this; - } - - FMT_CONSTEXPR null_terminating_iterator operator+(difference_type n) { - return null_terminating_iterator(ptr_ + n, end_); - } - - FMT_CONSTEXPR null_terminating_iterator operator-(difference_type n) { - return null_terminating_iterator(ptr_ - n, end_); - } - - FMT_CONSTEXPR null_terminating_iterator operator+=(difference_type n) { - ptr_ += n; - return *this; - } - - FMT_CONSTEXPR difference_type operator-( - null_terminating_iterator other) const { - return ptr_ - other.ptr_; - } - - FMT_CONSTEXPR bool operator!=(null_terminating_iterator other) const { - return ptr_ != other.ptr_; - } - - bool operator>=(null_terminating_iterator other) const { - return ptr_ >= other.ptr_; - } - - // This should be a friend specialization pointer_from<Char> but the latter - // doesn't compile by gcc 5.1 due to a compiler bug. - template <typename CharT> - friend FMT_CONSTEXPR_DECL const CharT *pointer_from( - null_terminating_iterator<CharT> it); - - private: - const Char *ptr_; - const Char *end_; -}; - -template <typename T> -FMT_CONSTEXPR const T *pointer_from(const T *p) { return p; } - -template <typename Char> -FMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it) { - return it.ptr_; -} - -// DEPRECATED: Parses the input as an unsigned integer. This function assumes -// that the first character is a digit and presence of a non-digit character at -// the end. -// it: an iterator pointing to the beginning of the input range. -template <typename Iterator, typename ErrorHandler> -FMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) { - assert('0' <= *it && *it <= '9'); - if (*it == '0') { - ++it; - return 0; - } - unsigned value = 0; - // Convert to unsigned to prevent a warning. - unsigned max_int = (std::numeric_limits<int>::max)(); - unsigned big = max_int / 10; - do { - // Check for overflow. - if (value > big) { - value = max_int + 1; - break; - } - value = value * 10 + unsigned(*it - '0'); - // Workaround for MSVC "setup_exception stack overflow" error: - auto next = it; - ++next; - it = next; - } while ('0' <= *it && *it <= '9'); - if (value > max_int) - eh.on_error("number is too big"); - return value; -} - -// Checks if a value fits in int - used to avoid warnings about comparing -// signed and unsigned integers. -template <bool IsSigned> -struct int_checker { - template <typename T> - static bool fits_in_int(T value) { - unsigned max = std::numeric_limits<int>::max(); - return value <= max; - } - static bool fits_in_int(bool) { return true; } -}; - -template <> -struct int_checker<true> { - template <typename T> - static bool fits_in_int(T value) { - return value >= std::numeric_limits<int>::min() && - value <= std::numeric_limits<int>::max(); - } - static bool fits_in_int(int) { return true; } -}; - -class printf_precision_handler: public function<int> { - public: - template <typename T> - typename std::enable_if<std::is_integral<T>::value, int>::type - operator()(T value) { - if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) - FMT_THROW(format_error("number is too big")); - return static_cast<int>(value); - } - - template <typename T> - typename std::enable_if<!std::is_integral<T>::value, int>::type operator()(T) { - FMT_THROW(format_error("precision is not integer")); - return 0; - } -}; - -// An argument visitor that returns true iff arg is a zero integer. -class is_zero_int: public function<bool> { - public: - template <typename T> - typename std::enable_if<std::is_integral<T>::value, bool>::type - operator()(T value) { return value == 0; } - - template <typename T> - typename std::enable_if<!std::is_integral<T>::value, bool>::type - operator()(T) { return false; } -}; - -template <typename T> -struct make_unsigned_or_bool : std::make_unsigned<T> {}; - -template <> -struct make_unsigned_or_bool<bool> { - typedef bool type; -}; - -template <typename T, typename Context> -class arg_converter: public function<void> { - private: - typedef typename Context::char_type Char; - - basic_format_arg<Context> &arg_; - typename Context::char_type type_; - - public: - arg_converter(basic_format_arg<Context> &arg, Char type) - : arg_(arg), type_(type) {} - - void operator()(bool value) { - if (type_ != 's') - operator()<bool>(value); - } - - template <typename U> - typename std::enable_if<std::is_integral<U>::value>::type - operator()(U value) { - bool is_signed = type_ == 'd' || type_ == 'i'; - typedef typename std::conditional< - std::is_same<T, void>::value, U, T>::type TargetType; - if (const_check(sizeof(TargetType) <= sizeof(int))) { - // Extra casts are used to silence warnings. - if (is_signed) { - arg_ = internal::make_arg<Context>( - static_cast<int>(static_cast<TargetType>(value))); - } else { - typedef typename make_unsigned_or_bool<TargetType>::type Unsigned; - arg_ = internal::make_arg<Context>( - static_cast<unsigned>(static_cast<Unsigned>(value))); - } - } else { - if (is_signed) { - // glibc's printf doesn't sign extend arguments of smaller types: - // std::printf("%lld", -42); // prints "4294967254" - // but we don't have to do the same because it's a UB. - arg_ = internal::make_arg<Context>(static_cast<long long>(value)); - } else { - arg_ = internal::make_arg<Context>( - static_cast<typename make_unsigned_or_bool<U>::type>(value)); - } - } - } - - template <typename U> - typename std::enable_if<!std::is_integral<U>::value>::type operator()(U) { - // No coversion needed for non-integral types. - } -}; - -// Converts an integer argument to T for printf, if T is an integral type. -// If T is void, the argument is converted to corresponding signed or unsigned -// type depending on the type specifier: 'd' and 'i' - signed, other - -// unsigned). -template <typename T, typename Context, typename Char> -void convert_arg(basic_format_arg<Context> &arg, Char type) { - visit_format_arg(arg_converter<T, Context>(arg, type), arg); -} - -// Converts an integer argument to char for printf. -template <typename Context> -class char_converter: public function<void> { - private: - basic_format_arg<Context> &arg_; - - public: - explicit char_converter(basic_format_arg<Context> &arg) : arg_(arg) {} - - template <typename T> - typename std::enable_if<std::is_integral<T>::value>::type - operator()(T value) { - typedef typename Context::char_type Char; - arg_ = internal::make_arg<Context>(static_cast<Char>(value)); - } - - template <typename T> - typename std::enable_if<!std::is_integral<T>::value>::type operator()(T) { - // No coversion needed for non-integral types. - } -}; - -// Checks if an argument is a valid printf width specifier and sets -// left alignment if it is negative. -template <typename Char> -class printf_width_handler: public function<unsigned> { - private: - typedef basic_format_specs<Char> format_specs; - - format_specs &spec_; - - public: - explicit printf_width_handler(format_specs &spec) : spec_(spec) {} - - template <typename T> - typename std::enable_if<std::is_integral<T>::value, unsigned>::type - operator()(T value) { - typedef typename internal::int_traits<T>::main_type UnsignedType; - UnsignedType width = static_cast<UnsignedType>(value); - if (internal::is_negative(value)) { - spec_.align_ = ALIGN_LEFT; - width = 0 - width; - } - unsigned int_max = std::numeric_limits<int>::max(); - if (width > int_max) - FMT_THROW(format_error("number is too big")); - return static_cast<unsigned>(width); - } - - template <typename T> - typename std::enable_if<!std::is_integral<T>::value, unsigned>::type - operator()(T) { - FMT_THROW(format_error("width is not integer")); - return 0; - } -}; - -template <typename Char, typename Context> -void printf(basic_buffer<Char> &buf, basic_string_view<Char> format, - basic_format_args<Context> args) { - Context(std::back_inserter(buf), format, args).format(); -} -} // namespace internal - -using internal::printf; // For printing into memory_buffer. - -template <typename Range> -class printf_arg_formatter; - -template < - typename OutputIt, typename Char, - typename ArgFormatter = - printf_arg_formatter<back_insert_range<internal::basic_buffer<Char>>>> -class basic_printf_context; - -/** - \rst - The ``printf`` argument formatter. - \endrst - */ -template <typename Range> -class printf_arg_formatter: - public internal::function< - typename internal::arg_formatter_base<Range>::iterator>, - public internal::arg_formatter_base<Range> { - private: - typedef typename Range::value_type char_type; - typedef decltype(internal::declval<Range>().begin()) iterator; - typedef internal::arg_formatter_base<Range> base; - typedef basic_printf_context<iterator, char_type> context_type; - - context_type &context_; - - void write_null_pointer(char) { - this->spec()->type = 0; - this->write("(nil)"); - } - - void write_null_pointer(wchar_t) { - this->spec()->type = 0; - this->write(L"(nil)"); - } - - public: - typedef typename base::format_specs format_specs; - - /** - \rst - Constructs an argument formatter object. - *buffer* is a reference to the output buffer and *spec* contains format - specifier information for standard argument types. - \endrst - */ - printf_arg_formatter(internal::basic_buffer<char_type> &buffer, - format_specs &spec, context_type &ctx) - : base(back_insert_range<internal::basic_buffer<char_type>>(buffer), &spec, - ctx.locale()), - context_(ctx) {} - - template <typename T> - typename std::enable_if<std::is_integral<T>::value, iterator>::type - operator()(T value) { - // MSVC2013 fails to compile separate overloads for bool and char_type so - // use std::is_same instead. - if (std::is_same<T, bool>::value) { - format_specs &fmt_spec = *this->spec(); - if (fmt_spec.type != 's') - return base::operator()(value ? 1 : 0); - fmt_spec.type = 0; - this->write(value != 0); - } else if (std::is_same<T, char_type>::value) { - format_specs &fmt_spec = *this->spec(); - if (fmt_spec.type && fmt_spec.type != 'c') - return (*this)(static_cast<int>(value)); - fmt_spec.flags = 0; - fmt_spec.align_ = ALIGN_RIGHT; - return base::operator()(value); - } else { - return base::operator()(value); - } - return this->out(); - } - - template <typename T> - typename std::enable_if<std::is_floating_point<T>::value, iterator>::type - operator()(T value) { - return base::operator()(value); - } - - /** Formats a null-terminated C string. */ - iterator operator()(const char *value) { - if (value) - base::operator()(value); - else if (this->spec()->type == 'p') - write_null_pointer(char_type()); - else - this->write("(null)"); - return this->out(); - } - - /** Formats a null-terminated wide C string. */ - iterator operator()(const wchar_t *value) { - if (value) - base::operator()(value); - else if (this->spec()->type == 'p') - write_null_pointer(char_type()); - else - this->write(L"(null)"); - return this->out(); - } - - iterator operator()(basic_string_view<char_type> value) { - return base::operator()(value); - } - - iterator operator()(monostate value) { - return base::operator()(value); - } - - /** Formats a pointer. */ - iterator operator()(const void *value) { - if (value) - return base::operator()(value); - this->spec()->type = 0; - write_null_pointer(char_type()); - return this->out(); - } - - /** Formats an argument of a custom (user-defined) type. */ - iterator operator()(typename basic_format_arg<context_type>::handle handle) { - handle.format(context_); - return this->out(); - } -}; - -template <typename T> -struct printf_formatter { - template <typename ParseContext> - auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { return ctx.begin(); } - - template <typename FormatContext> - auto format(const T &value, FormatContext &ctx) -> decltype(ctx.out()) { - internal::format_value(internal::get_container(ctx.out()), value); - return ctx.out(); - } -}; - -/** This template formats data and writes the output to a writer. */ -template <typename OutputIt, typename Char, typename ArgFormatter> -class basic_printf_context : - // Inherit publicly as a workaround for the icc bug - // https://software.intel.com/en-us/forums/intel-c-compiler/topic/783476. - public internal::context_base< - OutputIt, basic_printf_context<OutputIt, Char, ArgFormatter>, Char> { - public: - /** The character type for the output. */ - typedef Char char_type; - - template <typename T> - struct formatter_type { typedef printf_formatter<T> type; }; - - private: - typedef internal::context_base<OutputIt, basic_printf_context, Char> base; - typedef typename base::format_arg format_arg; - typedef basic_format_specs<char_type> format_specs; - typedef internal::null_terminating_iterator<char_type> iterator; - - void parse_flags(format_specs &spec, iterator &it); - - // Returns the argument with specified index or, if arg_index is equal - // to the maximum unsigned value, the next argument. - format_arg get_arg( - iterator it, - unsigned arg_index = (std::numeric_limits<unsigned>::max)()); - - // Parses argument index, flags and width and returns the argument index. - unsigned parse_header(iterator &it, format_specs &spec); - - public: - /** - \rst - Constructs a ``printf_context`` object. References to the arguments and - the writer are stored in the context object so make sure they have - appropriate lifetimes. - \endrst - */ - basic_printf_context(OutputIt out, basic_string_view<char_type> format_str, - basic_format_args<basic_printf_context> args) - : base(out, format_str, args) {} - - using base::parse_context; - using base::out; - using base::advance_to; - - /** Formats stored arguments and writes the output to the range. */ - void format(); -}; - -template <typename OutputIt, typename Char, typename AF> -void basic_printf_context<OutputIt, Char, AF>::parse_flags( - format_specs &spec, iterator &it) { - for (;;) { - switch (*it++) { - case '-': - spec.align_ = ALIGN_LEFT; - break; - case '+': - spec.flags |= SIGN_FLAG | PLUS_FLAG; - break; - case '0': - spec.fill_ = '0'; - break; - case ' ': - spec.flags |= SIGN_FLAG; - break; - case '#': - spec.flags |= HASH_FLAG; - break; - default: - --it; - return; - } - } -} - -template <typename OutputIt, typename Char, typename AF> -typename basic_printf_context<OutputIt, Char, AF>::format_arg - basic_printf_context<OutputIt, Char, AF>::get_arg( - iterator it, unsigned arg_index) { - (void)it; - if (arg_index == std::numeric_limits<unsigned>::max()) - return this->do_get_arg(this->parse_context().next_arg_id()); - return base::get_arg(arg_index - 1); -} - -template <typename OutputIt, typename Char, typename AF> -unsigned basic_printf_context<OutputIt, Char, AF>::parse_header( - iterator &it, format_specs &spec) { - unsigned arg_index = std::numeric_limits<unsigned>::max(); - char_type c = *it; - if (c >= '0' && c <= '9') { - // Parse an argument index (if followed by '$') or a width possibly - // preceded with '0' flag(s). - internal::error_handler eh; - unsigned value = parse_nonnegative_int(it, eh); - if (*it == '$') { // value is an argument index - ++it; - arg_index = value; - } else { - if (c == '0') - spec.fill_ = '0'; - if (value != 0) { - // Nonzero value means that we parsed width and don't need to - // parse it or flags again, so return now. - spec.width_ = value; - return arg_index; - } - } - } - parse_flags(spec, it); - // Parse width. - if (*it >= '0' && *it <= '9') { - internal::error_handler eh; - spec.width_ = parse_nonnegative_int(it, eh); - } else if (*it == '*') { - ++it; - spec.width_ = visit_format_arg( - internal::printf_width_handler<char_type>(spec), get_arg(it)); - } - return arg_index; -} - -template <typename OutputIt, typename Char, typename AF> -void basic_printf_context<OutputIt, Char, AF>::format() { - auto &buffer = internal::get_container(this->out()); - auto start = iterator(this->parse_context()); - auto it = start; - using internal::pointer_from; - while (*it) { - char_type c = *it++; - if (c != '%') continue; - if (*it == c) { - buffer.append(pointer_from(start), pointer_from(it)); - start = ++it; - continue; - } - buffer.append(pointer_from(start), pointer_from(it) - 1); - - format_specs spec; - spec.align_ = ALIGN_RIGHT; - - // Parse argument index, flags and width. - unsigned arg_index = parse_header(it, spec); - - // Parse precision. - if (*it == '.') { - ++it; - if ('0' <= *it && *it <= '9') { - internal::error_handler eh; - spec.precision = static_cast<int>(parse_nonnegative_int(it, eh)); - } else if (*it == '*') { - ++it; - spec.precision = - visit_format_arg(internal::printf_precision_handler(), get_arg(it)); - } else { - spec.precision = 0; - } - } - - format_arg arg = get_arg(it, arg_index); - if (spec.has(HASH_FLAG) && visit_format_arg(internal::is_zero_int(), arg)) - spec.flags = static_cast<uint_least8_t>(spec.flags & (~internal::to_unsigned<int>(HASH_FLAG))); - if (spec.fill_ == '0') { - if (arg.is_arithmetic()) - spec.align_ = ALIGN_NUMERIC; - else - spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. - } - - // Parse length and convert the argument to the required type. - using internal::convert_arg; - switch (*it++) { - case 'h': - if (*it == 'h') - convert_arg<signed char>(arg, *++it); - else - convert_arg<short>(arg, *it); - break; - case 'l': - if (*it == 'l') - convert_arg<long long>(arg, *++it); - else - convert_arg<long>(arg, *it); - break; - case 'j': - convert_arg<intmax_t>(arg, *it); - break; - case 'z': - convert_arg<std::size_t>(arg, *it); - break; - case 't': - convert_arg<std::ptrdiff_t>(arg, *it); - break; - case 'L': - // printf produces garbage when 'L' is omitted for long double, no - // need to do the same. - break; - default: - --it; - convert_arg<void>(arg, *it); - } - - // Parse type. - if (!*it) - FMT_THROW(format_error("invalid format string")); - spec.type = static_cast<char>(*it++); - if (arg.is_integral()) { - // Normalize type. - switch (spec.type) { - case 'i': case 'u': - spec.type = 'd'; - break; - case 'c': - // TODO: handle wchar_t better? - visit_format_arg( - internal::char_converter<basic_printf_context>(arg), arg); - break; - } - } - - start = it; - - // Format argument. - visit_format_arg(AF(buffer, spec, *this), arg); - } - buffer.append(pointer_from(start), pointer_from(it)); -} - -template <typename Buffer> -struct basic_printf_context_t { - typedef basic_printf_context< - std::back_insert_iterator<Buffer>, typename Buffer::value_type> type; -}; - -typedef basic_printf_context_t<internal::buffer>::type printf_context; -typedef basic_printf_context_t<internal::wbuffer>::type wprintf_context; - -typedef basic_format_args<printf_context> printf_args; -typedef basic_format_args<wprintf_context> wprintf_args; - -/** - \rst - Constructs an `~fmt::format_arg_store` object that contains references to - arguments and can be implicitly converted to `~fmt::printf_args`. - \endrst - */ -template<typename... Args> -inline format_arg_store<printf_context, Args...> - make_printf_args(const Args &... args) { return {args...}; } - -/** - \rst - Constructs an `~fmt::format_arg_store` object that contains references to - arguments and can be implicitly converted to `~fmt::wprintf_args`. - \endrst - */ -template<typename... Args> -inline format_arg_store<wprintf_context, Args...> - make_wprintf_args(const Args &... args) { return {args...}; } - -template <typename S, typename Char = FMT_CHAR(S)> -inline std::basic_string<Char> -vsprintf(const S &format, - basic_format_args<typename basic_printf_context_t< - internal::basic_buffer<Char>>::type> args) { - basic_memory_buffer<Char> buffer; - printf(buffer, to_string_view(format), args); - return to_string(buffer); -} - -/** - \rst - Formats arguments and returns the result as a string. - - **Example**:: - - std::string message = fmt::sprintf("The answer is %d", 42); - \endrst -*/ -template <typename S, typename... Args> -inline FMT_ENABLE_IF_T( - internal::is_string<S>::value, std::basic_string<FMT_CHAR(S)>) - sprintf(const S &format, const Args & ... args) { - internal::check_format_string<Args...>(format); - typedef internal::basic_buffer<FMT_CHAR(S)> buffer; - typedef typename basic_printf_context_t<buffer>::type context; - format_arg_store<context, Args...> as{ args... }; - return vsprintf(to_string_view(format), - basic_format_args<context>(as)); -} - -template <typename S, typename Char = FMT_CHAR(S)> -inline int vfprintf(std::FILE *f, const S &format, - basic_format_args<typename basic_printf_context_t< - internal::basic_buffer<Char>>::type> args) { - basic_memory_buffer<Char> buffer; - printf(buffer, to_string_view(format), args); - std::size_t size = buffer.size(); - return std::fwrite( - buffer.data(), sizeof(Char), size, f) < size ? -1 : static_cast<int>(size); -} - -/** - \rst - Prints formatted data to the file *f*. - - **Example**:: - - fmt::fprintf(stderr, "Don't %s!", "panic"); - \endrst - */ -template <typename S, typename... Args> -inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) - fprintf(std::FILE *f, const S &format, const Args & ... args) { - internal::check_format_string<Args...>(format); - typedef internal::basic_buffer<FMT_CHAR(S)> buffer; - typedef typename basic_printf_context_t<buffer>::type context; - format_arg_store<context, Args...> as{ args... }; - return vfprintf(f, to_string_view(format), - basic_format_args<context>(as)); -} - -template <typename S, typename Char = FMT_CHAR(S)> -inline int vprintf(const S &format, - basic_format_args<typename basic_printf_context_t< - internal::basic_buffer<Char>>::type> args) { - return vfprintf(stdout, to_string_view(format), args); -} - -/** - \rst - Prints formatted data to ``stdout``. - - **Example**:: - - fmt::printf("Elapsed time: %.2f seconds", 1.23); - \endrst - */ -template <typename S, typename... Args> -inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) - printf(const S &format_str, const Args & ... args) { - internal::check_format_string<Args...>(format_str); - typedef internal::basic_buffer<FMT_CHAR(S)> buffer; - typedef typename basic_printf_context_t<buffer>::type context; - format_arg_store<context, Args...> as{ args... }; - return vprintf(to_string_view(format_str), - basic_format_args<context>(as)); -} - -template <typename S, typename Char = FMT_CHAR(S)> -inline int vfprintf(std::basic_ostream<Char> &os, - const S &format, - basic_format_args<typename basic_printf_context_t< - internal::basic_buffer<Char>>::type> args) { - basic_memory_buffer<Char> buffer; - printf(buffer, to_string_view(format), args); - internal::write(os, buffer); - return static_cast<int>(buffer.size()); -} - -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - fmt::fprintf(cerr, "Don't %s!", "panic"); - \endrst - */ -template <typename S, typename... Args> -inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) - fprintf(std::basic_ostream<FMT_CHAR(S)> &os, - const S &format_str, const Args & ... args) { - internal::check_format_string<Args...>(format_str); - typedef internal::basic_buffer<FMT_CHAR(S)> buffer; - typedef typename basic_printf_context_t<buffer>::type context; - format_arg_store<context, Args...> as{ args... }; - return vfprintf(os, to_string_view(format_str), - basic_format_args<context>(as)); -} -FMT_END_NAMESPACE - -#endif // FMT_PRINTF_H_ |