Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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