• 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 {
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_