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