xref: /aosp_15_r20/external/fmtlib/include/fmt/printf.h (revision 5c90c05cd622c0a81b57953a4d343e0e489f2e08)
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