1 /* 2 Formatting library for C++ 3 4 Copyright (c) 2012 - 2016, Victor Zverovich 5 All rights reserved. 6 7 For the license information refer to format.h. 8 */ 9 10 #ifndef FMT_PRINTF_H_ 11 #define FMT_PRINTF_H_ 12 13 #include <algorithm> // std::fill_n 14 #include <limits> // std::numeric_limits 15 16 #include "ostream.h" 17 18 namespace fmt 19 { 20 namespace internal 21 { 22 23 // Checks if a value fits in int - used to avoid warnings about comparing 24 // signed and unsigned integers. 25 template <bool IsSigned> 26 struct IntChecker 27 { 28 template <typename T> fits_in_intIntChecker29 static bool fits_in_int(T value) 30 { 31 unsigned max = std::numeric_limits<int>::max(); 32 return value <= max; 33 } fits_in_intIntChecker34 static bool fits_in_int(bool) 35 { 36 return true; 37 } 38 }; 39 40 template <> 41 struct IntChecker<true> 42 { 43 template <typename T> 44 static bool fits_in_int(T value) 45 { 46 return value >= std::numeric_limits<int>::min() && 47 value <= std::numeric_limits<int>::max(); 48 } 49 static bool fits_in_int(int) 50 { 51 return true; 52 } 53 }; 54 55 class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> 56 { 57 public: 58 void report_unhandled_arg() 59 { 60 FMT_THROW(FormatError("precision is not integer")); 61 } 62 63 template <typename T> 64 int visit_any_int(T value) 65 { 66 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) 67 FMT_THROW(FormatError("number is too big")); 68 return static_cast<int>(value); 69 } 70 }; 71 72 // IsZeroInt::visit(arg) returns true iff arg is a zero integer. 73 class IsZeroInt : public ArgVisitor<IsZeroInt, bool> 74 { 75 public: 76 template <typename T> 77 bool visit_any_int(T value) 78 { 79 return value == 0; 80 } 81 }; 82 83 template <typename T, typename U> 84 struct is_same 85 { 86 enum { value = 0 }; 87 }; 88 89 template <typename T> 90 struct is_same<T, T> 91 { 92 enum { value = 1 }; 93 }; 94 95 // An argument visitor that converts an integer argument to T for printf, 96 // if T is an integral type. If T is void, the argument is converted to 97 // corresponding signed or unsigned type depending on the type specifier: 98 // 'd' and 'i' - signed, other - unsigned) 99 template <typename T = void> 100 class ArgConverter : public ArgVisitor<ArgConverter<T>, void> 101 { 102 private: 103 internal::Arg &arg_; 104 wchar_t type_; 105 106 FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); 107 108 public: 109 ArgConverter(internal::Arg &arg, wchar_t type) 110 : arg_(arg), type_(type) {} 111 112 void visit_bool(bool value) 113 { 114 if (type_ != 's') 115 visit_any_int(value); 116 } 117 118 template <typename U> 119 void visit_any_int(U value) 120 { 121 bool is_signed = type_ == 'd' || type_ == 'i'; 122 using internal::Arg; 123 typedef typename internal::Conditional< 124 is_same<T, void>::value, U, T>::type TargetType; 125 if (sizeof(TargetType) <= sizeof(int)) 126 { 127 // Extra casts are used to silence warnings. 128 if (is_signed) 129 { 130 arg_.type = Arg::INT; 131 arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); 132 } 133 else 134 { 135 arg_.type = Arg::UINT; 136 typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; 137 arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); 138 } 139 } 140 else 141 { 142 if (is_signed) 143 { 144 arg_.type = Arg::LONG_LONG; 145 // glibc's printf doesn't sign extend arguments of smaller types: 146 // std::printf("%lld", -42); // prints "4294967254" 147 // but we don't have to do the same because it's a UB. 148 arg_.long_long_value = static_cast<LongLong>(value); 149 } 150 else 151 { 152 arg_.type = Arg::ULONG_LONG; 153 arg_.ulong_long_value = 154 static_cast<typename internal::MakeUnsigned<U>::Type>(value); 155 } 156 } 157 } 158 }; 159 160 // Converts an integer argument to char for printf. 161 class CharConverter : public ArgVisitor<CharConverter, void> 162 { 163 private: 164 internal::Arg &arg_; 165 166 FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); 167 168 public: 169 explicit CharConverter(internal::Arg &arg) : arg_(arg) {} 170 171 template <typename T> 172 void visit_any_int(T value) 173 { 174 arg_.type = internal::Arg::CHAR; 175 arg_.int_value = static_cast<char>(value); 176 } 177 }; 178 179 // Checks if an argument is a valid printf width specifier and sets 180 // left alignment if it is negative. 181 class WidthHandler : public ArgVisitor<WidthHandler, unsigned> 182 { 183 private: 184 FormatSpec &spec_; 185 186 FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); 187 188 public: 189 explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} 190 191 void report_unhandled_arg() 192 { 193 FMT_THROW(FormatError("width is not integer")); 194 } 195 196 template <typename T> 197 unsigned visit_any_int(T value) 198 { 199 typedef typename internal::IntTraits<T>::MainType UnsignedType; 200 UnsignedType width = static_cast<UnsignedType>(value); 201 if (internal::is_negative(value)) 202 { 203 spec_.align_ = ALIGN_LEFT; 204 width = 0 - width; 205 } 206 unsigned int_max = std::numeric_limits<int>::max(); 207 if (width > int_max) 208 FMT_THROW(FormatError("number is too big")); 209 return static_cast<unsigned>(width); 210 } 211 }; 212 } // namespace internal 213 214 /** 215 \rst 216 A ``printf`` argument formatter based on the `curiously recurring template 217 pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_. 218 219 To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some 220 or all of the visit methods with the same signatures as the methods in 221 `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. 222 Pass the subclass as the *Impl* template parameter. When a formatting 223 function processes an argument, it will dispatch to a visit method 224 specific to the argument type. For example, if the argument type is 225 ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass 226 will be called. If the subclass doesn't contain a method with this signature, 227 then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its 228 superclass will be called. 229 \endrst 230 */ 231 template <typename Impl, typename Char> 232 class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> 233 { 234 private: 235 void write_null_pointer() 236 { 237 this->spec().type_ = 0; 238 this->write("(nil)"); 239 } 240 241 typedef internal::ArgFormatterBase<Impl, Char> Base; 242 243 public: 244 /** 245 \rst 246 Constructs an argument formatter object. 247 *writer* is a reference to the output writer and *spec* contains format 248 specifier information for standard argument types. 249 \endrst 250 */ 251 BasicPrintfArgFormatter(BasicWriter<Char> &writer, FormatSpec &spec) 252 : internal::ArgFormatterBase<Impl, Char>(writer, spec) {} 253 254 /** Formats an argument of type ``bool``. */ 255 void visit_bool(bool value) 256 { 257 FormatSpec &fmt_spec = this->spec(); 258 if (fmt_spec.type_ != 's') 259 return this->visit_any_int(value); 260 fmt_spec.type_ = 0; 261 this->write(value); 262 } 263 264 /** Formats a character. */ 265 void visit_char(int value) 266 { 267 const FormatSpec &fmt_spec = this->spec(); 268 BasicWriter<Char> &w = this->writer(); 269 if (fmt_spec.type_ && fmt_spec.type_ != 'c') 270 w.write_int(value, fmt_spec); 271 typedef typename BasicWriter<Char>::CharPtr CharPtr; 272 CharPtr out = CharPtr(); 273 if (fmt_spec.width_ > 1) 274 { 275 Char fill = ' '; 276 out = w.grow_buffer(fmt_spec.width_); 277 if (fmt_spec.align_ != ALIGN_LEFT) 278 { 279 std::fill_n(out, fmt_spec.width_ - 1, fill); 280 out += fmt_spec.width_ - 1; 281 } 282 else 283 { 284 std::fill_n(out + 1, fmt_spec.width_ - 1, fill); 285 } 286 } 287 else 288 { 289 out = w.grow_buffer(1); 290 } 291 *out = static_cast<Char>(value); 292 } 293 294 /** Formats a null-terminated C string. */ 295 void visit_cstring(const char *value) 296 { 297 if (value) 298 Base::visit_cstring(value); 299 else if (this->spec().type_ == 'p') 300 write_null_pointer(); 301 else 302 this->write("(null)"); 303 } 304 305 /** Formats a pointer. */ 306 void visit_pointer(const void *value) 307 { 308 if (value) 309 return Base::visit_pointer(value); 310 this->spec().type_ = 0; 311 write_null_pointer(); 312 } 313 314 /** Formats an argument of a custom (user-defined) type. */ 315 void visit_custom(internal::Arg::CustomValue c) 316 { 317 BasicFormatter<Char> formatter(ArgList(), this->writer()); 318 const Char format_str[] = { '}', 0 }; 319 const Char *format = format_str; 320 c.format(&formatter, c.value, &format); 321 } 322 }; 323 324 /** The default printf argument formatter. */ 325 template <typename Char> 326 class PrintfArgFormatter 327 : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char> 328 { 329 public: 330 /** Constructs an argument formatter object. */ 331 PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) 332 : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {} 333 }; 334 335 /** This template formats data and writes the output to a writer. */ 336 template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> > 337 class PrintfFormatter : private internal::FormatterBase 338 { 339 private: 340 BasicWriter<Char> &writer_; 341 342 void parse_flags(FormatSpec &spec, const Char *&s); 343 344 // Returns the argument with specified index or, if arg_index is equal 345 // to the maximum unsigned value, the next argument. 346 internal::Arg get_arg( 347 const Char *s, 348 unsigned arg_index = (std::numeric_limits<unsigned>::max)()); 349 350 // Parses argument index, flags and width and returns the argument index. 351 unsigned parse_header(const Char *&s, FormatSpec &spec); 352 353 public: 354 /** 355 \rst 356 Constructs a ``PrintfFormatter`` object. References to the arguments and 357 the writer are stored in the formatter object so make sure they have 358 appropriate lifetimes. 359 \endrst 360 */ 361 explicit PrintfFormatter(const ArgList &args, BasicWriter<Char> &w) 362 : FormatterBase(args), writer_(w) {} 363 364 /** Formats stored arguments and writes the output to the writer. */ 365 FMT_API void format(BasicCStringRef<Char> format_str); 366 }; 367 368 template <typename Char, typename AF> 369 void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) 370 { 371 for (;;) 372 { 373 switch (*s++) 374 { 375 case '-': 376 spec.align_ = ALIGN_LEFT; 377 break; 378 case '+': 379 spec.flags_ |= SIGN_FLAG | PLUS_FLAG; 380 break; 381 case '0': 382 spec.fill_ = '0'; 383 break; 384 case ' ': 385 spec.flags_ |= SIGN_FLAG; 386 break; 387 case '#': 388 spec.flags_ |= HASH_FLAG; 389 break; 390 default: 391 --s; 392 return; 393 } 394 } 395 } 396 397 template <typename Char, typename AF> 398 internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, 399 unsigned arg_index) 400 { 401 (void)s; 402 const char *error = 0; 403 internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? 404 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); 405 if (error) 406 FMT_THROW(FormatError(!*s ? "invalid format string" : error)); 407 return arg; 408 } 409 410 template <typename Char, typename AF> 411 unsigned PrintfFormatter<Char, AF>::parse_header( 412 const Char *&s, FormatSpec &spec) 413 { 414 unsigned arg_index = std::numeric_limits<unsigned>::max(); 415 Char c = *s; 416 if (c >= '0' && c <= '9') 417 { 418 // Parse an argument index (if followed by '$') or a width possibly 419 // preceded with '0' flag(s). 420 unsigned value = internal::parse_nonnegative_int(s); 421 if (*s == '$') // value is an argument index 422 { 423 ++s; 424 arg_index = value; 425 } 426 else 427 { 428 if (c == '0') 429 spec.fill_ = '0'; 430 if (value != 0) 431 { 432 // Nonzero value means that we parsed width and don't need to 433 // parse it or flags again, so return now. 434 spec.width_ = value; 435 return arg_index; 436 } 437 } 438 } 439 parse_flags(spec, s); 440 // Parse width. 441 if (*s >= '0' && *s <= '9') 442 { 443 spec.width_ = internal::parse_nonnegative_int(s); 444 } 445 else if (*s == '*') 446 { 447 ++s; 448 spec.width_ = internal::WidthHandler(spec).visit(get_arg(s)); 449 } 450 return arg_index; 451 } 452 453 template <typename Char, typename AF> 454 void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) 455 { 456 const Char *start = format_str.c_str(); 457 const Char *s = start; 458 while (*s) 459 { 460 Char c = *s++; 461 if (c != '%') continue; 462 if (*s == c) 463 { 464 write(writer_, start, s); 465 start = ++s; 466 continue; 467 } 468 write(writer_, start, s - 1); 469 470 FormatSpec spec; 471 spec.align_ = ALIGN_RIGHT; 472 473 // Parse argument index, flags and width. 474 unsigned arg_index = parse_header(s, spec); 475 476 // Parse precision. 477 if (*s == '.') 478 { 479 ++s; 480 if ('0' <= *s && *s <= '9') 481 { 482 spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s)); 483 } 484 else if (*s == '*') 485 { 486 ++s; 487 spec.precision_ = internal::PrecisionHandler().visit(get_arg(s)); 488 } 489 } 490 491 using internal::Arg; 492 Arg arg = get_arg(s, arg_index); 493 if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg)) 494 spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG); 495 if (spec.fill_ == '0') 496 { 497 if (arg.type <= Arg::LAST_NUMERIC_TYPE) 498 spec.align_ = ALIGN_NUMERIC; 499 else 500 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. 501 } 502 503 // Parse length and convert the argument to the required type. 504 using internal::ArgConverter; 505 switch (*s++) 506 { 507 case 'h': 508 if (*s == 'h') 509 ArgConverter<signed char>(arg, *++s).visit(arg); 510 else 511 ArgConverter<short>(arg, *s).visit(arg); 512 break; 513 case 'l': 514 if (*s == 'l') 515 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); 516 else 517 ArgConverter<long>(arg, *s).visit(arg); 518 break; 519 case 'j': 520 ArgConverter<intmax_t>(arg, *s).visit(arg); 521 break; 522 case 'z': 523 ArgConverter<std::size_t>(arg, *s).visit(arg); 524 break; 525 case 't': 526 ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); 527 break; 528 case 'L': 529 // printf produces garbage when 'L' is omitted for long double, no 530 // need to do the same. 531 break; 532 default: 533 --s; 534 ArgConverter<void>(arg, *s).visit(arg); 535 } 536 537 // Parse type. 538 if (!*s) 539 FMT_THROW(FormatError("invalid format string")); 540 spec.type_ = static_cast<char>(*s++); 541 if (arg.type <= Arg::LAST_INTEGER_TYPE) 542 { 543 // Normalize type. 544 switch (spec.type_) 545 { 546 case 'i': 547 case 'u': 548 spec.type_ = 'd'; 549 break; 550 case 'c': 551 // TODO: handle wchar_t 552 internal::CharConverter(arg).visit(arg); 553 break; 554 } 555 } 556 557 start = s; 558 559 // Format argument. 560 AF(writer_, spec).visit(arg); 561 } 562 write(writer_, start, s); 563 } 564 565 template <typename Char> 566 void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) 567 { 568 PrintfFormatter<Char>(args, w).format(format); 569 } 570 571 /** 572 \rst 573 Formats arguments and returns the result as a string. 574 575 **Example**:: 576 577 std::string message = fmt::sprintf("The answer is %d", 42); 578 \endrst 579 */ 580 inline std::string sprintf(CStringRef format, ArgList args) 581 { 582 MemoryWriter w; 583 printf(w, format, args); 584 return w.str(); 585 } 586 FMT_VARIADIC(std::string, sprintf, CStringRef) 587 588 inline std::wstring sprintf(WCStringRef format, ArgList args) 589 { 590 WMemoryWriter w; 591 printf(w, format, args); 592 return w.str(); 593 } 594 FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) 595 596 /** 597 \rst 598 Prints formatted data to the file *f*. 599 600 **Example**:: 601 602 fmt::fprintf(stderr, "Don't %s!", "panic"); 603 \endrst 604 */ 605 FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); 606 FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) 607 608 /** 609 \rst 610 Prints formatted data to ``stdout``. 611 612 **Example**:: 613 614 fmt::printf("Elapsed time: %.2f seconds", 1.23); 615 \endrst 616 */ 617 inline int printf(CStringRef format, ArgList args) 618 { 619 return fprintf(stdout, format, args); 620 } 621 FMT_VARIADIC(int, printf, CStringRef) 622 623 /** 624 \rst 625 Prints formatted data to the stream *os*. 626 627 **Example**:: 628 629 fprintf(cerr, "Don't %s!", "panic"); 630 \endrst 631 */ 632 inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) 633 { 634 MemoryWriter w; 635 printf(w, format_str, args); 636 internal::write(os, w); 637 return static_cast<int>(w.size()); 638 } 639 FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) 640 } // namespace fmt 641 642 #endif // FMT_PRINTF_H_