Home | History | Annotate | Download | only in fmt
      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 
     83 FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
     84 FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
     85 FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
     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 const char RESET_COLOR[] = "\x1b[0m";
    109 
    110 typedef void (*FormatFunc)(Writer &, int, StringRef);
    111 
    112 // Portable thread-safe version of strerror.
    113 // Sets buffer to point to a string describing the error code.
    114 // This can be either a pointer to a string stored in buffer,
    115 // or a pointer to some static immutable string.
    116 // Returns one of the following values:
    117 //   0      - success
    118 //   ERANGE - buffer is not large enough to store the error message
    119 //   other  - failure
    120 // Buffer should be at least of size 1.
    121 int safe_strerror(
    122     int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
    123   FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
    124 
    125   class StrError {
    126    private:
    127     int error_code_;
    128     char *&buffer_;
    129     std::size_t buffer_size_;
    130 
    131     // A noop assignment operator to avoid bogus warnings.
    132     void operator=(const StrError &) {}
    133 
    134     // Handle the result of XSI-compliant version of strerror_r.
    135     int handle(int result) {
    136       // glibc versions before 2.13 return result in errno.
    137       return result == -1 ? errno : result;
    138     }
    139 
    140     // Handle the result of GNU-specific version of strerror_r.
    141     int handle(char *message) {
    142       // If the buffer is full then the message is probably truncated.
    143       if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
    144         return ERANGE;
    145       buffer_ = message;
    146       return 0;
    147     }
    148 
    149     // Handle the case when strerror_r is not available.
    150     int handle(internal::Null<>) {
    151       return fallback(strerror_s(buffer_, buffer_size_, error_code_));
    152     }
    153 
    154     // Fallback to strerror_s when strerror_r is not available.
    155     int fallback(int result) {
    156       // If the buffer is full then the message is probably truncated.
    157       return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
    158             ERANGE : result;
    159     }
    160 
    161     // Fallback to strerror if strerror_r and strerror_s are not available.
    162     int fallback(internal::Null<>) {
    163       errno = 0;
    164       buffer_ = strerror(error_code_);
    165       return errno;
    166     }
    167 
    168    public:
    169     StrError(int err_code, char *&buf, std::size_t buf_size)
    170       : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
    171 
    172     int run() {
    173       // Suppress a warning about unused strerror_r.
    174       strerror_r(0, FMT_NULL, "");
    175       return handle(strerror_r(error_code_, buffer_, buffer_size_));
    176     }
    177   };
    178   return StrError(error_code, buffer, buffer_size).run();
    179 }
    180 
    181 void format_error_code(Writer &out, int error_code,
    182                        StringRef message) FMT_NOEXCEPT {
    183   // Report error code making sure that the output fits into
    184   // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
    185   // bad_alloc.
    186   out.clear();
    187   static const char SEP[] = ": ";
    188   static const char ERROR_STR[] = "error ";
    189   // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
    190   std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
    191   typedef internal::IntTraits<int>::MainType MainType;
    192   MainType abs_value = static_cast<MainType>(error_code);
    193   if (internal::is_negative(error_code)) {
    194     abs_value = 0 - abs_value;
    195     ++error_code_size;
    196   }
    197   error_code_size += internal::count_digits(abs_value);
    198   if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
    199     out << message << SEP;
    200   out << ERROR_STR << error_code;
    201   assert(out.size() <= internal::INLINE_BUFFER_SIZE);
    202 }
    203 
    204 void report_error(FormatFunc func, int error_code,
    205                   StringRef message) FMT_NOEXCEPT {
    206   MemoryWriter full_message;
    207   func(full_message, error_code, message);
    208   // Use Writer::data instead of Writer::c_str to avoid potential memory
    209   // allocation.
    210   std::fwrite(full_message.data(), full_message.size(), 1, stderr);
    211   std::fputc('\n', stderr);
    212 }
    213 }  // namespace
    214 
    215 namespace internal {
    216 
    217 // This method is used to preserve binary compatibility with fmt 3.0.
    218 // It can be removed in 4.0.
    219 FMT_FUNC void format_system_error(
    220   Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
    221   fmt::format_system_error(out, error_code, message);
    222 }
    223 }  // namespace internal
    224 
    225 FMT_FUNC void SystemError::init(
    226     int err_code, CStringRef format_str, ArgList args) {
    227   error_code_ = err_code;
    228   MemoryWriter w;
    229   format_system_error(w, err_code, format(format_str, args));
    230   std::runtime_error &base = *this;
    231   base = std::runtime_error(w.str());
    232 }
    233 
    234 template <typename T>
    235 int internal::CharTraits<char>::format_float(
    236     char *buffer, std::size_t size, const char *format,
    237     unsigned width, int precision, T value) {
    238   if (width == 0) {
    239     return precision < 0 ?
    240         FMT_SNPRINTF(buffer, size, format, value) :
    241         FMT_SNPRINTF(buffer, size, format, precision, value);
    242   }
    243   return precision < 0 ?
    244       FMT_SNPRINTF(buffer, size, format, width, value) :
    245       FMT_SNPRINTF(buffer, size, format, width, precision, value);
    246 }
    247 
    248 template <typename T>
    249 int internal::CharTraits<wchar_t>::format_float(
    250     wchar_t *buffer, std::size_t size, const wchar_t *format,
    251     unsigned width, int precision, T value) {
    252   if (width == 0) {
    253     return precision < 0 ?
    254         FMT_SWPRINTF(buffer, size, format, value) :
    255         FMT_SWPRINTF(buffer, size, format, precision, value);
    256   }
    257   return precision < 0 ?
    258       FMT_SWPRINTF(buffer, size, format, width, value) :
    259       FMT_SWPRINTF(buffer, size, format, width, precision, value);
    260 }
    261 
    262 template <typename T>
    263 const char internal::BasicData<T>::DIGITS[] =
    264     "0001020304050607080910111213141516171819"
    265     "2021222324252627282930313233343536373839"
    266     "4041424344454647484950515253545556575859"
    267     "6061626364656667686970717273747576777879"
    268     "8081828384858687888990919293949596979899";
    269 
    270 #define FMT_POWERS_OF_10(factor) \
    271   factor * 10, \
    272   factor * 100, \
    273   factor * 1000, \
    274   factor * 10000, \
    275   factor * 100000, \
    276   factor * 1000000, \
    277   factor * 10000000, \
    278   factor * 100000000, \
    279   factor * 1000000000
    280 
    281 template <typename T>
    282 const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
    283   0, FMT_POWERS_OF_10(1)
    284 };
    285 
    286 template <typename T>
    287 const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
    288   0,
    289   FMT_POWERS_OF_10(1),
    290   FMT_POWERS_OF_10(ULongLong(1000000000)),
    291   // Multiply several constants instead of using a single long long constant
    292   // to avoid warnings about C++98 not supporting long long.
    293   ULongLong(1000000000) * ULongLong(1000000000) * 10
    294 };
    295 
    296 FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
    297   (void)type;
    298   if (std::isprint(static_cast<unsigned char>(code))) {
    299     FMT_THROW(FormatError(
    300         format("unknown format code '{}' for {}", code, type)));
    301   }
    302   FMT_THROW(FormatError(
    303       format("unknown format code '\\x{:02x}' for {}",
    304         static_cast<unsigned>(code), type)));
    305 }
    306 
    307 #if FMT_USE_WINDOWS_H
    308 
    309 FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
    310   static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
    311   if (s.size() > INT_MAX)
    312     FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
    313   int s_size = static_cast<int>(s.size());
    314   int length = MultiByteToWideChar(
    315       CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
    316   if (length == 0)
    317     FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
    318   buffer_.resize(length + 1);
    319   length = MultiByteToWideChar(
    320     CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
    321   if (length == 0)
    322     FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
    323   buffer_[length] = 0;
    324 }
    325 
    326 FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
    327   if (int error_code = convert(s)) {
    328     FMT_THROW(WindowsError(error_code,
    329         "cannot convert string from UTF-16 to UTF-8"));
    330   }
    331 }
    332 
    333 FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
    334   if (s.size() > INT_MAX)
    335     return ERROR_INVALID_PARAMETER;
    336   int s_size = static_cast<int>(s.size());
    337   int length = WideCharToMultiByte(
    338     CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
    339   if (length == 0)
    340     return GetLastError();
    341   buffer_.resize(length + 1);
    342   length = WideCharToMultiByte(
    343     CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
    344   if (length == 0)
    345     return GetLastError();
    346   buffer_[length] = 0;
    347   return 0;
    348 }
    349 
    350 FMT_FUNC void WindowsError::init(
    351     int err_code, CStringRef format_str, ArgList args) {
    352   error_code_ = err_code;
    353   MemoryWriter w;
    354   internal::format_windows_error(w, err_code, format(format_str, args));
    355   std::runtime_error &base = *this;
    356   base = std::runtime_error(w.str());
    357 }
    358 
    359 FMT_FUNC void internal::format_windows_error(
    360     Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
    361   FMT_TRY {
    362     MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
    363     buffer.resize(INLINE_BUFFER_SIZE);
    364     for (;;) {
    365       wchar_t *system_message = &buffer[0];
    366       int result = FormatMessageW(
    367         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    368         FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    369         system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
    370       if (result != 0) {
    371         UTF16ToUTF8 utf8_message;
    372         if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
    373           out << message << ": " << utf8_message;
    374           return;
    375         }
    376         break;
    377       }
    378       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    379         break;  // Can't get error message, report error code instead.
    380       buffer.resize(buffer.size() * 2);
    381     }
    382   } FMT_CATCH(...) {}
    383   fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
    384 }
    385 
    386 #endif  // FMT_USE_WINDOWS_H
    387 
    388 FMT_FUNC void format_system_error(
    389     Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
    390   FMT_TRY {
    391     internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
    392     buffer.resize(internal::INLINE_BUFFER_SIZE);
    393     for (;;) {
    394       char *system_message = &buffer[0];
    395       int result = safe_strerror(error_code, system_message, buffer.size());
    396       if (result == 0) {
    397         out << message << ": " << system_message;
    398         return;
    399       }
    400       if (result != ERANGE)
    401         break;  // Can't get error message, report error code instead.
    402       buffer.resize(buffer.size() * 2);
    403     }
    404   } FMT_CATCH(...) {}
    405   fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
    406 }
    407 
    408 template <typename Char>
    409 void internal::ArgMap<Char>::init(const ArgList &args) {
    410   if (!map_.empty())
    411     return;
    412   typedef internal::NamedArg<Char> NamedArg;
    413   const NamedArg *named_arg = FMT_NULL;
    414   bool use_values =
    415       args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
    416   if (use_values) {
    417     for (unsigned i = 0;/*nothing*/; ++i) {
    418       internal::Arg::Type arg_type = args.type(i);
    419       switch (arg_type) {
    420       case internal::Arg::NONE:
    421         return;
    422       case internal::Arg::NAMED_ARG:
    423         named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
    424         map_.push_back(Pair(named_arg->name, *named_arg));
    425         break;
    426       default:
    427         /*nothing*/;
    428       }
    429     }
    430     return;
    431   }
    432   for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
    433     internal::Arg::Type arg_type = args.type(i);
    434     if (arg_type == internal::Arg::NAMED_ARG) {
    435       named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
    436       map_.push_back(Pair(named_arg->name, *named_arg));
    437     }
    438   }
    439   for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
    440     switch (args.args_[i].type) {
    441     case internal::Arg::NONE:
    442       return;
    443     case internal::Arg::NAMED_ARG:
    444       named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
    445       map_.push_back(Pair(named_arg->name, *named_arg));
    446       break;
    447     default:
    448       /*nothing*/;
    449     }
    450   }
    451 }
    452 
    453 template <typename Char>
    454 void internal::FixedBuffer<Char>::grow(std::size_t) {
    455   FMT_THROW(std::runtime_error("buffer overflow"));
    456 }
    457 
    458 FMT_FUNC Arg internal::FormatterBase::do_get_arg(
    459     unsigned arg_index, const char *&error) {
    460   Arg arg = args_[arg_index];
    461   switch (arg.type) {
    462   case Arg::NONE:
    463     error = "argument index out of range";
    464     break;
    465   case Arg::NAMED_ARG:
    466     arg = *static_cast<const internal::Arg*>(arg.pointer);
    467     break;
    468   default:
    469     /*nothing*/;
    470   }
    471   return arg;
    472 }
    473 
    474 FMT_FUNC void report_system_error(
    475     int error_code, fmt::StringRef message) FMT_NOEXCEPT {
    476   // 'fmt::' is for bcc32.
    477   report_error(format_system_error, error_code, message);
    478 }
    479 
    480 #if FMT_USE_WINDOWS_H
    481 FMT_FUNC void report_windows_error(
    482     int error_code, fmt::StringRef message) FMT_NOEXCEPT {
    483   // 'fmt::' is for bcc32.
    484   report_error(internal::format_windows_error, error_code, message);
    485 }
    486 #endif
    487 
    488 FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
    489   MemoryWriter w;
    490   w.write(format_str, args);
    491   std::fwrite(w.data(), 1, w.size(), f);
    492 }
    493 
    494 FMT_FUNC void print(CStringRef format_str, ArgList args) {
    495   print(stdout, format_str, args);
    496 }
    497 
    498 FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
    499   char escape[] = "\x1b[30m";
    500   escape[3] = static_cast<char>('0' + c);
    501   std::fputs(escape, stdout);
    502   print(format, args);
    503   std::fputs(RESET_COLOR, stdout);
    504 }
    505 
    506 #ifndef FMT_HEADER_ONLY
    507 
    508 template struct internal::BasicData<void>;
    509 
    510 // Explicit instantiations for char.
    511 
    512 template void internal::FixedBuffer<char>::grow(std::size_t);
    513 
    514 template void internal::ArgMap<char>::init(const ArgList &args);
    515 
    516 template int internal::CharTraits<char>::format_float(
    517     char *buffer, std::size_t size, const char *format,
    518     unsigned width, int precision, double value);
    519 
    520 template int internal::CharTraits<char>::format_float(
    521     char *buffer, std::size_t size, const char *format,
    522     unsigned width, int precision, long double value);
    523 
    524 // Explicit instantiations for wchar_t.
    525 
    526 template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
    527 
    528 template void internal::ArgMap<wchar_t>::init(const ArgList &args);
    529 
    530 template int internal::CharTraits<wchar_t>::format_float(
    531     wchar_t *buffer, std::size_t size, const wchar_t *format,
    532     unsigned width, int precision, double value);
    533 
    534 template int internal::CharTraits<wchar_t>::format_float(
    535     wchar_t *buffer, std::size_t size, const wchar_t *format,
    536     unsigned width, int precision, long double value);
    537 
    538 #endif  // FMT_HEADER_ONLY
    539 
    540 }  // namespace fmt
    541 
    542 #ifdef _MSC_VER
    543 # pragma warning(pop)
    544 #endif
    545