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.

640 lines
20 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_MODULE_EXPORT_BEGIN
  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. FMT_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. FMT_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. using format_specs = basic_format_specs<Char>;
  163. format_specs& specs_;
  164. public:
  165. explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
  166. template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
  167. unsigned operator()(T value) {
  168. auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
  169. if (detail::is_negative(value)) {
  170. specs_.align = align::left;
  171. width = 0 - width;
  172. }
  173. unsigned int_max = max_value<int>();
  174. if (width > int_max) FMT_THROW(format_error("number is too big"));
  175. return static_cast<unsigned>(width);
  176. }
  177. template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
  178. unsigned operator()(T) {
  179. FMT_THROW(format_error("width is not integer"));
  180. return 0;
  181. }
  182. };
  183. // The ``printf`` argument formatter.
  184. template <typename OutputIt, typename Char>
  185. class printf_arg_formatter : public arg_formatter<Char> {
  186. private:
  187. using base = arg_formatter<Char>;
  188. using context_type = basic_printf_context<OutputIt, Char>;
  189. using format_specs = basic_format_specs<Char>;
  190. context_type& context_;
  191. OutputIt write_null_pointer(bool is_string = false) {
  192. auto s = this->specs;
  193. s.type = presentation_type::none;
  194. return write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
  195. }
  196. public:
  197. printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx)
  198. : base{iter, s, locale_ref()}, context_(ctx) {}
  199. OutputIt operator()(monostate value) { return base::operator()(value); }
  200. template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
  201. OutputIt operator()(T value) {
  202. // MSVC2013 fails to compile separate overloads for bool and Char so use
  203. // std::is_same instead.
  204. if (std::is_same<T, Char>::value) {
  205. format_specs fmt_specs = this->specs;
  206. if (fmt_specs.type != presentation_type::none &&
  207. fmt_specs.type != presentation_type::chr) {
  208. return (*this)(static_cast<int>(value));
  209. }
  210. fmt_specs.sign = sign::none;
  211. fmt_specs.alt = false;
  212. fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
  213. // align::numeric needs to be overwritten here since the '0' flag is
  214. // ignored for non-numeric types
  215. if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
  216. fmt_specs.align = align::right;
  217. return write<Char>(this->out, static_cast<Char>(value), fmt_specs);
  218. }
  219. return base::operator()(value);
  220. }
  221. template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
  222. OutputIt operator()(T value) {
  223. return base::operator()(value);
  224. }
  225. /** Formats a null-terminated C string. */
  226. OutputIt operator()(const char* value) {
  227. if (value) return base::operator()(value);
  228. return write_null_pointer(this->specs.type != presentation_type::pointer);
  229. }
  230. /** Formats a null-terminated wide C string. */
  231. OutputIt operator()(const wchar_t* value) {
  232. if (value) return base::operator()(value);
  233. return write_null_pointer(this->specs.type != presentation_type::pointer);
  234. }
  235. OutputIt operator()(basic_string_view<Char> value) {
  236. return base::operator()(value);
  237. }
  238. /** Formats a pointer. */
  239. OutputIt operator()(const void* value) {
  240. return value ? base::operator()(value) : write_null_pointer();
  241. }
  242. /** Formats an argument of a custom (user-defined) type. */
  243. OutputIt operator()(typename basic_format_arg<context_type>::handle handle) {
  244. auto parse_ctx =
  245. basic_printf_parse_context<Char>(basic_string_view<Char>());
  246. handle.format(parse_ctx, context_);
  247. return this->out;
  248. }
  249. };
  250. template <typename Char>
  251. void parse_flags(basic_format_specs<Char>& specs, const Char*& it,
  252. const Char* end) {
  253. for (; it != end; ++it) {
  254. switch (*it) {
  255. case '-':
  256. specs.align = align::left;
  257. break;
  258. case '+':
  259. specs.sign = sign::plus;
  260. break;
  261. case '0':
  262. specs.fill[0] = '0';
  263. break;
  264. case ' ':
  265. if (specs.sign != sign::plus) {
  266. specs.sign = sign::space;
  267. }
  268. break;
  269. case '#':
  270. specs.alt = true;
  271. break;
  272. default:
  273. return;
  274. }
  275. }
  276. }
  277. template <typename Char, typename GetArg>
  278. int parse_header(const Char*& it, const Char* end,
  279. basic_format_specs<Char>& specs, GetArg get_arg) {
  280. int arg_index = -1;
  281. Char c = *it;
  282. if (c >= '0' && c <= '9') {
  283. // Parse an argument index (if followed by '$') or a width possibly
  284. // preceded with '0' flag(s).
  285. int value = parse_nonnegative_int(it, end, -1);
  286. if (it != end && *it == '$') { // value is an argument index
  287. ++it;
  288. arg_index = value != -1 ? value : max_value<int>();
  289. } else {
  290. if (c == '0') specs.fill[0] = '0';
  291. if (value != 0) {
  292. // Nonzero value means that we parsed width and don't need to
  293. // parse it or flags again, so return now.
  294. if (value == -1) FMT_THROW(format_error("number is too big"));
  295. specs.width = value;
  296. return arg_index;
  297. }
  298. }
  299. }
  300. parse_flags(specs, it, end);
  301. // Parse width.
  302. if (it != end) {
  303. if (*it >= '0' && *it <= '9') {
  304. specs.width = parse_nonnegative_int(it, end, -1);
  305. if (specs.width == -1) FMT_THROW(format_error("number is too big"));
  306. } else if (*it == '*') {
  307. ++it;
  308. specs.width = static_cast<int>(visit_format_arg(
  309. detail::printf_width_handler<Char>(specs), get_arg(-1)));
  310. }
  311. }
  312. return arg_index;
  313. }
  314. template <typename Char, typename Context>
  315. void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
  316. basic_format_args<Context> args) {
  317. using OutputIt = buffer_appender<Char>;
  318. auto out = OutputIt(buf);
  319. auto context = basic_printf_context<OutputIt, Char>(out, args);
  320. auto parse_ctx = basic_printf_parse_context<Char>(format);
  321. // Returns the argument with specified index or, if arg_index is -1, the next
  322. // argument.
  323. auto get_arg = [&](int arg_index) {
  324. if (arg_index < 0)
  325. arg_index = parse_ctx.next_arg_id();
  326. else
  327. parse_ctx.check_arg_id(--arg_index);
  328. return detail::get_arg(context, arg_index);
  329. };
  330. const Char* start = parse_ctx.begin();
  331. const Char* end = parse_ctx.end();
  332. auto it = start;
  333. while (it != end) {
  334. if (!detail::find<false, Char>(it, end, '%', it)) {
  335. it = end; // detail::find leaves it == nullptr if it doesn't find '%'
  336. break;
  337. }
  338. Char c = *it++;
  339. if (it != end && *it == c) {
  340. out = detail::write(
  341. out, basic_string_view<Char>(start, detail::to_unsigned(it - start)));
  342. start = ++it;
  343. continue;
  344. }
  345. out = detail::write(out, basic_string_view<Char>(
  346. start, detail::to_unsigned(it - 1 - start)));
  347. basic_format_specs<Char> specs;
  348. specs.align = align::right;
  349. // Parse argument index, flags and width.
  350. int arg_index = parse_header(it, end, specs, get_arg);
  351. if (arg_index == 0) parse_ctx.on_error("argument not found");
  352. // Parse precision.
  353. if (it != end && *it == '.') {
  354. ++it;
  355. c = it != end ? *it : 0;
  356. if ('0' <= c && c <= '9') {
  357. specs.precision = parse_nonnegative_int(it, end, 0);
  358. } else if (c == '*') {
  359. ++it;
  360. specs.precision = static_cast<int>(
  361. visit_format_arg(detail::printf_precision_handler(), get_arg(-1)));
  362. } else {
  363. specs.precision = 0;
  364. }
  365. }
  366. auto arg = get_arg(arg_index);
  367. // For d, i, o, u, x, and X conversion specifiers, if a precision is
  368. // specified, the '0' flag is ignored
  369. if (specs.precision >= 0 && arg.is_integral())
  370. specs.fill[0] =
  371. ' '; // Ignore '0' flag for non-numeric types or if '-' present.
  372. if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {
  373. auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
  374. auto str_end = str + specs.precision;
  375. auto nul = std::find(str, str_end, Char());
  376. arg = detail::make_arg<basic_printf_context<OutputIt, Char>>(
  377. basic_string_view<Char>(
  378. str, detail::to_unsigned(nul != str_end ? nul - str
  379. : specs.precision)));
  380. }
  381. if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))
  382. specs.alt = false;
  383. if (specs.fill[0] == '0') {
  384. if (arg.is_arithmetic() && specs.align != align::left)
  385. specs.align = align::numeric;
  386. else
  387. specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-'
  388. // flag is also present.
  389. }
  390. // Parse length and convert the argument to the required type.
  391. c = it != end ? *it++ : 0;
  392. Char t = it != end ? *it : 0;
  393. using detail::convert_arg;
  394. switch (c) {
  395. case 'h':
  396. if (t == 'h') {
  397. ++it;
  398. t = it != end ? *it : 0;
  399. convert_arg<signed char>(arg, t);
  400. } else {
  401. convert_arg<short>(arg, t);
  402. }
  403. break;
  404. case 'l':
  405. if (t == 'l') {
  406. ++it;
  407. t = it != end ? *it : 0;
  408. convert_arg<long long>(arg, t);
  409. } else {
  410. convert_arg<long>(arg, t);
  411. }
  412. break;
  413. case 'j':
  414. convert_arg<intmax_t>(arg, t);
  415. break;
  416. case 'z':
  417. convert_arg<size_t>(arg, t);
  418. break;
  419. case 't':
  420. convert_arg<std::ptrdiff_t>(arg, t);
  421. break;
  422. case 'L':
  423. // printf produces garbage when 'L' is omitted for long double, no
  424. // need to do the same.
  425. break;
  426. default:
  427. --it;
  428. convert_arg<void>(arg, c);
  429. }
  430. // Parse type.
  431. if (it == end) FMT_THROW(format_error("invalid format string"));
  432. char type = static_cast<char>(*it++);
  433. if (arg.is_integral()) {
  434. // Normalize type.
  435. switch (type) {
  436. case 'i':
  437. case 'u':
  438. type = 'd';
  439. break;
  440. case 'c':
  441. visit_format_arg(
  442. detail::char_converter<basic_printf_context<OutputIt, Char>>(arg),
  443. arg);
  444. break;
  445. }
  446. }
  447. specs.type = parse_presentation_type(type);
  448. if (specs.type == presentation_type::none)
  449. parse_ctx.on_error("invalid type specifier");
  450. start = it;
  451. // Format argument.
  452. out = visit_format_arg(
  453. detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg);
  454. }
  455. detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
  456. }
  457. FMT_END_DETAIL_NAMESPACE
  458. template <typename Char>
  459. using basic_printf_context_t =
  460. basic_printf_context<detail::buffer_appender<Char>, Char>;
  461. using printf_context = basic_printf_context_t<char>;
  462. using wprintf_context = basic_printf_context_t<wchar_t>;
  463. using printf_args = basic_format_args<printf_context>;
  464. using wprintf_args = basic_format_args<wprintf_context>;
  465. /**
  466. \rst
  467. Constructs an `~fmt::format_arg_store` object that contains references to
  468. arguments and can be implicitly converted to `~fmt::printf_args`.
  469. \endrst
  470. */
  471. template <typename... T>
  472. inline auto make_printf_args(const T&... args)
  473. -> format_arg_store<printf_context, T...> {
  474. return {args...};
  475. }
  476. /**
  477. \rst
  478. Constructs an `~fmt::format_arg_store` object that contains references to
  479. arguments and can be implicitly converted to `~fmt::wprintf_args`.
  480. \endrst
  481. */
  482. template <typename... T>
  483. inline auto make_wprintf_args(const T&... args)
  484. -> format_arg_store<wprintf_context, T...> {
  485. return {args...};
  486. }
  487. template <typename S, typename Char = char_t<S>>
  488. inline auto vsprintf(
  489. const S& fmt,
  490. basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
  491. -> std::basic_string<Char> {
  492. basic_memory_buffer<Char> buffer;
  493. vprintf(buffer, detail::to_string_view(fmt), args);
  494. return to_string(buffer);
  495. }
  496. /**
  497. \rst
  498. Formats arguments and returns the result as a string.
  499. **Example**::
  500. std::string message = fmt::sprintf("The answer is %d", 42);
  501. \endrst
  502. */
  503. template <typename S, typename... T,
  504. typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
  505. inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
  506. using context = basic_printf_context_t<Char>;
  507. return vsprintf(detail::to_string_view(fmt),
  508. fmt::make_format_args<context>(args...));
  509. }
  510. template <typename S, typename Char = char_t<S>>
  511. inline auto vfprintf(
  512. std::FILE* f, const S& fmt,
  513. basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
  514. -> int {
  515. basic_memory_buffer<Char> buffer;
  516. vprintf(buffer, detail::to_string_view(fmt), args);
  517. size_t size = buffer.size();
  518. return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
  519. ? -1
  520. : static_cast<int>(size);
  521. }
  522. /**
  523. \rst
  524. Prints formatted data to the file *f*.
  525. **Example**::
  526. fmt::fprintf(stderr, "Don't %s!", "panic");
  527. \endrst
  528. */
  529. template <typename S, typename... T, typename Char = char_t<S>>
  530. inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
  531. using context = basic_printf_context_t<Char>;
  532. return vfprintf(f, detail::to_string_view(fmt),
  533. fmt::make_format_args<context>(args...));
  534. }
  535. template <typename S, typename Char = char_t<S>>
  536. inline auto vprintf(
  537. const S& fmt,
  538. basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
  539. -> int {
  540. return vfprintf(stdout, detail::to_string_view(fmt), args);
  541. }
  542. /**
  543. \rst
  544. Prints formatted data to ``stdout``.
  545. **Example**::
  546. fmt::printf("Elapsed time: %.2f seconds", 1.23);
  547. \endrst
  548. */
  549. template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>
  550. inline auto printf(const S& fmt, const T&... args) -> int {
  551. return vprintf(
  552. detail::to_string_view(fmt),
  553. fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
  554. }
  555. FMT_MODULE_EXPORT_END
  556. FMT_END_NAMESPACE
  557. #endif // FMT_PRINTF_H_