You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

679 lines
21 KiB

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