format.cc
Go to the documentation of this file.
1 /*
2  Formatting library for C++
3 
4  Copyright (c) 2012 - 2016, Victor Zverovich
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions are met:
9 
10  1. Redistributions of source code must retain the above copyright notice, this
11  list of conditions and the following disclaimer.
12  2. Redistributions in binary form must reproduce the above copyright notice,
13  this list of conditions and the following disclaimer in the documentation
14  and/or other materials provided with the distribution.
15 
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "format.h"
29 
30 #include <string.h>
31 
32 #include <cctype>
33 #include <cerrno>
34 #include <climits>
35 #include <cmath>
36 #include <cstdarg>
37 #include <cstddef> // for std::ptrdiff_t
38 
39 #if defined(_WIN32) && defined(__MINGW32__)
40 # include <cstring>
41 #endif
42 
43 #if FMT_USE_WINDOWS_H
44 # if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
45 # include <windows.h>
46 # else
47 # define NOMINMAX
48 # include <windows.h>
49 # undef NOMINMAX
50 # endif
51 #endif
52 
53 using fmt::internal::Arg;
54 
55 #if FMT_EXCEPTIONS
56 # define FMT_TRY try
57 # define FMT_CATCH(x) catch (x)
58 #else
59 # define FMT_TRY if (true)
60 # define FMT_CATCH(x) if (false)
61 #endif
62 
63 #ifdef _MSC_VER
64 # pragma warning(push)
65 # pragma warning(disable: 4127) // conditional expression is constant
66 # pragma warning(disable: 4702) // unreachable code
67 // Disable deprecation warning for strerror. The latter is not called but
68 // MSVC fails to detect it.
69 # pragma warning(disable: 4996)
70 #endif
71 
72 // Dummy implementations of strerror_r and strerror_s called if corresponding
73 // system functions are not available.
74 static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
75  return fmt::internal::Null<>();
76 }
77 static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
78  return fmt::internal::Null<>();
79 }
80 
81 namespace fmt {
82 
86 
87 namespace {
88 
89 #ifndef _MSC_VER
90 # define FMT_SNPRINTF snprintf
91 #else // _MSC_VER
92 inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
93  va_list args;
94  va_start(args, format);
95  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
96  va_end(args);
97  return result;
98 }
99 # define FMT_SNPRINTF fmt_snprintf
100 #endif // _MSC_VER
101 
102 #if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
103 # define FMT_SWPRINTF snwprintf
104 #else
105 # define FMT_SWPRINTF swprintf
106 #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
107 
108 // Checks if a value fits in int - used to avoid warnings about comparing
109 // signed and unsigned integers.
110 template <bool IsSigned>
111 struct IntChecker {
112  template <typename T>
113  static bool fits_in_int(T value) {
114  unsigned max = INT_MAX;
115  return value <= max;
116  }
117  static bool fits_in_int(bool) { return true; }
118 };
119 
120 template <>
121 struct IntChecker<true> {
122  template <typename T>
123  static bool fits_in_int(T value) {
124  return value >= INT_MIN && value <= INT_MAX;
125  }
126  static bool fits_in_int(int) { return true; }
127 };
128 
129 const char RESET_COLOR[] = "\x1b[0m";
130 
131 typedef void (*FormatFunc)(Writer &, int, StringRef);
132 
133 // Portable thread-safe version of strerror.
134 // Sets buffer to point to a string describing the error code.
135 // This can be either a pointer to a string stored in buffer,
136 // or a pointer to some static immutable string.
137 // Returns one of the following values:
138 // 0 - success
139 // ERANGE - buffer is not large enough to store the error message
140 // other - failure
141 // Buffer should be at least of size 1.
142 int safe_strerror(
143  int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
144  FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
145 
146  class StrError {
147  private:
148  int error_code_;
149  char *&buffer_;
150  std::size_t buffer_size_;
151 
152  // A noop assignment operator to avoid bogus warnings.
153  void operator=(const StrError &) {}
154 
155  // Handle the result of XSI-compliant version of strerror_r.
156  int handle(int result) {
157  // glibc versions before 2.13 return result in errno.
158  return result == -1 ? errno : result;
159  }
160 
161  // Handle the result of GNU-specific version of strerror_r.
162  int handle(char *message) {
163  // If the buffer is full then the message is probably truncated.
164  if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
165  return ERANGE;
166  buffer_ = message;
167  return 0;
168  }
169 
170  // Handle the case when strerror_r is not available.
171  int handle(internal::Null<>) {
172  return fallback(strerror_s(buffer_, buffer_size_, error_code_));
173  }
174 
175  // Fallback to strerror_s when strerror_r is not available.
176  int fallback(int result) {
177  // If the buffer is full then the message is probably truncated.
178  return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
179  ERANGE : result;
180  }
181 
182  // Fallback to strerror if strerror_r and strerror_s are not available.
183  int fallback(internal::Null<>) {
184  errno = 0;
185  buffer_ = strerror(error_code_);
186  return errno;
187  }
188 
189  public:
190  StrError(int err_code, char *&buf, std::size_t buf_size)
191  : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
192 
193  int run() {
194  strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
195  return handle(strerror_r(error_code_, buffer_, buffer_size_));
196  }
197  };
198  return StrError(error_code, buffer, buffer_size).run();
199 }
200 
201 void format_error_code(Writer &out, int error_code,
203  // Report error code making sure that the output fits into
204  // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
205  // bad_alloc.
206  out.clear();
207  static const char SEP[] = ": ";
208  static const char ERROR_STR[] = "error ";
209  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
210  std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
211  typedef internal::IntTraits<int>::MainType MainType;
212  MainType abs_value = static_cast<MainType>(error_code);
213  if (internal::is_negative(error_code)) {
214  abs_value = 0 - abs_value;
215  ++error_code_size;
216  }
217  error_code_size += internal::count_digits(abs_value);
218  if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
219  out << message << SEP;
220  out << ERROR_STR << error_code;
221  assert(out.size() <= internal::INLINE_BUFFER_SIZE);
222 }
223 
224 void report_error(FormatFunc func, int error_code,
225  StringRef message) FMT_NOEXCEPT {
226  MemoryWriter full_message;
227  func(full_message, error_code, message);
228  // Use Writer::data instead of Writer::c_str to avoid potential memory
229  // allocation.
230  std::fwrite(full_message.data(), full_message.size(), 1, stderr);
231  std::fputc('\n', stderr);
232 }
233 
234 // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
235 class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
236  public:
237  template <typename T>
238  bool visit_any_int(T value) { return value == 0; }
239 };
240 
241 // Checks if an argument is a valid printf width specifier and sets
242 // left alignment if it is negative.
243 class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
244  private:
245  FormatSpec &spec_;
246 
247  FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
248 
249  public:
250  explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
251 
252  void report_unhandled_arg() {
253  FMT_THROW(FormatError("width is not integer"));
254  }
255 
256  template <typename T>
257  unsigned visit_any_int(T value) {
258  typedef typename internal::IntTraits<T>::MainType UnsignedType;
259  UnsignedType width = static_cast<UnsignedType>(value);
260  if (internal::is_negative(value)) {
261  spec_.align_ = ALIGN_LEFT;
262  width = 0 - width;
263  }
264  if (width > INT_MAX)
265  FMT_THROW(FormatError("number is too big"));
266  return static_cast<unsigned>(width);
267  }
268 };
269 
270 class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
271  public:
272  void report_unhandled_arg() {
273  FMT_THROW(FormatError("precision is not integer"));
274  }
275 
276  template <typename T>
277  int visit_any_int(T value) {
278  if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
279  FMT_THROW(FormatError("number is too big"));
280  return static_cast<int>(value);
281  }
282 };
283 
284 template <typename T, typename U>
285 struct is_same {
286  enum { value = 0 };
287 };
288 
289 template <typename T>
290 struct is_same<T, T> {
291  enum { value = 1 };
292 };
293 
294 // An argument visitor that converts an integer argument to T for printf,
295 // if T is an integral type. If T is void, the argument is converted to
296 // corresponding signed or unsigned type depending on the type specifier:
297 // 'd' and 'i' - signed, other - unsigned)
298 template <typename T = void>
299 class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
300  private:
301  internal::Arg &arg_;
302  wchar_t type_;
303 
304  FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
305 
306  public:
307  ArgConverter(internal::Arg &arg, wchar_t type)
308  : arg_(arg), type_(type) {}
309 
310  void visit_bool(bool value) {
311  if (type_ != 's')
312  visit_any_int(value);
313  }
314 
315  template <typename U>
316  void visit_any_int(U value) {
317  bool is_signed = type_ == 'd' || type_ == 'i';
318  using internal::Arg;
319  typedef typename internal::Conditional<
320  is_same<T, void>::value, U, T>::type TargetType;
321  if (sizeof(TargetType) <= sizeof(int)) {
322  // Extra casts are used to silence warnings.
323  if (is_signed) {
324  arg_.type = Arg::INT;
325  arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
326  } else {
327  arg_.type = Arg::UINT;
328  typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
329  arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
330  }
331  } else {
332  if (is_signed) {
333  arg_.type = Arg::LONG_LONG;
334  // glibc's printf doesn't sign extend arguments of smaller types:
335  // std::printf("%lld", -42); // prints "4294967254"
336  // but we don't have to do the same because it's a UB.
337  arg_.long_long_value = static_cast<LongLong>(value);
338  } else {
339  arg_.type = Arg::ULONG_LONG;
340  arg_.ulong_long_value =
341  static_cast<typename internal::MakeUnsigned<U>::Type>(value);
342  }
343  }
344  }
345 };
346 
347 // Converts an integer argument to char for printf.
348 class CharConverter : public ArgVisitor<CharConverter, void> {
349  private:
350  internal::Arg &arg_;
351 
352  FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
353 
354  public:
355  explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
356 
357  template <typename T>
358  void visit_any_int(T value) {
359  arg_.type = internal::Arg::CHAR;
360  arg_.int_value = static_cast<char>(value);
361  }
362 };
363 } // namespace
364 
365 namespace internal {
366 
367 template <typename Char>
369  public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
370 
372  this->spec().type_ = 0;
373  this->write("(nil)");
374  }
375 
377 
378  public:
381 
382  void visit_bool(bool value) {
383  FormatSpec &fmt_spec = this->spec();
384  if (fmt_spec.type_ != 's')
385  return this->visit_any_int(value);
386  fmt_spec.type_ = 0;
387  this->write(value);
388  }
389 
390  void visit_char(int value) {
391  const FormatSpec &fmt_spec = this->spec();
392  BasicWriter<Char> &w = this->writer();
393  if (fmt_spec.type_ && fmt_spec.type_ != 'c')
394  w.write_int(value, fmt_spec);
395  typedef typename BasicWriter<Char>::CharPtr CharPtr;
396  CharPtr out = CharPtr();
397  if (fmt_spec.width_ > 1) {
398  Char fill = ' ';
399  out = w.grow_buffer(fmt_spec.width_);
400  if (fmt_spec.align_ != ALIGN_LEFT) {
401  std::fill_n(out, fmt_spec.width_ - 1, fill);
402  out += fmt_spec.width_ - 1;
403  } else {
404  std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
405  }
406  } else {
407  out = w.grow_buffer(1);
408  }
409  *out = static_cast<Char>(value);
410  }
411 
412  void visit_cstring(const char *value) {
413  if (value)
414  Base::visit_cstring(value);
415  else if (this->spec().type_ == 'p')
416  write_null_pointer();
417  else
418  this->write("(null)");
419  }
420 
421  void visit_pointer(const void *value) {
422  if (value)
423  return Base::visit_pointer(value);
424  this->spec().type_ = 0;
425  write_null_pointer();
426  }
427 
429  BasicFormatter<Char> formatter(ArgList(), this->writer());
430  const Char format_str[] = {'}', 0};
431  const Char *format = format_str;
432  c.format(&formatter, c.value, &format);
433  }
434 };
435 } // namespace internal
436 } // namespace fmt
437 
439  int err_code, CStringRef format_str, ArgList args) {
440  error_code_ = err_code;
441  MemoryWriter w;
442  internal::format_system_error(w, err_code, format(format_str, args));
443  std::runtime_error &base = *this;
444  base = std::runtime_error(w.str());
445 }
446 
447 template <typename T>
449  char *buffer, std::size_t size, const char *format,
450  unsigned width, int precision, T value) {
451  if (width == 0) {
452  return precision < 0 ?
453  FMT_SNPRINTF(buffer, size, format, value) :
454  FMT_SNPRINTF(buffer, size, format, precision, value);
455  }
456  return precision < 0 ?
457  FMT_SNPRINTF(buffer, size, format, width, value) :
458  FMT_SNPRINTF(buffer, size, format, width, precision, value);
459 }
460 
461 template <typename T>
463  wchar_t *buffer, std::size_t size, const wchar_t *format,
464  unsigned width, int precision, T value) {
465  if (width == 0) {
466  return precision < 0 ?
467  FMT_SWPRINTF(buffer, size, format, value) :
468  FMT_SWPRINTF(buffer, size, format, precision, value);
469  }
470  return precision < 0 ?
471  FMT_SWPRINTF(buffer, size, format, width, value) :
472  FMT_SWPRINTF(buffer, size, format, width, precision, value);
473 }
474 
475 template <typename T>
477  "0001020304050607080910111213141516171819"
478  "2021222324252627282930313233343536373839"
479  "4041424344454647484950515253545556575859"
480  "6061626364656667686970717273747576777879"
481  "8081828384858687888990919293949596979899";
482 
483 #define FMT_POWERS_OF_10(factor) \
484  factor * 10, \
485  factor * 100, \
486  factor * 1000, \
487  factor * 10000, \
488  factor * 100000, \
489  factor * 1000000, \
490  factor * 10000000, \
491  factor * 100000000, \
492  factor * 1000000000
493 
494 template <typename T>
496  0, FMT_POWERS_OF_10(1)
497 };
498 
499 template <typename T>
501  0,
502  FMT_POWERS_OF_10(1),
503  FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
504  // Multiply several constants instead of using a single long long constant
505  // to avoid warnings about C++98 not supporting long long.
506  fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
507 };
508 
509 FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
510  (void)type;
511  if (std::isprint(static_cast<unsigned char>(code))) {
513  fmt::format("unknown format code '{}' for {}", code, type)));
514  }
516  fmt::format("unknown format code '\\x{:02x}' for {}",
517  static_cast<unsigned>(code), type)));
518 }
519 
520 #if FMT_USE_WINDOWS_H
521 
522 FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
523  static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
524  if (s.size() > INT_MAX)
525  FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
526  int s_size = static_cast<int>(s.size());
527  int length = MultiByteToWideChar(
528  CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
529  if (length == 0)
530  FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
531  buffer_.resize(length + 1);
532  length = MultiByteToWideChar(
533  CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
534  if (length == 0)
535  FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
536  buffer_[length] = 0;
537 }
538 
539 FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
540  if (int error_code = convert(s)) {
541  FMT_THROW(WindowsError(error_code,
542  "cannot convert string from UTF-16 to UTF-8"));
543  }
544 }
545 
547  if (s.size() > INT_MAX)
548  return ERROR_INVALID_PARAMETER;
549  int s_size = static_cast<int>(s.size());
550  int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
551  if (length == 0)
552  return GetLastError();
553  buffer_.resize(length + 1);
554  length = WideCharToMultiByte(
555  CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
556  if (length == 0)
557  return GetLastError();
558  buffer_[length] = 0;
559  return 0;
560 }
561 
562 FMT_FUNC void fmt::WindowsError::init(
563  int err_code, CStringRef format_str, ArgList args) {
564  error_code_ = err_code;
565  MemoryWriter w;
566  internal::format_windows_error(w, err_code, format(format_str, args));
567  std::runtime_error &base = *this;
568  base = std::runtime_error(w.str());
569 }
570 
571 FMT_FUNC void fmt::internal::format_windows_error(
572  fmt::Writer &out, int error_code,
573  fmt::StringRef message) FMT_NOEXCEPT {
574  FMT_TRY {
576  buffer.resize(INLINE_BUFFER_SIZE);
577  for (;;) {
578  wchar_t *system_message = &buffer[0];
579  int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
580  0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
581  system_message, static_cast<uint32_t>(buffer.size()), 0);
582  if (result != 0) {
583  UTF16ToUTF8 utf8_message;
584  if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
585  out << message << ": " << utf8_message;
586  return;
587  }
588  break;
589  }
590  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
591  break; // Can't get error message, report error code instead.
592  buffer.resize(buffer.size() * 2);
593  }
594  } FMT_CATCH(...) {}
595  fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
596 }
597 
598 #endif // FMT_USE_WINDOWS_H
599 
601  fmt::Writer &out, int error_code,
602  fmt::StringRef message) FMT_NOEXCEPT {
603  FMT_TRY {
605  buffer.resize(INLINE_BUFFER_SIZE);
606  for (;;) {
607  char *system_message = &buffer[0];
608  int result = safe_strerror(error_code, system_message, buffer.size());
609  if (result == 0) {
610  out << message << ": " << system_message;
611  return;
612  }
613  if (result != ERANGE)
614  break; // Can't get error message, report error code instead.
615  buffer.resize(buffer.size() * 2);
616  }
617  } FMT_CATCH(...) {}
618  fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
619 }
620 
621 template <typename Char>
623  if (!map_.empty())
624  return;
626  const NamedArg *named_arg = 0;
627  bool use_values =
629  if (use_values) {
630  for (unsigned i = 0;/*nothing*/; ++i) {
631  internal::Arg::Type arg_type = args.type(i);
632  switch (arg_type) {
633  case internal::Arg::NONE:
634  return;
636  named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
637  map_.push_back(Pair(named_arg->name, *named_arg));
638  break;
639  default:
640  /*nothing*/;
641  }
642  }
643  return;
644  }
645  for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
646  internal::Arg::Type arg_type = args.type(i);
647  if (arg_type == internal::Arg::NAMED_ARG) {
648  named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
649  map_.push_back(Pair(named_arg->name, *named_arg));
650  }
651  }
652  for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
653  switch (args.args_[i].type) {
654  case internal::Arg::NONE:
655  return;
657  named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
658  map_.push_back(Pair(named_arg->name, *named_arg));
659  break;
660  default:
661  /*nothing*/;
662  }
663  }
664 }
665 
666 template <typename Char>
668  FMT_THROW(std::runtime_error("buffer overflow"));
669 }
670 
672  unsigned arg_index, const char *&error) {
673  Arg arg = args_[arg_index];
674  switch (arg.type) {
675  case Arg::NONE:
676  error = "argument index out of range";
677  break;
678  case Arg::NAMED_ARG:
679  arg = *static_cast<const internal::Arg*>(arg.pointer);
680  break;
681  default:
682  /*nothing*/;
683  }
684  return arg;
685 }
686 
687 template <typename Char>
689  FormatSpec &spec, const Char *&s) {
690  for (;;) {
691  switch (*s++) {
692  case '-':
693  spec.align_ = ALIGN_LEFT;
694  break;
695  case '+':
696  spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
697  break;
698  case '0':
699  spec.fill_ = '0';
700  break;
701  case ' ':
702  spec.flags_ |= SIGN_FLAG;
703  break;
704  case '#':
705  spec.flags_ |= HASH_FLAG;
706  break;
707  default:
708  --s;
709  return;
710  }
711  }
712 }
713 
714 template <typename Char>
716  const Char *s, unsigned arg_index) {
717  (void)s;
718  const char *error = 0;
719  Arg arg = arg_index == UINT_MAX ?
720  next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
721  if (error)
722  FMT_THROW(FormatError(!*s ? "invalid format string" : error));
723  return arg;
724 }
725 
726 template <typename Char>
728  const Char *&s, FormatSpec &spec) {
729  unsigned arg_index = UINT_MAX;
730  Char c = *s;
731  if (c >= '0' && c <= '9') {
732  // Parse an argument index (if followed by '$') or a width possibly
733  // preceded with '0' flag(s).
734  unsigned value = parse_nonnegative_int(s);
735  if (*s == '$') { // value is an argument index
736  ++s;
737  arg_index = value;
738  } else {
739  if (c == '0')
740  spec.fill_ = '0';
741  if (value != 0) {
742  // Nonzero value means that we parsed width and don't need to
743  // parse it or flags again, so return now.
744  spec.width_ = value;
745  return arg_index;
746  }
747  }
748  }
749  parse_flags(spec, s);
750  // Parse width.
751  if (*s >= '0' && *s <= '9') {
752  spec.width_ = parse_nonnegative_int(s);
753  } else if (*s == '*') {
754  ++s;
755  spec.width_ = WidthHandler(spec).visit(get_arg(s));
756  }
757  return arg_index;
758 }
759 
760 template <typename Char>
762  BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
763  const Char *start = format_str.c_str();
764  const Char *s = start;
765  while (*s) {
766  Char c = *s++;
767  if (c != '%') continue;
768  if (*s == c) {
769  write(writer, start, s);
770  start = ++s;
771  continue;
772  }
773  write(writer, start, s - 1);
774 
775  FormatSpec spec;
776  spec.align_ = ALIGN_RIGHT;
777 
778  // Parse argument index, flags and width.
779  unsigned arg_index = parse_header(s, spec);
780 
781  // Parse precision.
782  if (*s == '.') {
783  ++s;
784  if ('0' <= *s && *s <= '9') {
785  spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
786  } else if (*s == '*') {
787  ++s;
788  spec.precision_ = PrecisionHandler().visit(get_arg(s));
789  }
790  }
791 
792  Arg arg = get_arg(s, arg_index);
793  if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
794  spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
795  if (spec.fill_ == '0') {
796  if (arg.type <= Arg::LAST_NUMERIC_TYPE)
797  spec.align_ = ALIGN_NUMERIC;
798  else
799  spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
800  }
801 
802  // Parse length and convert the argument to the required type.
803  switch (*s++) {
804  case 'h':
805  if (*s == 'h')
806  ArgConverter<signed char>(arg, *++s).visit(arg);
807  else
808  ArgConverter<short>(arg, *s).visit(arg);
809  break;
810  case 'l':
811  if (*s == 'l')
812  ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
813  else
814  ArgConverter<long>(arg, *s).visit(arg);
815  break;
816  case 'j':
817  ArgConverter<intmax_t>(arg, *s).visit(arg);
818  break;
819  case 'z':
820  ArgConverter<std::size_t>(arg, *s).visit(arg);
821  break;
822  case 't':
823  ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
824  break;
825  case 'L':
826  // printf produces garbage when 'L' is omitted for long double, no
827  // need to do the same.
828  break;
829  default:
830  --s;
831  ArgConverter<void>(arg, *s).visit(arg);
832  }
833 
834  // Parse type.
835  if (!*s)
836  FMT_THROW(FormatError("invalid format string"));
837  spec.type_ = static_cast<char>(*s++);
838  if (arg.type <= Arg::LAST_INTEGER_TYPE) {
839  // Normalize type.
840  switch (spec.type_) {
841  case 'i': case 'u':
842  spec.type_ = 'd';
843  break;
844  case 'c':
845  // TODO: handle wchar_t
846  CharConverter(arg).visit(arg);
847  break;
848  }
849  }
850 
851  start = s;
852 
853  // Format argument.
854  internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
855  }
856  write(writer, start, s);
857 }
858 
860  int error_code, fmt::StringRef message) FMT_NOEXCEPT {
861  // 'fmt::' is for bcc32.
862  fmt::report_error(internal::format_system_error, error_code, message);
863 }
864 
865 #if FMT_USE_WINDOWS_H
866 FMT_FUNC void fmt::report_windows_error(
867  int error_code, fmt::StringRef message) FMT_NOEXCEPT {
868  // 'fmt::' is for bcc32.
869  fmt::report_error(internal::format_windows_error, error_code, message);
870 }
871 #endif
872 
873 FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
874  MemoryWriter w;
875  w.write(format_str, args);
876  std::fwrite(w.data(), 1, w.size(), f);
877 }
878 
879 FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
880  print(stdout, format_str, args);
881 }
882 
884  char escape[] = "\x1b[30m";
885  escape[3] = static_cast<char>('0' + c);
886  std::fputs(escape, stdout);
887  print(format, args);
888  std::fputs(RESET_COLOR, stdout);
889 }
890 
891 FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
892  MemoryWriter w;
893  printf(w, format, args);
894  std::size_t size = w.size();
895  return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
896 }
897 
898 #ifndef FMT_HEADER_ONLY
899 
900 template struct fmt::internal::BasicData<void>;
901 
902 // Explicit instantiations for char.
903 
904 template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
905 
906 template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
907 
910 
912  char *buffer, std::size_t size, const char *format,
913  unsigned width, int precision, double value);
914 
915 template int fmt::internal::CharTraits<char>::format_float(
916  char *buffer, std::size_t size, const char *format,
917  unsigned width, int precision, long double value);
918 
919 // Explicit instantiations for wchar_t.
920 
921 template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
922 
923 template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
924 
926  BasicWriter<wchar_t> &writer, WCStringRef format);
927 
929  wchar_t *buffer, std::size_t size, const wchar_t *format,
930  unsigned width, int precision, double value);
931 
932 template int fmt::internal::CharTraits<wchar_t>::format_float(
933  wchar_t *buffer, std::size_t size, const wchar_t *format,
934  unsigned width, int precision, long double value);
935 
936 #endif // FMT_HEADER_ONLY
937 
938 #ifdef _MSC_VER
939 # pragma warning(pop)
940 #endif
internal::Arg & arg_
Definition: format.cc:301
#define FMT_NOEXCEPT
Definition: format.h:190
bool is_negative(T value)
Definition: format.h:944
#define FMT_ASSERT(condition, message)
Definition: format.h:240
Alignment align_
Definition: format.h:1894
const Char * data() const
Definition: format.h:501
FMT_API void format_system_error(fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT
Definition: format.cc:600
ROSCPP_DECL void start()
void resize(std::size_t new_size)
Definition: format.h:706
wchar_t fill_
Definition: format.h:1877
FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args)
Definition: format.cc:873
void visit_pointer(const void *value)
Definition: format.cc:421
FMT_API void report_unknown_type(char code, const char *type)
Definition: format.cc:509
FormatSpec & spec_
Definition: format.cc:245
static fmt::internal::Null strerror_s(char *, std::size_t,...)
Definition: format.cc:77
FMT_API void format(BasicWriter< Char > &writer, BasicCStringRef< Char > format_str)
Definition: format.cc:761
void write(BasicCStringRef< Char > format, ArgList args)
Definition: format.h:2918
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3686
XmlRpcServer s
static fmt::internal::Null strerror_r(int, char *,...)
Definition: format.cc:74
unsigned width_
Definition: format.h:1874
const Char * c_str() const
Definition: format.h:594
FMT_GCC_EXTENSION typedef unsigned long long ULongLong
Definition: format.h:419
void init(int err_code, CStringRef format_str, ArgList args)
Definition: format.cc:438
std::basic_string< Char > str() const
Definition: format.h:2888
const void * pointer
Definition: format.h:1204
BasicStringRef< Char > name
Definition: format.h:1554
unsigned parse_nonnegative_int(const Char *&s)
Definition: format.h:4088
const Char * data() const FMT_NOEXCEPT
Definition: format.h:2866
#define FMT_THROW(x)
Definition: format.h:172
void visit_custom(Arg::CustomValue c)
Definition: format.cc:428
FMT_API void grow(std::size_t size)
Definition: format.cc:667
Yes & convert(fmt::ULongLong)
FMT_API void print_colored(Color c, CStringRef format, ArgList args)
Definition: format.cc:883
bool flag(unsigned f) const
Definition: format.h:1937
#define FMT_SNPRINTF
Definition: format.cc:90
ArgFormatterBase< PrintfArgFormatter< Char >, Char > Base
Definition: format.cc:376
bool write(ros_opcua_srvs::Write::Request &req, ros_opcua_srvs::Write::Response &res)
BasicStringRef< char > StringRef
Definition: format.h:548
BasicMemoryWriter< char > MemoryWriter
Definition: format.h:3558
#define FMT_FUNC
Definition: format.h:4498
CharPtr grow_buffer(std::size_t n)
Definition: format.h:2753
message
Definition: server.py:50
#define FMT_SWPRINTF
Definition: format.cc:105
internal::PairMatcher< FirstMatcher, SecondMatcher > Pair(FirstMatcher first_matcher, SecondMatcher second_matcher)
handle
Definition: client.py:58
BasicWriter< char > Writer
Definition: format.h:426
std::size_t size() const
Definition: format.h:692
std::size_t size() const
Definition: format.h:2857
FMT_API void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT
Definition: format.cc:859
std::size_t size() const
Definition: format.h:507
const internal::Arg * args_
Definition: format.h:1590
#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: format.h:222
void write_int(T value, Spec spec)
Definition: format.h:3186
internal::CharTraits< Char >::CharPtr CharPtr
Definition: format.h:2731
void visit_bool(bool value)
Definition: format.cc:382
wchar_t type_
Definition: format.cc:302
Color
Definition: format.h:3667
internal::NamedArg< char > arg(StringRef name, const T &arg)
Definition: format.h:3918
FMT_API void init(const ArgList &args)
Definition: format.cc:622
void parse_flags(FormatSpec &spec, const Char *&s)
Definition: format.cc:688
unsigned count_digits(uint64_t n)
Definition: format.h:1007
unsigned parse_header(const Char *&s, FormatSpec &spec)
Definition: format.cc:727
PrintfArgFormatter(BasicWriter< Char > &w, FormatSpec &s)
Definition: format.cc:379
Arg get_arg(const Char *s, unsigned arg_index=(std::numeric_limits< unsigned >::max)())
Definition: format.cc:715
FMT_API Arg do_get_arg(unsigned arg_index, const char *&error)
Definition: format.cc:671
#define FMT_POWERS_OF_10(factor)
Definition: format.cc:483
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args)
Definition: format.cc:891
Definition: format.cc:81
unsigned flags_
Definition: format.h:1929
#define FMT_CATCH(x)
Definition: format.cc:57
Arg get_arg(unsigned arg_index, const char *&error)
Definition: format.h:2300
void visit_cstring(const char *value)
Definition: format.cc:412
const internal::Value * values_
Definition: format.h:1589
#define FMT_TRY
Definition: format.cc:56
internal::Arg::Type type(unsigned index) const
Definition: format.h:1593
FMT_GCC_EXTENSION typedef long long LongLong
Definition: format.h:418
void printf(BasicWriter< Char > &w, BasicCStringRef< Char > format, ArgList args)
Definition: format.h:3723


ros_opcua_impl_freeopcua
Author(s): Denis Štogl
autogenerated on Tue Jan 19 2021 03:06:04