bitz-server  2.0.1
printf.h
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 {
26  template<typename T>
27  static bool fits_in_int(T value)
28  {
29  unsigned max = std::numeric_limits<int>::max();
30  return value <= max;
31  }
32  static bool fits_in_int(bool)
33  {
34  return true;
35  }
36 };
37 
38 template<>
39 struct IntChecker<true>
40 {
41  template<typename T>
42  static bool fits_in_int(T value)
43  {
44  return value >= std::numeric_limits<int>::min() && value <= std::numeric_limits<int>::max();
45  }
46  static bool fits_in_int(int)
47  {
48  return true;
49  }
50 };
51 
52 class PrecisionHandler : public ArgVisitor<PrecisionHandler, int>
53 {
54 public:
55  void report_unhandled_arg()
56  {
57  FMT_THROW(FormatError("precision is not integer"));
58  }
59 
60  template<typename T>
61  int visit_any_int(T value)
62  {
63  if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
64  FMT_THROW(FormatError("number is too big"));
65  return static_cast<int>(value);
66  }
67 };
68 
69 // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
70 class IsZeroInt : public ArgVisitor<IsZeroInt, bool>
71 {
72 public:
73  template<typename T>
74  bool visit_any_int(T value)
75  {
76  return value == 0;
77  }
78 };
79 
80 // returns the default type for format specific "%s"
81 class DefaultType : public ArgVisitor<DefaultType, char>
82 {
83 public:
84  char visit_char(int)
85  {
86  return 'c';
87  }
88 
89  char visit_bool(bool)
90  {
91  return 's';
92  }
93 
94  char visit_pointer(const void *)
95  {
96  return 'p';
97  }
98 
99  template<typename T>
100  char visit_any_int(T)
101  {
102  return 'd';
103  }
104 
105  template<typename T>
106  char visit_any_double(T)
107  {
108  return 'g';
109  }
110 
111  char visit_unhandled_arg()
112  {
113  return 's';
114  }
115 };
116 
117 template<typename T, typename U>
118 struct is_same
119 {
120  enum
121  {
122  value = 0
123  };
124 };
125 
126 template<typename T>
127 struct is_same<T, T>
128 {
129  enum
130  {
131  value = 1
132  };
133 };
134 
135 // An argument visitor that converts an integer argument to T for printf,
136 // if T is an integral type. If T is void, the argument is converted to
137 // corresponding signed or unsigned type depending on the type specifier:
138 // 'd' and 'i' - signed, other - unsigned)
139 template<typename T = void>
140 class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
141 {
142 private:
143  internal::Arg &arg_;
144  wchar_t type_;
145 
146  FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
147 
148 public:
149  ArgConverter(internal::Arg &arg, wchar_t type)
150  : arg_(arg)
151  , type_(type)
152  {
153  }
154 
155  void visit_bool(bool value)
156  {
157  if (type_ != 's')
158  visit_any_int(value);
159  }
160 
161  void visit_char(int value)
162  {
163  if (type_ != 's')
164  visit_any_int(value);
165  }
166 
167  template<typename U>
168  void visit_any_int(U value)
169  {
170  bool is_signed = type_ == 'd' || type_ == 'i';
171  if (type_ == 's')
172  {
173  is_signed = std::numeric_limits<U>::is_signed;
174  }
175 
176  using internal::Arg;
177  typedef typename internal::Conditional<is_same<T, void>::value, U, T>::type TargetType;
178  if (const_check(sizeof(TargetType) <= sizeof(int)))
179  {
180  // Extra casts are used to silence warnings.
181  if (is_signed)
182  {
183  arg_.type = Arg::INT;
184  arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
185  }
186  else
187  {
188  arg_.type = Arg::UINT;
189  typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
190  arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
191  }
192  }
193  else
194  {
195  if (is_signed)
196  {
197  arg_.type = Arg::LONG_LONG;
198  // glibc's printf doesn't sign extend arguments of smaller types:
199  // std::printf("%lld", -42); // prints "4294967254"
200  // but we don't have to do the same because it's a UB.
201  arg_.long_long_value = static_cast<LongLong>(value);
202  }
203  else
204  {
205  arg_.type = Arg::ULONG_LONG;
206  arg_.ulong_long_value = static_cast<typename internal::MakeUnsigned<U>::Type>(value);
207  }
208  }
209  }
210 };
211 
212 // Converts an integer argument to char for printf.
213 class CharConverter : public ArgVisitor<CharConverter, void>
214 {
215 private:
216  internal::Arg &arg_;
217 
218  FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
219 
220 public:
221  explicit CharConverter(internal::Arg &arg)
222  : arg_(arg)
223  {
224  }
225 
226  template<typename T>
227  void visit_any_int(T value)
228  {
229  arg_.type = internal::Arg::CHAR;
230  arg_.int_value = static_cast<char>(value);
231  }
232 };
233 
234 // Checks if an argument is a valid printf width specifier and sets
235 // left alignment if it is negative.
236 class WidthHandler : public ArgVisitor<WidthHandler, unsigned>
237 {
238 private:
239  FormatSpec &spec_;
240 
241  FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
242 
243 public:
244  explicit WidthHandler(FormatSpec &spec)
245  : spec_(spec)
246  {
247  }
248 
249  void report_unhandled_arg()
250  {
251  FMT_THROW(FormatError("width is not integer"));
252  }
253 
254  template<typename T>
255  unsigned visit_any_int(T value)
256  {
257  typedef typename internal::IntTraits<T>::MainType UnsignedType;
258  UnsignedType width = static_cast<UnsignedType>(value);
259  if (internal::is_negative(value))
260  {
261  spec_.align_ = ALIGN_LEFT;
262  width = 0 - width;
263  }
264  unsigned int_max = std::numeric_limits<int>::max();
265  if (width > int_max)
266  FMT_THROW(FormatError("number is too big"));
267  return static_cast<unsigned>(width);
268  }
269 };
270 } // namespace internal
271 
289 template<typename Impl, typename Char, typename Spec>
290 class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec>
291 {
292 private:
293  void write_null_pointer()
294  {
295  this->spec().type_ = 0;
296  this->write("(nil)");
297  }
298 
300 
301 public:
310  : internal::ArgFormatterBase<Impl, Char, Spec>(w, s)
311  {
312  }
313 
315  void visit_bool(bool value)
316  {
317  Spec &fmt_spec = this->spec();
318  if (fmt_spec.type_ != 's')
319  return this->visit_any_int(value);
320  fmt_spec.type_ = 0;
321  this->write(value);
322  }
323 
325  void visit_char(int value)
326  {
327  const Spec &fmt_spec = this->spec();
328  BasicWriter<Char> &w = this->writer();
329  if (fmt_spec.type_ && fmt_spec.type_ != 'c')
330  w.write_int(value, fmt_spec);
331  typedef typename BasicWriter<Char>::CharPtr CharPtr;
332  CharPtr out = CharPtr();
333  if (fmt_spec.width_ > 1)
334  {
335  Char fill = ' ';
336  out = w.grow_buffer(fmt_spec.width_);
337  if (fmt_spec.align_ != ALIGN_LEFT)
338  {
339  std::fill_n(out, fmt_spec.width_ - 1, fill);
340  out += fmt_spec.width_ - 1;
341  }
342  else
343  {
344  std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
345  }
346  }
347  else
348  {
349  out = w.grow_buffer(1);
350  }
351  *out = static_cast<Char>(value);
352  }
353 
355  void visit_cstring(const char *value)
356  {
357  if (value)
358  Base::visit_cstring(value);
359  else if (this->spec().type_ == 'p')
360  write_null_pointer();
361  else
362  this->write("(null)");
363  }
364 
366  void visit_pointer(const void *value)
367  {
368  if (value)
369  return Base::visit_pointer(value);
370  this->spec().type_ = 0;
371  write_null_pointer();
372  }
373 
376  {
377  BasicFormatter<Char> formatter(ArgList(), this->writer());
378  const Char format_str[] = {'}', 0};
379  const Char *format = format_str;
380  c.format(&formatter, c.value, &format);
381  }
382 };
383 
385 template<typename Char>
386 class PrintfArgFormatter : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>
387 {
388 public:
392  {
393  }
394 };
395 
397 template<typename Char, typename ArgFormatter = PrintfArgFormatter<Char>>
399 {
400 private:
401  BasicWriter<Char> &writer_;
402 
403  void parse_flags(FormatSpec &spec, const Char *&s);
404 
405  // Returns the argument with specified index or, if arg_index is equal
406  // to the maximum unsigned value, the next argument.
407  internal::Arg get_arg(const Char *s, unsigned arg_index = (std::numeric_limits<unsigned>::max)());
408 
409  // Parses argument index, flags and width and returns the argument index.
410  unsigned parse_header(const Char *&s, FormatSpec &spec);
411 
412 public:
420  explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
421  : FormatterBase(al)
422  , writer_(w)
423  {
424  }
425 
427  void format(BasicCStringRef<Char> format_str);
428 };
429 
430 template<typename Char, typename AF>
431 void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
432 {
433  for (;;)
434  {
435  switch (*s++)
436  {
437  case '-':
438  spec.align_ = ALIGN_LEFT;
439  break;
440  case '+':
441  spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
442  break;
443  case '0':
444  spec.fill_ = '0';
445  break;
446  case ' ':
447  spec.flags_ |= SIGN_FLAG;
448  break;
449  case '#':
450  spec.flags_ |= HASH_FLAG;
451  break;
452  default:
453  --s;
454  return;
455  }
456  }
457 }
458 
459 template<typename Char, typename AF>
460 internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index)
461 {
462  (void)s;
463  const char *error = FMT_NULL;
464  internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
465  if (error)
466  FMT_THROW(FormatError(!*s ? "invalid format string" : error));
467  return arg;
468 }
469 
470 template<typename Char, typename AF>
471 unsigned PrintfFormatter<Char, AF>::parse_header(const Char *&s, FormatSpec &spec)
472 {
473  unsigned arg_index = std::numeric_limits<unsigned>::max();
474  Char c = *s;
475  if (c >= '0' && c <= '9')
476  {
477  // Parse an argument index (if followed by '$') or a width possibly
478  // preceded with '0' flag(s).
479  unsigned value = internal::parse_nonnegative_int(s);
480  if (*s == '$') // value is an argument index
481  {
482  ++s;
483  arg_index = value;
484  }
485  else
486  {
487  if (c == '0')
488  spec.fill_ = '0';
489  if (value != 0)
490  {
491  // Nonzero value means that we parsed width and don't need to
492  // parse it or flags again, so return now.
493  spec.width_ = value;
494  return arg_index;
495  }
496  }
497  }
498  parse_flags(spec, s);
499  // Parse width.
500  if (*s >= '0' && *s <= '9')
501  {
502  spec.width_ = internal::parse_nonnegative_int(s);
503  }
504  else if (*s == '*')
505  {
506  ++s;
507  spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
508  }
509  return arg_index;
510 }
511 
512 template<typename Char, typename AF>
514 {
515  const Char *start = format_str.c_str();
516  const Char *s = start;
517  while (*s)
518  {
519  Char c = *s++;
520  if (c != '%')
521  continue;
522  if (*s == c)
523  {
524  write(writer_, start, s);
525  start = ++s;
526  continue;
527  }
528  write(writer_, start, s - 1);
529 
530  FormatSpec spec;
531  spec.align_ = ALIGN_RIGHT;
532 
533  // Parse argument index, flags and width.
534  unsigned arg_index = parse_header(s, spec);
535 
536  // Parse precision.
537  if (*s == '.')
538  {
539  ++s;
540  if ('0' <= *s && *s <= '9')
541  {
542  spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
543  }
544  else if (*s == '*')
545  {
546  ++s;
547  spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
548  }
549  else
550  {
551  spec.precision_ = 0;
552  }
553  }
554 
555  using internal::Arg;
556  Arg arg = get_arg(s, arg_index);
557  if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
558  spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
559  if (spec.fill_ == '0')
560  {
561  if (arg.type <= Arg::LAST_NUMERIC_TYPE)
562  spec.align_ = ALIGN_NUMERIC;
563  else
564  spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
565  }
566 
567  // Parse length and convert the argument to the required type.
569  switch (*s++)
570  {
571  case 'h':
572  if (*s == 'h')
573  ArgConverter<signed char>(arg, *++s).visit(arg);
574  else
575  ArgConverter<short>(arg, *s).visit(arg);
576  break;
577  case 'l':
578  if (*s == 'l')
579  ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
580  else
581  ArgConverter<long>(arg, *s).visit(arg);
582  break;
583  case 'j':
584  ArgConverter<intmax_t>(arg, *s).visit(arg);
585  break;
586  case 'z':
587  ArgConverter<std::size_t>(arg, *s).visit(arg);
588  break;
589  case 't':
590  ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
591  break;
592  case 'L':
593  // printf produces garbage when 'L' is omitted for long double, no
594  // need to do the same.
595  break;
596  default:
597  --s;
598  ArgConverter<void>(arg, *s).visit(arg);
599  }
600 
601  // Parse type.
602  if (!*s)
603  FMT_THROW(FormatError("invalid format string"));
604  spec.type_ = static_cast<char>(*s++);
605 
606  if (spec.type_ == 's')
607  {
608  // set the format type to the default if 's' is specified
609  spec.type_ = internal::DefaultType().visit(arg);
610  }
611 
612  if (arg.type <= Arg::LAST_INTEGER_TYPE)
613  {
614  // Normalize type.
615  switch (spec.type_)
616  {
617  case 'i':
618  case 'u':
619  spec.type_ = 'd';
620  break;
621  case 'c':
622  // TODO: handle wchar_t
623  internal::CharConverter(arg).visit(arg);
624  break;
625  }
626  }
627 
628  start = s;
629 
630  // Format argument.
631  AF(writer_, spec).visit(arg);
632  }
633  write(writer_, start, s);
634 }
635 
636 inline void printf(Writer &w, CStringRef format, ArgList args)
637 {
638  PrintfFormatter<char>(args, w).format(format);
639 }
640 FMT_VARIADIC(void, printf, Writer &, CStringRef)
641 
642 inline void printf(WWriter &w, WCStringRef format, ArgList args)
643 {
644  PrintfFormatter<wchar_t>(args, w).format(format);
645 }
646 FMT_VARIADIC(void, printf, WWriter &, WCStringRef)
647 
648 
657 inline std::string sprintf(CStringRef format, ArgList args)
658 {
659  MemoryWriter w;
660  printf(w, format, args);
661  return w.str();
662 }
663 FMT_VARIADIC(std::string, sprintf, CStringRef)
664 
665 inline std::wstring sprintf(WCStringRef format, ArgList args)
666 {
667  WMemoryWriter w;
668  printf(w, format, args);
669  return w.str();
670 }
671 FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
672 
673 
682 FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
683 FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
684 
685 
694 inline int printf(CStringRef format, ArgList args)
695 {
696  return fprintf(stdout, format, args);
697 }
698 FMT_VARIADIC(int, printf, CStringRef)
699 
700 
709 inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
710 {
711  MemoryWriter w;
712  printf(w, format_str, args);
713  internal::write(os, w);
714  return static_cast<int>(w.size());
715 }
716 FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
717 } // namespace fmt
718 
719 #ifdef FMT_HEADER_ONLY
720 #include "printf.cc"
721 #endif
722 
723 #endif // FMT_PRINTF_H_
Definition: format.h:2275
void format(BasicCStringRef< Char > format_str)
Definition: printf.h:513
Definition: format.h:1876
void visit_char(int value)
Definition: printf.h:325
Definition: format.h:705
Definition: format.h:1136
Definition: printf.h:70
Definition: printf.h:118
Definition: printf.h:236
Definition: format.h:1360
Definition: format.h:1408
Definition: printf.h:52
Definition: format.h:1994
void visit_bool(bool value)
Definition: printf.h:315
Definition: printf.h:140
void visit_cstring(const char *value)
Definition: printf.h:355
PrintfFormatter(const ArgList &al, BasicWriter< Char > &w)
Definition: printf.h:420
std::size_t size() const
Definition: format.h:3271
PrintfArgFormatter(BasicWriter< Char > &w, FormatSpec &s)
Definition: printf.h:390
Definition: printf.h:24
Definition: printf.h:398
const Char * c_str() const
Definition: format.h:729
Definition: format.h:2686
std::basic_string< Char > str() const
Definition: format.h:3302
void visit_pointer(const void *value)
Definition: printf.h:366
Definition: format.h:529
BasicPrintfArgFormatter(BasicWriter< Char > &w, Spec &s)
Definition: printf.h:309
Definition: printf.h:81
Definition: format.h:2548
Definition: format.h:3924
Definition: format.h:739
Result visit(const Arg &arg)
Definition: format.h:2108
Definition: format.h:526
Definition: format.cc:84
Definition: printf.h:213
void visit_custom(internal::Arg::CustomValue c)
Definition: printf.h:375
Definition: format.h:1517
Definition: printf.h:386
Definition: format.h:515