1*5c90c05cSAndroid Build Coastguard Worker // Formatting library for C++ - legacy printf implementation 2*5c90c05cSAndroid Build Coastguard Worker // 3*5c90c05cSAndroid Build Coastguard Worker // Copyright (c) 2012 - 2016, Victor Zverovich 4*5c90c05cSAndroid Build Coastguard Worker // All rights reserved. 5*5c90c05cSAndroid Build Coastguard Worker // 6*5c90c05cSAndroid Build Coastguard Worker // For the license information refer to format.h. 7*5c90c05cSAndroid Build Coastguard Worker 8*5c90c05cSAndroid Build Coastguard Worker #ifndef FMT_PRINTF_H_ 9*5c90c05cSAndroid Build Coastguard Worker #define FMT_PRINTF_H_ 10*5c90c05cSAndroid Build Coastguard Worker 11*5c90c05cSAndroid Build Coastguard Worker #ifndef FMT_MODULE 12*5c90c05cSAndroid Build Coastguard Worker # include <algorithm> // std::max 13*5c90c05cSAndroid Build Coastguard Worker # include <limits> // std::numeric_limits 14*5c90c05cSAndroid Build Coastguard Worker #endif 15*5c90c05cSAndroid Build Coastguard Worker 16*5c90c05cSAndroid Build Coastguard Worker #include "format.h" 17*5c90c05cSAndroid Build Coastguard Worker 18*5c90c05cSAndroid Build Coastguard Worker FMT_BEGIN_NAMESPACE 19*5c90c05cSAndroid Build Coastguard Worker FMT_BEGIN_EXPORT 20*5c90c05cSAndroid Build Coastguard Worker 21*5c90c05cSAndroid Build Coastguard Worker template <typename T> struct printf_formatter { 22*5c90c05cSAndroid Build Coastguard Worker printf_formatter() = delete; 23*5c90c05cSAndroid Build Coastguard Worker }; 24*5c90c05cSAndroid Build Coastguard Worker 25*5c90c05cSAndroid Build Coastguard Worker template <typename Char> class basic_printf_context { 26*5c90c05cSAndroid Build Coastguard Worker private: 27*5c90c05cSAndroid Build Coastguard Worker basic_appender<Char> out_; 28*5c90c05cSAndroid Build Coastguard Worker basic_format_args<basic_printf_context> args_; 29*5c90c05cSAndroid Build Coastguard Worker 30*5c90c05cSAndroid Build Coastguard Worker static_assert(std::is_same<Char, char>::value || 31*5c90c05cSAndroid Build Coastguard Worker std::is_same<Char, wchar_t>::value, 32*5c90c05cSAndroid Build Coastguard Worker "Unsupported code unit type."); 33*5c90c05cSAndroid Build Coastguard Worker 34*5c90c05cSAndroid Build Coastguard Worker public: 35*5c90c05cSAndroid Build Coastguard Worker using char_type = Char; 36*5c90c05cSAndroid Build Coastguard Worker using parse_context_type = parse_context<Char>; 37*5c90c05cSAndroid Build Coastguard Worker template <typename T> using formatter_type = printf_formatter<T>; 38*5c90c05cSAndroid Build Coastguard Worker enum { builtin_types = 1 }; 39*5c90c05cSAndroid Build Coastguard Worker 40*5c90c05cSAndroid Build Coastguard Worker /// Constructs a `printf_context` object. References to the arguments are 41*5c90c05cSAndroid Build Coastguard Worker /// stored in the context object so make sure they have appropriate lifetimes. basic_printf_context(basic_appender<Char> out,basic_format_args<basic_printf_context> args)42*5c90c05cSAndroid Build Coastguard Worker basic_printf_context(basic_appender<Char> out, 43*5c90c05cSAndroid Build Coastguard Worker basic_format_args<basic_printf_context> args) 44*5c90c05cSAndroid Build Coastguard Worker : out_(out), args_(args) {} 45*5c90c05cSAndroid Build Coastguard Worker 46*5c90c05cSAndroid Build Coastguard Worker auto out() -> basic_appender<Char> { return out_; } advance_to(basic_appender<Char>)47*5c90c05cSAndroid Build Coastguard Worker void advance_to(basic_appender<Char>) {} 48*5c90c05cSAndroid Build Coastguard Worker 49*5c90c05cSAndroid Build Coastguard Worker auto locale() -> detail::locale_ref { return {}; } 50*5c90c05cSAndroid Build Coastguard Worker 51*5c90c05cSAndroid Build Coastguard Worker auto arg(int id) const -> basic_format_arg<basic_printf_context> { 52*5c90c05cSAndroid Build Coastguard Worker return args_.get(id); 53*5c90c05cSAndroid Build Coastguard Worker } 54*5c90c05cSAndroid Build Coastguard Worker }; 55*5c90c05cSAndroid Build Coastguard Worker 56*5c90c05cSAndroid Build Coastguard Worker namespace detail { 57*5c90c05cSAndroid Build Coastguard Worker 58*5c90c05cSAndroid Build Coastguard Worker // Return the result via the out param to workaround gcc bug 77539. 59*5c90c05cSAndroid Build Coastguard Worker template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*> 60*5c90c05cSAndroid Build Coastguard Worker FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { 61*5c90c05cSAndroid Build Coastguard Worker for (out = first; out != last; ++out) { 62*5c90c05cSAndroid Build Coastguard Worker if (*out == value) return true; 63*5c90c05cSAndroid Build Coastguard Worker } 64*5c90c05cSAndroid Build Coastguard Worker return false; 65*5c90c05cSAndroid Build Coastguard Worker } 66*5c90c05cSAndroid Build Coastguard Worker 67*5c90c05cSAndroid Build Coastguard Worker template <> 68*5c90c05cSAndroid Build Coastguard Worker inline auto find<false, char>(const char* first, const char* last, char value, 69*5c90c05cSAndroid Build Coastguard Worker const char*& out) -> bool { 70*5c90c05cSAndroid Build Coastguard Worker out = 71*5c90c05cSAndroid Build Coastguard Worker static_cast<const char*>(memchr(first, value, to_unsigned(last - first))); 72*5c90c05cSAndroid Build Coastguard Worker return out != nullptr; 73*5c90c05cSAndroid Build Coastguard Worker } 74*5c90c05cSAndroid Build Coastguard Worker 75*5c90c05cSAndroid Build Coastguard Worker // Checks if a value fits in int - used to avoid warnings about comparing 76*5c90c05cSAndroid Build Coastguard Worker // signed and unsigned integers. 77*5c90c05cSAndroid Build Coastguard Worker template <bool IsSigned> struct int_checker { 78*5c90c05cSAndroid Build Coastguard Worker template <typename T> static auto fits_in_int(T value) -> bool { 79*5c90c05cSAndroid Build Coastguard Worker unsigned max = to_unsigned(max_value<int>()); 80*5c90c05cSAndroid Build Coastguard Worker return value <= max; 81*5c90c05cSAndroid Build Coastguard Worker } 82*5c90c05cSAndroid Build Coastguard Worker inline static auto fits_in_int(bool) -> bool { return true; } 83*5c90c05cSAndroid Build Coastguard Worker }; 84*5c90c05cSAndroid Build Coastguard Worker 85*5c90c05cSAndroid Build Coastguard Worker template <> struct int_checker<true> { 86*5c90c05cSAndroid Build Coastguard Worker template <typename T> static auto fits_in_int(T value) -> bool { 87*5c90c05cSAndroid Build Coastguard Worker return value >= (std::numeric_limits<int>::min)() && 88*5c90c05cSAndroid Build Coastguard Worker value <= max_value<int>(); 89*5c90c05cSAndroid Build Coastguard Worker } 90*5c90c05cSAndroid Build Coastguard Worker inline static auto fits_in_int(int) -> bool { return true; } 91*5c90c05cSAndroid Build Coastguard Worker }; 92*5c90c05cSAndroid Build Coastguard Worker 93*5c90c05cSAndroid Build Coastguard Worker struct printf_precision_handler { 94*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> 95*5c90c05cSAndroid Build Coastguard Worker auto operator()(T value) -> int { 96*5c90c05cSAndroid Build Coastguard Worker if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) 97*5c90c05cSAndroid Build Coastguard Worker report_error("number is too big"); 98*5c90c05cSAndroid Build Coastguard Worker return (std::max)(static_cast<int>(value), 0); 99*5c90c05cSAndroid Build Coastguard Worker } 100*5c90c05cSAndroid Build Coastguard Worker 101*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> 102*5c90c05cSAndroid Build Coastguard Worker auto operator()(T) -> int { 103*5c90c05cSAndroid Build Coastguard Worker report_error("precision is not integer"); 104*5c90c05cSAndroid Build Coastguard Worker return 0; 105*5c90c05cSAndroid Build Coastguard Worker } 106*5c90c05cSAndroid Build Coastguard Worker }; 107*5c90c05cSAndroid Build Coastguard Worker 108*5c90c05cSAndroid Build Coastguard Worker // An argument visitor that returns true iff arg is a zero integer. 109*5c90c05cSAndroid Build Coastguard Worker struct is_zero_int { 110*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> 111*5c90c05cSAndroid Build Coastguard Worker auto operator()(T value) -> bool { 112*5c90c05cSAndroid Build Coastguard Worker return value == 0; 113*5c90c05cSAndroid Build Coastguard Worker } 114*5c90c05cSAndroid Build Coastguard Worker 115*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> 116*5c90c05cSAndroid Build Coastguard Worker auto operator()(T) -> bool { 117*5c90c05cSAndroid Build Coastguard Worker return false; 118*5c90c05cSAndroid Build Coastguard Worker } 119*5c90c05cSAndroid Build Coastguard Worker }; 120*5c90c05cSAndroid Build Coastguard Worker 121*5c90c05cSAndroid Build Coastguard Worker template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {}; 122*5c90c05cSAndroid Build Coastguard Worker 123*5c90c05cSAndroid Build Coastguard Worker template <> struct make_unsigned_or_bool<bool> { 124*5c90c05cSAndroid Build Coastguard Worker using type = bool; 125*5c90c05cSAndroid Build Coastguard Worker }; 126*5c90c05cSAndroid Build Coastguard Worker 127*5c90c05cSAndroid Build Coastguard Worker template <typename T, typename Context> class arg_converter { 128*5c90c05cSAndroid Build Coastguard Worker private: 129*5c90c05cSAndroid Build Coastguard Worker using char_type = typename Context::char_type; 130*5c90c05cSAndroid Build Coastguard Worker 131*5c90c05cSAndroid Build Coastguard Worker basic_format_arg<Context>& arg_; 132*5c90c05cSAndroid Build Coastguard Worker char_type type_; 133*5c90c05cSAndroid Build Coastguard Worker 134*5c90c05cSAndroid Build Coastguard Worker public: 135*5c90c05cSAndroid Build Coastguard Worker arg_converter(basic_format_arg<Context>& arg, char_type type) 136*5c90c05cSAndroid Build Coastguard Worker : arg_(arg), type_(type) {} 137*5c90c05cSAndroid Build Coastguard Worker 138*5c90c05cSAndroid Build Coastguard Worker void operator()(bool value) { 139*5c90c05cSAndroid Build Coastguard Worker if (type_ != 's') operator()<bool>(value); 140*5c90c05cSAndroid Build Coastguard Worker } 141*5c90c05cSAndroid Build Coastguard Worker 142*5c90c05cSAndroid Build Coastguard Worker template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)> 143*5c90c05cSAndroid Build Coastguard Worker void operator()(U value) { 144*5c90c05cSAndroid Build Coastguard Worker bool is_signed = type_ == 'd' || type_ == 'i'; 145*5c90c05cSAndroid Build Coastguard Worker using target_type = conditional_t<std::is_same<T, void>::value, U, T>; 146*5c90c05cSAndroid Build Coastguard Worker if (const_check(sizeof(target_type) <= sizeof(int))) { 147*5c90c05cSAndroid Build Coastguard Worker // Extra casts are used to silence warnings. 148*5c90c05cSAndroid Build Coastguard Worker using unsigned_type = typename make_unsigned_or_bool<target_type>::type; 149*5c90c05cSAndroid Build Coastguard Worker if (is_signed) 150*5c90c05cSAndroid Build Coastguard Worker arg_ = static_cast<int>(static_cast<target_type>(value)); 151*5c90c05cSAndroid Build Coastguard Worker else 152*5c90c05cSAndroid Build Coastguard Worker arg_ = static_cast<unsigned>(static_cast<unsigned_type>(value)); 153*5c90c05cSAndroid Build Coastguard Worker } else { 154*5c90c05cSAndroid Build Coastguard Worker // glibc's printf doesn't sign extend arguments of smaller types: 155*5c90c05cSAndroid Build Coastguard Worker // std::printf("%lld", -42); // prints "4294967254" 156*5c90c05cSAndroid Build Coastguard Worker // but we don't have to do the same because it's a UB. 157*5c90c05cSAndroid Build Coastguard Worker if (is_signed) 158*5c90c05cSAndroid Build Coastguard Worker arg_ = static_cast<long long>(value); 159*5c90c05cSAndroid Build Coastguard Worker else 160*5c90c05cSAndroid Build Coastguard Worker arg_ = static_cast<typename make_unsigned_or_bool<U>::type>(value); 161*5c90c05cSAndroid Build Coastguard Worker } 162*5c90c05cSAndroid Build Coastguard Worker } 163*5c90c05cSAndroid Build Coastguard Worker 164*5c90c05cSAndroid Build Coastguard Worker template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)> 165*5c90c05cSAndroid Build Coastguard Worker void operator()(U) {} // No conversion needed for non-integral types. 166*5c90c05cSAndroid Build Coastguard Worker }; 167*5c90c05cSAndroid Build Coastguard Worker 168*5c90c05cSAndroid Build Coastguard Worker // Converts an integer argument to T for printf, if T is an integral type. 169*5c90c05cSAndroid Build Coastguard Worker // If T is void, the argument is converted to corresponding signed or unsigned 170*5c90c05cSAndroid Build Coastguard Worker // type depending on the type specifier: 'd' and 'i' - signed, other - 171*5c90c05cSAndroid Build Coastguard Worker // unsigned). 172*5c90c05cSAndroid Build Coastguard Worker template <typename T, typename Context, typename Char> 173*5c90c05cSAndroid Build Coastguard Worker void convert_arg(basic_format_arg<Context>& arg, Char type) { 174*5c90c05cSAndroid Build Coastguard Worker arg.visit(arg_converter<T, Context>(arg, type)); 175*5c90c05cSAndroid Build Coastguard Worker } 176*5c90c05cSAndroid Build Coastguard Worker 177*5c90c05cSAndroid Build Coastguard Worker // Converts an integer argument to char for printf. 178*5c90c05cSAndroid Build Coastguard Worker template <typename Context> class char_converter { 179*5c90c05cSAndroid Build Coastguard Worker private: 180*5c90c05cSAndroid Build Coastguard Worker basic_format_arg<Context>& arg_; 181*5c90c05cSAndroid Build Coastguard Worker 182*5c90c05cSAndroid Build Coastguard Worker public: 183*5c90c05cSAndroid Build Coastguard Worker explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {} 184*5c90c05cSAndroid Build Coastguard Worker 185*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> 186*5c90c05cSAndroid Build Coastguard Worker void operator()(T value) { 187*5c90c05cSAndroid Build Coastguard Worker arg_ = static_cast<typename Context::char_type>(value); 188*5c90c05cSAndroid Build Coastguard Worker } 189*5c90c05cSAndroid Build Coastguard Worker 190*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> 191*5c90c05cSAndroid Build Coastguard Worker void operator()(T) {} // No conversion needed for non-integral types. 192*5c90c05cSAndroid Build Coastguard Worker }; 193*5c90c05cSAndroid Build Coastguard Worker 194*5c90c05cSAndroid Build Coastguard Worker // An argument visitor that return a pointer to a C string if argument is a 195*5c90c05cSAndroid Build Coastguard Worker // string or null otherwise. 196*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct get_cstring { 197*5c90c05cSAndroid Build Coastguard Worker template <typename T> auto operator()(T) -> const Char* { return nullptr; } 198*5c90c05cSAndroid Build Coastguard Worker auto operator()(const Char* s) -> const Char* { return s; } 199*5c90c05cSAndroid Build Coastguard Worker }; 200*5c90c05cSAndroid Build Coastguard Worker 201*5c90c05cSAndroid Build Coastguard Worker // Checks if an argument is a valid printf width specifier and sets 202*5c90c05cSAndroid Build Coastguard Worker // left alignment if it is negative. 203*5c90c05cSAndroid Build Coastguard Worker class printf_width_handler { 204*5c90c05cSAndroid Build Coastguard Worker private: 205*5c90c05cSAndroid Build Coastguard Worker format_specs& specs_; 206*5c90c05cSAndroid Build Coastguard Worker 207*5c90c05cSAndroid Build Coastguard Worker public: 208*5c90c05cSAndroid Build Coastguard Worker inline explicit printf_width_handler(format_specs& specs) : specs_(specs) {} 209*5c90c05cSAndroid Build Coastguard Worker 210*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> 211*5c90c05cSAndroid Build Coastguard Worker auto operator()(T value) -> unsigned { 212*5c90c05cSAndroid Build Coastguard Worker auto width = static_cast<uint32_or_64_or_128_t<T>>(value); 213*5c90c05cSAndroid Build Coastguard Worker if (detail::is_negative(value)) { 214*5c90c05cSAndroid Build Coastguard Worker specs_.set_align(align::left); 215*5c90c05cSAndroid Build Coastguard Worker width = 0 - width; 216*5c90c05cSAndroid Build Coastguard Worker } 217*5c90c05cSAndroid Build Coastguard Worker unsigned int_max = to_unsigned(max_value<int>()); 218*5c90c05cSAndroid Build Coastguard Worker if (width > int_max) report_error("number is too big"); 219*5c90c05cSAndroid Build Coastguard Worker return static_cast<unsigned>(width); 220*5c90c05cSAndroid Build Coastguard Worker } 221*5c90c05cSAndroid Build Coastguard Worker 222*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> 223*5c90c05cSAndroid Build Coastguard Worker auto operator()(T) -> unsigned { 224*5c90c05cSAndroid Build Coastguard Worker report_error("width is not integer"); 225*5c90c05cSAndroid Build Coastguard Worker return 0; 226*5c90c05cSAndroid Build Coastguard Worker } 227*5c90c05cSAndroid Build Coastguard Worker }; 228*5c90c05cSAndroid Build Coastguard Worker 229*5c90c05cSAndroid Build Coastguard Worker // Workaround for a bug with the XL compiler when initializing 230*5c90c05cSAndroid Build Coastguard Worker // printf_arg_formatter's base class. 231*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 232*5c90c05cSAndroid Build Coastguard Worker auto make_arg_formatter(basic_appender<Char> iter, format_specs& s) 233*5c90c05cSAndroid Build Coastguard Worker -> arg_formatter<Char> { 234*5c90c05cSAndroid Build Coastguard Worker return {iter, s, locale_ref()}; 235*5c90c05cSAndroid Build Coastguard Worker } 236*5c90c05cSAndroid Build Coastguard Worker 237*5c90c05cSAndroid Build Coastguard Worker // The `printf` argument formatter. 238*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 239*5c90c05cSAndroid Build Coastguard Worker class printf_arg_formatter : public arg_formatter<Char> { 240*5c90c05cSAndroid Build Coastguard Worker private: 241*5c90c05cSAndroid Build Coastguard Worker using base = arg_formatter<Char>; 242*5c90c05cSAndroid Build Coastguard Worker using context_type = basic_printf_context<Char>; 243*5c90c05cSAndroid Build Coastguard Worker 244*5c90c05cSAndroid Build Coastguard Worker context_type& context_; 245*5c90c05cSAndroid Build Coastguard Worker 246*5c90c05cSAndroid Build Coastguard Worker void write_null_pointer(bool is_string = false) { 247*5c90c05cSAndroid Build Coastguard Worker auto s = this->specs; 248*5c90c05cSAndroid Build Coastguard Worker s.set_type(presentation_type::none); 249*5c90c05cSAndroid Build Coastguard Worker write_bytes<Char>(this->out, is_string ? "(null)" : "(nil)", s); 250*5c90c05cSAndroid Build Coastguard Worker } 251*5c90c05cSAndroid Build Coastguard Worker 252*5c90c05cSAndroid Build Coastguard Worker template <typename T> void write(T value) { 253*5c90c05cSAndroid Build Coastguard Worker detail::write<Char>(this->out, value, this->specs, this->locale); 254*5c90c05cSAndroid Build Coastguard Worker } 255*5c90c05cSAndroid Build Coastguard Worker 256*5c90c05cSAndroid Build Coastguard Worker public: 257*5c90c05cSAndroid Build Coastguard Worker printf_arg_formatter(basic_appender<Char> iter, format_specs& s, 258*5c90c05cSAndroid Build Coastguard Worker context_type& ctx) 259*5c90c05cSAndroid Build Coastguard Worker : base(make_arg_formatter(iter, s)), context_(ctx) {} 260*5c90c05cSAndroid Build Coastguard Worker 261*5c90c05cSAndroid Build Coastguard Worker void operator()(monostate value) { write(value); } 262*5c90c05cSAndroid Build Coastguard Worker 263*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)> 264*5c90c05cSAndroid Build Coastguard Worker void operator()(T value) { 265*5c90c05cSAndroid Build Coastguard Worker // MSVC2013 fails to compile separate overloads for bool and Char so use 266*5c90c05cSAndroid Build Coastguard Worker // std::is_same instead. 267*5c90c05cSAndroid Build Coastguard Worker if (!std::is_same<T, Char>::value) { 268*5c90c05cSAndroid Build Coastguard Worker write(value); 269*5c90c05cSAndroid Build Coastguard Worker return; 270*5c90c05cSAndroid Build Coastguard Worker } 271*5c90c05cSAndroid Build Coastguard Worker format_specs s = this->specs; 272*5c90c05cSAndroid Build Coastguard Worker if (s.type() != presentation_type::none && 273*5c90c05cSAndroid Build Coastguard Worker s.type() != presentation_type::chr) { 274*5c90c05cSAndroid Build Coastguard Worker return (*this)(static_cast<int>(value)); 275*5c90c05cSAndroid Build Coastguard Worker } 276*5c90c05cSAndroid Build Coastguard Worker s.set_sign(sign::none); 277*5c90c05cSAndroid Build Coastguard Worker s.clear_alt(); 278*5c90c05cSAndroid Build Coastguard Worker s.set_fill(' '); // Ignore '0' flag for char types. 279*5c90c05cSAndroid Build Coastguard Worker // align::numeric needs to be overwritten here since the '0' flag is 280*5c90c05cSAndroid Build Coastguard Worker // ignored for non-numeric types 281*5c90c05cSAndroid Build Coastguard Worker if (s.align() == align::none || s.align() == align::numeric) 282*5c90c05cSAndroid Build Coastguard Worker s.set_align(align::right); 283*5c90c05cSAndroid Build Coastguard Worker detail::write<Char>(this->out, static_cast<Char>(value), s); 284*5c90c05cSAndroid Build Coastguard Worker } 285*5c90c05cSAndroid Build Coastguard Worker 286*5c90c05cSAndroid Build Coastguard Worker template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> 287*5c90c05cSAndroid Build Coastguard Worker void operator()(T value) { 288*5c90c05cSAndroid Build Coastguard Worker write(value); 289*5c90c05cSAndroid Build Coastguard Worker } 290*5c90c05cSAndroid Build Coastguard Worker 291*5c90c05cSAndroid Build Coastguard Worker void operator()(const char* value) { 292*5c90c05cSAndroid Build Coastguard Worker if (value) 293*5c90c05cSAndroid Build Coastguard Worker write(value); 294*5c90c05cSAndroid Build Coastguard Worker else 295*5c90c05cSAndroid Build Coastguard Worker write_null_pointer(this->specs.type() != presentation_type::pointer); 296*5c90c05cSAndroid Build Coastguard Worker } 297*5c90c05cSAndroid Build Coastguard Worker 298*5c90c05cSAndroid Build Coastguard Worker void operator()(const wchar_t* value) { 299*5c90c05cSAndroid Build Coastguard Worker if (value) 300*5c90c05cSAndroid Build Coastguard Worker write(value); 301*5c90c05cSAndroid Build Coastguard Worker else 302*5c90c05cSAndroid Build Coastguard Worker write_null_pointer(this->specs.type() != presentation_type::pointer); 303*5c90c05cSAndroid Build Coastguard Worker } 304*5c90c05cSAndroid Build Coastguard Worker 305*5c90c05cSAndroid Build Coastguard Worker void operator()(basic_string_view<Char> value) { write(value); } 306*5c90c05cSAndroid Build Coastguard Worker 307*5c90c05cSAndroid Build Coastguard Worker void operator()(const void* value) { 308*5c90c05cSAndroid Build Coastguard Worker if (value) 309*5c90c05cSAndroid Build Coastguard Worker write(value); 310*5c90c05cSAndroid Build Coastguard Worker else 311*5c90c05cSAndroid Build Coastguard Worker write_null_pointer(); 312*5c90c05cSAndroid Build Coastguard Worker } 313*5c90c05cSAndroid Build Coastguard Worker 314*5c90c05cSAndroid Build Coastguard Worker void operator()(typename basic_format_arg<context_type>::handle handle) { 315*5c90c05cSAndroid Build Coastguard Worker auto parse_ctx = parse_context<Char>({}); 316*5c90c05cSAndroid Build Coastguard Worker handle.format(parse_ctx, context_); 317*5c90c05cSAndroid Build Coastguard Worker } 318*5c90c05cSAndroid Build Coastguard Worker }; 319*5c90c05cSAndroid Build Coastguard Worker 320*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 321*5c90c05cSAndroid Build Coastguard Worker void parse_flags(format_specs& specs, const Char*& it, const Char* end) { 322*5c90c05cSAndroid Build Coastguard Worker for (; it != end; ++it) { 323*5c90c05cSAndroid Build Coastguard Worker switch (*it) { 324*5c90c05cSAndroid Build Coastguard Worker case '-': specs.set_align(align::left); break; 325*5c90c05cSAndroid Build Coastguard Worker case '+': specs.set_sign(sign::plus); break; 326*5c90c05cSAndroid Build Coastguard Worker case '0': specs.set_fill('0'); break; 327*5c90c05cSAndroid Build Coastguard Worker case ' ': 328*5c90c05cSAndroid Build Coastguard Worker if (specs.sign() != sign::plus) specs.set_sign(sign::space); 329*5c90c05cSAndroid Build Coastguard Worker break; 330*5c90c05cSAndroid Build Coastguard Worker case '#': specs.set_alt(); break; 331*5c90c05cSAndroid Build Coastguard Worker default: return; 332*5c90c05cSAndroid Build Coastguard Worker } 333*5c90c05cSAndroid Build Coastguard Worker } 334*5c90c05cSAndroid Build Coastguard Worker } 335*5c90c05cSAndroid Build Coastguard Worker 336*5c90c05cSAndroid Build Coastguard Worker template <typename Char, typename GetArg> 337*5c90c05cSAndroid Build Coastguard Worker auto parse_header(const Char*& it, const Char* end, format_specs& specs, 338*5c90c05cSAndroid Build Coastguard Worker GetArg get_arg) -> int { 339*5c90c05cSAndroid Build Coastguard Worker int arg_index = -1; 340*5c90c05cSAndroid Build Coastguard Worker Char c = *it; 341*5c90c05cSAndroid Build Coastguard Worker if (c >= '0' && c <= '9') { 342*5c90c05cSAndroid Build Coastguard Worker // Parse an argument index (if followed by '$') or a width possibly 343*5c90c05cSAndroid Build Coastguard Worker // preceded with '0' flag(s). 344*5c90c05cSAndroid Build Coastguard Worker int value = parse_nonnegative_int(it, end, -1); 345*5c90c05cSAndroid Build Coastguard Worker if (it != end && *it == '$') { // value is an argument index 346*5c90c05cSAndroid Build Coastguard Worker ++it; 347*5c90c05cSAndroid Build Coastguard Worker arg_index = value != -1 ? value : max_value<int>(); 348*5c90c05cSAndroid Build Coastguard Worker } else { 349*5c90c05cSAndroid Build Coastguard Worker if (c == '0') specs.set_fill('0'); 350*5c90c05cSAndroid Build Coastguard Worker if (value != 0) { 351*5c90c05cSAndroid Build Coastguard Worker // Nonzero value means that we parsed width and don't need to 352*5c90c05cSAndroid Build Coastguard Worker // parse it or flags again, so return now. 353*5c90c05cSAndroid Build Coastguard Worker if (value == -1) report_error("number is too big"); 354*5c90c05cSAndroid Build Coastguard Worker specs.width = value; 355*5c90c05cSAndroid Build Coastguard Worker return arg_index; 356*5c90c05cSAndroid Build Coastguard Worker } 357*5c90c05cSAndroid Build Coastguard Worker } 358*5c90c05cSAndroid Build Coastguard Worker } 359*5c90c05cSAndroid Build Coastguard Worker parse_flags(specs, it, end); 360*5c90c05cSAndroid Build Coastguard Worker // Parse width. 361*5c90c05cSAndroid Build Coastguard Worker if (it != end) { 362*5c90c05cSAndroid Build Coastguard Worker if (*it >= '0' && *it <= '9') { 363*5c90c05cSAndroid Build Coastguard Worker specs.width = parse_nonnegative_int(it, end, -1); 364*5c90c05cSAndroid Build Coastguard Worker if (specs.width == -1) report_error("number is too big"); 365*5c90c05cSAndroid Build Coastguard Worker } else if (*it == '*') { 366*5c90c05cSAndroid Build Coastguard Worker ++it; 367*5c90c05cSAndroid Build Coastguard Worker specs.width = static_cast<int>( 368*5c90c05cSAndroid Build Coastguard Worker get_arg(-1).visit(detail::printf_width_handler(specs))); 369*5c90c05cSAndroid Build Coastguard Worker } 370*5c90c05cSAndroid Build Coastguard Worker } 371*5c90c05cSAndroid Build Coastguard Worker return arg_index; 372*5c90c05cSAndroid Build Coastguard Worker } 373*5c90c05cSAndroid Build Coastguard Worker 374*5c90c05cSAndroid Build Coastguard Worker inline auto parse_printf_presentation_type(char c, type t, bool& upper) 375*5c90c05cSAndroid Build Coastguard Worker -> presentation_type { 376*5c90c05cSAndroid Build Coastguard Worker using pt = presentation_type; 377*5c90c05cSAndroid Build Coastguard Worker constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; 378*5c90c05cSAndroid Build Coastguard Worker switch (c) { 379*5c90c05cSAndroid Build Coastguard Worker case 'd': return in(t, integral_set) ? pt::dec : pt::none; 380*5c90c05cSAndroid Build Coastguard Worker case 'o': return in(t, integral_set) ? pt::oct : pt::none; 381*5c90c05cSAndroid Build Coastguard Worker case 'X': upper = true; FMT_FALLTHROUGH; 382*5c90c05cSAndroid Build Coastguard Worker case 'x': return in(t, integral_set) ? pt::hex : pt::none; 383*5c90c05cSAndroid Build Coastguard Worker case 'E': upper = true; FMT_FALLTHROUGH; 384*5c90c05cSAndroid Build Coastguard Worker case 'e': return in(t, float_set) ? pt::exp : pt::none; 385*5c90c05cSAndroid Build Coastguard Worker case 'F': upper = true; FMT_FALLTHROUGH; 386*5c90c05cSAndroid Build Coastguard Worker case 'f': return in(t, float_set) ? pt::fixed : pt::none; 387*5c90c05cSAndroid Build Coastguard Worker case 'G': upper = true; FMT_FALLTHROUGH; 388*5c90c05cSAndroid Build Coastguard Worker case 'g': return in(t, float_set) ? pt::general : pt::none; 389*5c90c05cSAndroid Build Coastguard Worker case 'A': upper = true; FMT_FALLTHROUGH; 390*5c90c05cSAndroid Build Coastguard Worker case 'a': return in(t, float_set) ? pt::hexfloat : pt::none; 391*5c90c05cSAndroid Build Coastguard Worker case 'c': return in(t, integral_set) ? pt::chr : pt::none; 392*5c90c05cSAndroid Build Coastguard Worker case 's': return in(t, string_set | cstring_set) ? pt::string : pt::none; 393*5c90c05cSAndroid Build Coastguard Worker case 'p': return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none; 394*5c90c05cSAndroid Build Coastguard Worker default: return pt::none; 395*5c90c05cSAndroid Build Coastguard Worker } 396*5c90c05cSAndroid Build Coastguard Worker } 397*5c90c05cSAndroid Build Coastguard Worker 398*5c90c05cSAndroid Build Coastguard Worker template <typename Char, typename Context> 399*5c90c05cSAndroid Build Coastguard Worker void vprintf(buffer<Char>& buf, basic_string_view<Char> format, 400*5c90c05cSAndroid Build Coastguard Worker basic_format_args<Context> args) { 401*5c90c05cSAndroid Build Coastguard Worker using iterator = basic_appender<Char>; 402*5c90c05cSAndroid Build Coastguard Worker auto out = iterator(buf); 403*5c90c05cSAndroid Build Coastguard Worker auto context = basic_printf_context<Char>(out, args); 404*5c90c05cSAndroid Build Coastguard Worker auto parse_ctx = parse_context<Char>(format); 405*5c90c05cSAndroid Build Coastguard Worker 406*5c90c05cSAndroid Build Coastguard Worker // Returns the argument with specified index or, if arg_index is -1, the next 407*5c90c05cSAndroid Build Coastguard Worker // argument. 408*5c90c05cSAndroid Build Coastguard Worker auto get_arg = [&](int arg_index) { 409*5c90c05cSAndroid Build Coastguard Worker if (arg_index < 0) 410*5c90c05cSAndroid Build Coastguard Worker arg_index = parse_ctx.next_arg_id(); 411*5c90c05cSAndroid Build Coastguard Worker else 412*5c90c05cSAndroid Build Coastguard Worker parse_ctx.check_arg_id(--arg_index); 413*5c90c05cSAndroid Build Coastguard Worker return detail::get_arg(context, arg_index); 414*5c90c05cSAndroid Build Coastguard Worker }; 415*5c90c05cSAndroid Build Coastguard Worker 416*5c90c05cSAndroid Build Coastguard Worker const Char* start = parse_ctx.begin(); 417*5c90c05cSAndroid Build Coastguard Worker const Char* end = parse_ctx.end(); 418*5c90c05cSAndroid Build Coastguard Worker auto it = start; 419*5c90c05cSAndroid Build Coastguard Worker while (it != end) { 420*5c90c05cSAndroid Build Coastguard Worker if (!find<false, Char>(it, end, '%', it)) { 421*5c90c05cSAndroid Build Coastguard Worker it = end; // find leaves it == nullptr if it doesn't find '%'. 422*5c90c05cSAndroid Build Coastguard Worker break; 423*5c90c05cSAndroid Build Coastguard Worker } 424*5c90c05cSAndroid Build Coastguard Worker Char c = *it++; 425*5c90c05cSAndroid Build Coastguard Worker if (it != end && *it == c) { 426*5c90c05cSAndroid Build Coastguard Worker write(out, basic_string_view<Char>(start, to_unsigned(it - start))); 427*5c90c05cSAndroid Build Coastguard Worker start = ++it; 428*5c90c05cSAndroid Build Coastguard Worker continue; 429*5c90c05cSAndroid Build Coastguard Worker } 430*5c90c05cSAndroid Build Coastguard Worker write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start))); 431*5c90c05cSAndroid Build Coastguard Worker 432*5c90c05cSAndroid Build Coastguard Worker auto specs = format_specs(); 433*5c90c05cSAndroid Build Coastguard Worker specs.set_align(align::right); 434*5c90c05cSAndroid Build Coastguard Worker 435*5c90c05cSAndroid Build Coastguard Worker // Parse argument index, flags and width. 436*5c90c05cSAndroid Build Coastguard Worker int arg_index = parse_header(it, end, specs, get_arg); 437*5c90c05cSAndroid Build Coastguard Worker if (arg_index == 0) report_error("argument not found"); 438*5c90c05cSAndroid Build Coastguard Worker 439*5c90c05cSAndroid Build Coastguard Worker // Parse precision. 440*5c90c05cSAndroid Build Coastguard Worker if (it != end && *it == '.') { 441*5c90c05cSAndroid Build Coastguard Worker ++it; 442*5c90c05cSAndroid Build Coastguard Worker c = it != end ? *it : 0; 443*5c90c05cSAndroid Build Coastguard Worker if ('0' <= c && c <= '9') { 444*5c90c05cSAndroid Build Coastguard Worker specs.precision = parse_nonnegative_int(it, end, 0); 445*5c90c05cSAndroid Build Coastguard Worker } else if (c == '*') { 446*5c90c05cSAndroid Build Coastguard Worker ++it; 447*5c90c05cSAndroid Build Coastguard Worker specs.precision = 448*5c90c05cSAndroid Build Coastguard Worker static_cast<int>(get_arg(-1).visit(printf_precision_handler())); 449*5c90c05cSAndroid Build Coastguard Worker } else { 450*5c90c05cSAndroid Build Coastguard Worker specs.precision = 0; 451*5c90c05cSAndroid Build Coastguard Worker } 452*5c90c05cSAndroid Build Coastguard Worker } 453*5c90c05cSAndroid Build Coastguard Worker 454*5c90c05cSAndroid Build Coastguard Worker auto arg = get_arg(arg_index); 455*5c90c05cSAndroid Build Coastguard Worker // For d, i, o, u, x, and X conversion specifiers, if a precision is 456*5c90c05cSAndroid Build Coastguard Worker // specified, the '0' flag is ignored 457*5c90c05cSAndroid Build Coastguard Worker if (specs.precision >= 0 && is_integral_type(arg.type())) { 458*5c90c05cSAndroid Build Coastguard Worker // Ignore '0' for non-numeric types or if '-' present. 459*5c90c05cSAndroid Build Coastguard Worker specs.set_fill(' '); 460*5c90c05cSAndroid Build Coastguard Worker } 461*5c90c05cSAndroid Build Coastguard Worker if (specs.precision >= 0 && arg.type() == type::cstring_type) { 462*5c90c05cSAndroid Build Coastguard Worker auto str = arg.visit(get_cstring<Char>()); 463*5c90c05cSAndroid Build Coastguard Worker auto str_end = str + specs.precision; 464*5c90c05cSAndroid Build Coastguard Worker auto nul = std::find(str, str_end, Char()); 465*5c90c05cSAndroid Build Coastguard Worker auto sv = basic_string_view<Char>( 466*5c90c05cSAndroid Build Coastguard Worker str, to_unsigned(nul != str_end ? nul - str : specs.precision)); 467*5c90c05cSAndroid Build Coastguard Worker arg = sv; 468*5c90c05cSAndroid Build Coastguard Worker } 469*5c90c05cSAndroid Build Coastguard Worker if (specs.alt() && arg.visit(is_zero_int())) specs.clear_alt(); 470*5c90c05cSAndroid Build Coastguard Worker if (specs.fill_unit<Char>() == '0') { 471*5c90c05cSAndroid Build Coastguard Worker if (is_arithmetic_type(arg.type()) && specs.align() != align::left) { 472*5c90c05cSAndroid Build Coastguard Worker specs.set_align(align::numeric); 473*5c90c05cSAndroid Build Coastguard Worker } else { 474*5c90c05cSAndroid Build Coastguard Worker // Ignore '0' flag for non-numeric types or if '-' flag is also present. 475*5c90c05cSAndroid Build Coastguard Worker specs.set_fill(' '); 476*5c90c05cSAndroid Build Coastguard Worker } 477*5c90c05cSAndroid Build Coastguard Worker } 478*5c90c05cSAndroid Build Coastguard Worker 479*5c90c05cSAndroid Build Coastguard Worker // Parse length and convert the argument to the required type. 480*5c90c05cSAndroid Build Coastguard Worker c = it != end ? *it++ : 0; 481*5c90c05cSAndroid Build Coastguard Worker Char t = it != end ? *it : 0; 482*5c90c05cSAndroid Build Coastguard Worker switch (c) { 483*5c90c05cSAndroid Build Coastguard Worker case 'h': 484*5c90c05cSAndroid Build Coastguard Worker if (t == 'h') { 485*5c90c05cSAndroid Build Coastguard Worker ++it; 486*5c90c05cSAndroid Build Coastguard Worker t = it != end ? *it : 0; 487*5c90c05cSAndroid Build Coastguard Worker convert_arg<signed char>(arg, t); 488*5c90c05cSAndroid Build Coastguard Worker } else { 489*5c90c05cSAndroid Build Coastguard Worker convert_arg<short>(arg, t); 490*5c90c05cSAndroid Build Coastguard Worker } 491*5c90c05cSAndroid Build Coastguard Worker break; 492*5c90c05cSAndroid Build Coastguard Worker case 'l': 493*5c90c05cSAndroid Build Coastguard Worker if (t == 'l') { 494*5c90c05cSAndroid Build Coastguard Worker ++it; 495*5c90c05cSAndroid Build Coastguard Worker t = it != end ? *it : 0; 496*5c90c05cSAndroid Build Coastguard Worker convert_arg<long long>(arg, t); 497*5c90c05cSAndroid Build Coastguard Worker } else { 498*5c90c05cSAndroid Build Coastguard Worker convert_arg<long>(arg, t); 499*5c90c05cSAndroid Build Coastguard Worker } 500*5c90c05cSAndroid Build Coastguard Worker break; 501*5c90c05cSAndroid Build Coastguard Worker case 'j': convert_arg<intmax_t>(arg, t); break; 502*5c90c05cSAndroid Build Coastguard Worker case 'z': convert_arg<size_t>(arg, t); break; 503*5c90c05cSAndroid Build Coastguard Worker case 't': convert_arg<std::ptrdiff_t>(arg, t); break; 504*5c90c05cSAndroid Build Coastguard Worker case 'L': 505*5c90c05cSAndroid Build Coastguard Worker // printf produces garbage when 'L' is omitted for long double, no 506*5c90c05cSAndroid Build Coastguard Worker // need to do the same. 507*5c90c05cSAndroid Build Coastguard Worker break; 508*5c90c05cSAndroid Build Coastguard Worker default: --it; convert_arg<void>(arg, c); 509*5c90c05cSAndroid Build Coastguard Worker } 510*5c90c05cSAndroid Build Coastguard Worker 511*5c90c05cSAndroid Build Coastguard Worker // Parse type. 512*5c90c05cSAndroid Build Coastguard Worker if (it == end) report_error("invalid format string"); 513*5c90c05cSAndroid Build Coastguard Worker char type = static_cast<char>(*it++); 514*5c90c05cSAndroid Build Coastguard Worker if (is_integral_type(arg.type())) { 515*5c90c05cSAndroid Build Coastguard Worker // Normalize type. 516*5c90c05cSAndroid Build Coastguard Worker switch (type) { 517*5c90c05cSAndroid Build Coastguard Worker case 'i': 518*5c90c05cSAndroid Build Coastguard Worker case 'u': type = 'd'; break; 519*5c90c05cSAndroid Build Coastguard Worker case 'c': 520*5c90c05cSAndroid Build Coastguard Worker arg.visit(char_converter<basic_printf_context<Char>>(arg)); 521*5c90c05cSAndroid Build Coastguard Worker break; 522*5c90c05cSAndroid Build Coastguard Worker } 523*5c90c05cSAndroid Build Coastguard Worker } 524*5c90c05cSAndroid Build Coastguard Worker bool upper = false; 525*5c90c05cSAndroid Build Coastguard Worker specs.set_type(parse_printf_presentation_type(type, arg.type(), upper)); 526*5c90c05cSAndroid Build Coastguard Worker if (specs.type() == presentation_type::none) 527*5c90c05cSAndroid Build Coastguard Worker report_error("invalid format specifier"); 528*5c90c05cSAndroid Build Coastguard Worker if (upper) specs.set_upper(); 529*5c90c05cSAndroid Build Coastguard Worker 530*5c90c05cSAndroid Build Coastguard Worker start = it; 531*5c90c05cSAndroid Build Coastguard Worker 532*5c90c05cSAndroid Build Coastguard Worker // Format argument. 533*5c90c05cSAndroid Build Coastguard Worker arg.visit(printf_arg_formatter<Char>(out, specs, context)); 534*5c90c05cSAndroid Build Coastguard Worker } 535*5c90c05cSAndroid Build Coastguard Worker write(out, basic_string_view<Char>(start, to_unsigned(it - start))); 536*5c90c05cSAndroid Build Coastguard Worker } 537*5c90c05cSAndroid Build Coastguard Worker } // namespace detail 538*5c90c05cSAndroid Build Coastguard Worker 539*5c90c05cSAndroid Build Coastguard Worker using printf_context = basic_printf_context<char>; 540*5c90c05cSAndroid Build Coastguard Worker using wprintf_context = basic_printf_context<wchar_t>; 541*5c90c05cSAndroid Build Coastguard Worker 542*5c90c05cSAndroid Build Coastguard Worker using printf_args = basic_format_args<printf_context>; 543*5c90c05cSAndroid Build Coastguard Worker using wprintf_args = basic_format_args<wprintf_context>; 544*5c90c05cSAndroid Build Coastguard Worker 545*5c90c05cSAndroid Build Coastguard Worker /// Constructs an `format_arg_store` object that contains references to 546*5c90c05cSAndroid Build Coastguard Worker /// arguments and can be implicitly converted to `printf_args`. 547*5c90c05cSAndroid Build Coastguard Worker template <typename Char = char, typename... T> 548*5c90c05cSAndroid Build Coastguard Worker inline auto make_printf_args(T&... args) 549*5c90c05cSAndroid Build Coastguard Worker -> decltype(fmt::make_format_args<basic_printf_context<Char>>(args...)) { 550*5c90c05cSAndroid Build Coastguard Worker return fmt::make_format_args<basic_printf_context<Char>>(args...); 551*5c90c05cSAndroid Build Coastguard Worker } 552*5c90c05cSAndroid Build Coastguard Worker 553*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct vprintf_args { 554*5c90c05cSAndroid Build Coastguard Worker using type = basic_format_args<basic_printf_context<Char>>; 555*5c90c05cSAndroid Build Coastguard Worker }; 556*5c90c05cSAndroid Build Coastguard Worker 557*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 558*5c90c05cSAndroid Build Coastguard Worker inline auto vsprintf(basic_string_view<Char> fmt, 559*5c90c05cSAndroid Build Coastguard Worker typename vprintf_args<Char>::type args) 560*5c90c05cSAndroid Build Coastguard Worker -> std::basic_string<Char> { 561*5c90c05cSAndroid Build Coastguard Worker auto buf = basic_memory_buffer<Char>(); 562*5c90c05cSAndroid Build Coastguard Worker detail::vprintf(buf, fmt, args); 563*5c90c05cSAndroid Build Coastguard Worker return {buf.data(), buf.size()}; 564*5c90c05cSAndroid Build Coastguard Worker } 565*5c90c05cSAndroid Build Coastguard Worker 566*5c90c05cSAndroid Build Coastguard Worker /** 567*5c90c05cSAndroid Build Coastguard Worker * Formats `args` according to specifications in `fmt` and returns the result 568*5c90c05cSAndroid Build Coastguard Worker * as as string. 569*5c90c05cSAndroid Build Coastguard Worker * 570*5c90c05cSAndroid Build Coastguard Worker * **Example**: 571*5c90c05cSAndroid Build Coastguard Worker * 572*5c90c05cSAndroid Build Coastguard Worker * std::string message = fmt::sprintf("The answer is %d", 42); 573*5c90c05cSAndroid Build Coastguard Worker */ 574*5c90c05cSAndroid Build Coastguard Worker template <typename S, typename... T, typename Char = detail::char_t<S>> 575*5c90c05cSAndroid Build Coastguard Worker inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> { 576*5c90c05cSAndroid Build Coastguard Worker return vsprintf(detail::to_string_view(fmt), 577*5c90c05cSAndroid Build Coastguard Worker fmt::make_format_args<basic_printf_context<Char>>(args...)); 578*5c90c05cSAndroid Build Coastguard Worker } 579*5c90c05cSAndroid Build Coastguard Worker 580*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 581*5c90c05cSAndroid Build Coastguard Worker inline auto vfprintf(std::FILE* f, basic_string_view<Char> fmt, 582*5c90c05cSAndroid Build Coastguard Worker typename vprintf_args<Char>::type args) -> int { 583*5c90c05cSAndroid Build Coastguard Worker auto buf = basic_memory_buffer<Char>(); 584*5c90c05cSAndroid Build Coastguard Worker detail::vprintf(buf, fmt, args); 585*5c90c05cSAndroid Build Coastguard Worker size_t size = buf.size(); 586*5c90c05cSAndroid Build Coastguard Worker return std::fwrite(buf.data(), sizeof(Char), size, f) < size 587*5c90c05cSAndroid Build Coastguard Worker ? -1 588*5c90c05cSAndroid Build Coastguard Worker : static_cast<int>(size); 589*5c90c05cSAndroid Build Coastguard Worker } 590*5c90c05cSAndroid Build Coastguard Worker 591*5c90c05cSAndroid Build Coastguard Worker /** 592*5c90c05cSAndroid Build Coastguard Worker * Formats `args` according to specifications in `fmt` and writes the output 593*5c90c05cSAndroid Build Coastguard Worker * to `f`. 594*5c90c05cSAndroid Build Coastguard Worker * 595*5c90c05cSAndroid Build Coastguard Worker * **Example**: 596*5c90c05cSAndroid Build Coastguard Worker * 597*5c90c05cSAndroid Build Coastguard Worker * fmt::fprintf(stderr, "Don't %s!", "panic"); 598*5c90c05cSAndroid Build Coastguard Worker */ 599*5c90c05cSAndroid Build Coastguard Worker template <typename S, typename... T, typename Char = detail::char_t<S>> 600*5c90c05cSAndroid Build Coastguard Worker inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { 601*5c90c05cSAndroid Build Coastguard Worker return vfprintf(f, detail::to_string_view(fmt), 602*5c90c05cSAndroid Build Coastguard Worker make_printf_args<Char>(args...)); 603*5c90c05cSAndroid Build Coastguard Worker } 604*5c90c05cSAndroid Build Coastguard Worker 605*5c90c05cSAndroid Build Coastguard Worker template <typename Char> 606*5c90c05cSAndroid Build Coastguard Worker FMT_DEPRECATED inline auto vprintf(basic_string_view<Char> fmt, 607*5c90c05cSAndroid Build Coastguard Worker typename vprintf_args<Char>::type args) 608*5c90c05cSAndroid Build Coastguard Worker -> int { 609*5c90c05cSAndroid Build Coastguard Worker return vfprintf(stdout, fmt, args); 610*5c90c05cSAndroid Build Coastguard Worker } 611*5c90c05cSAndroid Build Coastguard Worker 612*5c90c05cSAndroid Build Coastguard Worker /** 613*5c90c05cSAndroid Build Coastguard Worker * Formats `args` according to specifications in `fmt` and writes the output 614*5c90c05cSAndroid Build Coastguard Worker * to `stdout`. 615*5c90c05cSAndroid Build Coastguard Worker * 616*5c90c05cSAndroid Build Coastguard Worker * **Example**: 617*5c90c05cSAndroid Build Coastguard Worker * 618*5c90c05cSAndroid Build Coastguard Worker * fmt::printf("Elapsed time: %.2f seconds", 1.23); 619*5c90c05cSAndroid Build Coastguard Worker */ 620*5c90c05cSAndroid Build Coastguard Worker template <typename... T> 621*5c90c05cSAndroid Build Coastguard Worker inline auto printf(string_view fmt, const T&... args) -> int { 622*5c90c05cSAndroid Build Coastguard Worker return vfprintf(stdout, fmt, make_printf_args(args...)); 623*5c90c05cSAndroid Build Coastguard Worker } 624*5c90c05cSAndroid Build Coastguard Worker template <typename... T> 625*5c90c05cSAndroid Build Coastguard Worker FMT_DEPRECATED inline auto printf(basic_string_view<wchar_t> fmt, 626*5c90c05cSAndroid Build Coastguard Worker const T&... args) -> int { 627*5c90c05cSAndroid Build Coastguard Worker return vfprintf(stdout, fmt, make_printf_args<wchar_t>(args...)); 628*5c90c05cSAndroid Build Coastguard Worker } 629*5c90c05cSAndroid Build Coastguard Worker 630*5c90c05cSAndroid Build Coastguard Worker FMT_END_EXPORT 631*5c90c05cSAndroid Build Coastguard Worker FMT_END_NAMESPACE 632*5c90c05cSAndroid Build Coastguard Worker 633*5c90c05cSAndroid Build Coastguard Worker #endif // FMT_PRINTF_H_ 634