diff options
Diffstat (limited to 'lib/spdlog/fmt/bundled/format.cc')
| -rw-r--r-- | lib/spdlog/fmt/bundled/format.cc | 495 | 
1 files changed, 495 insertions, 0 deletions
diff --git a/lib/spdlog/fmt/bundled/format.cc b/lib/spdlog/fmt/bundled/format.cc new file mode 100644 index 0000000..2d236bc --- /dev/null +++ b/lib/spdlog/fmt/bundled/format.cc @@ -0,0 +1,495 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this +    list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, +    this list of conditions and the following disclaimer in the documentation +    and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "format.h" + +#include <string.h> + +#include <cctype> +#include <cerrno> +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstddef>  // for std::ptrdiff_t + +#if defined(_WIN32) && defined(__MINGW32__) +# include <cstring> +#endif + +#if FMT_USE_WINDOWS_H +# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN) +#  define WIN32_LEAN_AND_MEAN +# endif +# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) +#  include <windows.h> +# else +#  define NOMINMAX +#  include <windows.h> +#  undef NOMINMAX +# endif +#endif + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127)  // conditional expression is constant +# pragma warning(disable: 4702)  // unreachable code +// Disable deprecation warning for strerror. The latter is not called but +// MSVC fails to detect it. +# pragma warning(disable: 4996) +#endif + +// Dummy implementations of strerror_r and strerror_s called if corresponding +// system functions are not available. +FMT_MAYBE_UNUSED +static inline fmt::internal::Null<> strerror_r(int, char *, ...) { +  return fmt::internal::Null<>(); +} +FMT_MAYBE_UNUSED +static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { +  return fmt::internal::Null<>(); +} + +namespace fmt { + +FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} +FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {} +FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {} + +namespace { + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else  // _MSC_VER +inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { +  va_list args; +  va_start(args, format); +  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); +  va_end(args); +  return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif  // _MSC_VER + +#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) +# define FMT_SWPRINTF snwprintf +#else +# define FMT_SWPRINTF swprintf +#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) + +const char RESET_COLOR[] = "\x1b[0m"; + +typedef void (*FormatFunc)(Writer &, int, StringRef); + +// Portable thread-safe version of strerror. +// Sets buffer to point to a string describing the error code. +// This can be either a pointer to a string stored in buffer, +// or a pointer to some static immutable string. +// Returns one of the following values: +//   0      - success +//   ERANGE - buffer is not large enough to store the error message +//   other  - failure +// Buffer should be at least of size 1. +int safe_strerror( +    int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { +  FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer"); + +  class StrError { +   private: +    int error_code_; +    char *&buffer_; +    std::size_t buffer_size_; + +    // A noop assignment operator to avoid bogus warnings. +    void operator=(const StrError &) {} + +    // Handle the result of XSI-compliant version of strerror_r. +    int handle(int result) { +      // glibc versions before 2.13 return result in errno. +      return result == -1 ? errno : result; +    } + +    // Handle the result of GNU-specific version of strerror_r. +    int handle(char *message) { +      // If the buffer is full then the message is probably truncated. +      if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1) +        return ERANGE; +      buffer_ = message; +      return 0; +    } + +    // Handle the case when strerror_r is not available. +    int handle(internal::Null<>) { +      return fallback(strerror_s(buffer_, buffer_size_, error_code_)); +    } + +    // Fallback to strerror_s when strerror_r is not available. +    int fallback(int result) { +      // If the buffer is full then the message is probably truncated. +      return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? +            ERANGE : result; +    } + +#ifdef __c2__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + +    // Fallback to strerror if strerror_r and strerror_s are not available. +    int fallback(internal::Null<>) { +      errno = 0; +      buffer_ = strerror(error_code_); +      return errno; +    } + +#ifdef __c2__ +# pragma clang diagnostic pop +#endif + +   public: +    StrError(int err_code, char *&buf, std::size_t buf_size) +      : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} + +    int run() { +      return handle(strerror_r(error_code_, buffer_, buffer_size_)); +    } +  }; +  return StrError(error_code, buffer, buffer_size).run(); +} + +void format_error_code(Writer &out, int error_code, +                       StringRef message) FMT_NOEXCEPT { +  // Report error code making sure that the output fits into +  // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential +  // bad_alloc. +  out.clear(); +  static const char SEP[] = ": "; +  static const char ERROR_STR[] = "error "; +  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. +  std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; +  typedef internal::IntTraits<int>::MainType MainType; +  MainType abs_value = static_cast<MainType>(error_code); +  if (internal::is_negative(error_code)) { +    abs_value = 0 - abs_value; +    ++error_code_size; +  } +  error_code_size += internal::count_digits(abs_value); +  if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) +    out << message << SEP; +  out << ERROR_STR << error_code; +  assert(out.size() <= internal::INLINE_BUFFER_SIZE); +} + +void report_error(FormatFunc func, int error_code, +                  StringRef message) FMT_NOEXCEPT { +  MemoryWriter full_message; +  func(full_message, error_code, message); +  // Use Writer::data instead of Writer::c_str to avoid potential memory +  // allocation. +  std::fwrite(full_message.data(), full_message.size(), 1, stderr); +  std::fputc('\n', stderr); +} +}  // namespace + +FMT_FUNC void SystemError::init( +    int err_code, CStringRef format_str, ArgList args) { +  error_code_ = err_code; +  MemoryWriter w; +  format_system_error(w, err_code, format(format_str, args)); +  std::runtime_error &base = *this; +  base = std::runtime_error(w.str()); +} + +template <typename T> +int internal::CharTraits<char>::format_float( +    char *buffer, std::size_t size, const char *format, +    unsigned width, int precision, T value) { +  if (width == 0) { +    return precision < 0 ? +        FMT_SNPRINTF(buffer, size, format, value) : +        FMT_SNPRINTF(buffer, size, format, precision, value); +  } +  return precision < 0 ? +      FMT_SNPRINTF(buffer, size, format, width, value) : +      FMT_SNPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +int internal::CharTraits<wchar_t>::format_float( +    wchar_t *buffer, std::size_t size, const wchar_t *format, +    unsigned width, int precision, T value) { +  if (width == 0) { +    return precision < 0 ? +        FMT_SWPRINTF(buffer, size, format, value) : +        FMT_SWPRINTF(buffer, size, format, precision, value); +  } +  return precision < 0 ? +      FMT_SWPRINTF(buffer, size, format, width, value) : +      FMT_SWPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +const char internal::BasicData<T>::DIGITS[] = +    "0001020304050607080910111213141516171819" +    "2021222324252627282930313233343536373839" +    "4041424344454647484950515253545556575859" +    "6061626364656667686970717273747576777879" +    "8081828384858687888990919293949596979899"; + +#define FMT_POWERS_OF_10(factor) \ +  factor * 10, \ +  factor * 100, \ +  factor * 1000, \ +  factor * 10000, \ +  factor * 100000, \ +  factor * 1000000, \ +  factor * 10000000, \ +  factor * 100000000, \ +  factor * 1000000000 + +template <typename T> +const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = { +  0, FMT_POWERS_OF_10(1) +}; + +template <typename T> +const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = { +  0, +  FMT_POWERS_OF_10(1), +  FMT_POWERS_OF_10(ULongLong(1000000000)), +  // Multiply several constants instead of using a single long long constant +  // to avoid warnings about C++98 not supporting long long. +  ULongLong(1000000000) * ULongLong(1000000000) * 10 +}; + +FMT_FUNC void internal::report_unknown_type(char code, const char *type) { +  (void)type; +  if (std::isprint(static_cast<unsigned char>(code))) { +    FMT_THROW(FormatError( +        format("unknown format code '{}' for {}", code, type))); +  } +  FMT_THROW(FormatError( +      format("unknown format code '\\x{:02x}' for {}", +        static_cast<unsigned>(code), type))); +} + +#if FMT_USE_WINDOWS_H + +FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) { +  static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; +  if (s.size() > INT_MAX) +    FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); +  int s_size = static_cast<int>(s.size()); +  int length = MultiByteToWideChar( +      CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0); +  if (length == 0) +    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); +  buffer_.resize(length + 1); +  length = MultiByteToWideChar( +    CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); +  if (length == 0) +    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); +  buffer_[length] = 0; +} + +FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { +  if (int error_code = convert(s)) { +    FMT_THROW(WindowsError(error_code, +        "cannot convert string from UTF-16 to UTF-8")); +  } +} + +FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) { +  if (s.size() > INT_MAX) +    return ERROR_INVALID_PARAMETER; +  int s_size = static_cast<int>(s.size()); +  int length = WideCharToMultiByte( +    CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL); +  if (length == 0) +    return GetLastError(); +  buffer_.resize(length + 1); +  length = WideCharToMultiByte( +    CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL); +  if (length == 0) +    return GetLastError(); +  buffer_[length] = 0; +  return 0; +} + +FMT_FUNC void WindowsError::init( +    int err_code, CStringRef format_str, ArgList args) { +  error_code_ = err_code; +  MemoryWriter w; +  internal::format_windows_error(w, err_code, format(format_str, args)); +  std::runtime_error &base = *this; +  base = std::runtime_error(w.str()); +} + +FMT_FUNC void internal::format_windows_error( +    Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { +  FMT_TRY { +    MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; +    buffer.resize(INLINE_BUFFER_SIZE); +    for (;;) { +      wchar_t *system_message = &buffer[0]; +      int result = FormatMessageW( +        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, +        FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), +        system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL); +      if (result != 0) { +        UTF16ToUTF8 utf8_message; +        if (utf8_message.convert(system_message) == ERROR_SUCCESS) { +          out << message << ": " << utf8_message; +          return; +        } +        break; +      } +      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) +        break;  // Can't get error message, report error code instead. +      buffer.resize(buffer.size() * 2); +    } +  } FMT_CATCH(...) {} +  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32. +} + +#endif  // FMT_USE_WINDOWS_H + +FMT_FUNC void format_system_error( +    Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { +  FMT_TRY { +    internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer; +    buffer.resize(internal::INLINE_BUFFER_SIZE); +    for (;;) { +      char *system_message = &buffer[0]; +      int result = safe_strerror(error_code, system_message, buffer.size()); +      if (result == 0) { +        out << message << ": " << system_message; +        return; +      } +      if (result != ERANGE) +        break;  // Can't get error message, report error code instead. +      buffer.resize(buffer.size() * 2); +    } +  } FMT_CATCH(...) {} +  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32. +} + +template <typename Char> +void internal::FixedBuffer<Char>::grow(std::size_t) { +  FMT_THROW(std::runtime_error("buffer overflow")); +} + +FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg( +    unsigned arg_index, const char *&error) { +  internal::Arg arg = args_[arg_index]; +  switch (arg.type) { +  case internal::Arg::NONE: +    error = "argument index out of range"; +    break; +  case internal::Arg::NAMED_ARG: +    arg = *static_cast<const internal::Arg*>(arg.pointer); +    break; +  default: +    /*nothing*/; +  } +  return arg; +} + +FMT_FUNC void report_system_error( +    int error_code, fmt::StringRef message) FMT_NOEXCEPT { +  // 'fmt::' is for bcc32. +  report_error(format_system_error, error_code, message); +} + +#if FMT_USE_WINDOWS_H +FMT_FUNC void report_windows_error( +    int error_code, fmt::StringRef message) FMT_NOEXCEPT { +  // 'fmt::' is for bcc32. +  report_error(internal::format_windows_error, error_code, message); +} +#endif + +FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) { +  MemoryWriter w; +  w.write(format_str, args); +  std::fwrite(w.data(), 1, w.size(), f); +} + +FMT_FUNC void print(CStringRef format_str, ArgList args) { +  print(stdout, format_str, args); +} + +FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) { +  char escape[] = "\x1b[30m"; +  escape[3] = static_cast<char>('0' + c); +  std::fputs(escape, stdout); +  print(format, args); +  std::fputs(RESET_COLOR, stdout); +} + +#ifndef FMT_HEADER_ONLY + +template struct internal::BasicData<void>; + +// Explicit instantiations for char. + +template void internal::FixedBuffer<char>::grow(std::size_t); + +template FMT_API int internal::CharTraits<char>::format_float( +    char *buffer, std::size_t size, const char *format, +    unsigned width, int precision, double value); + +template FMT_API int internal::CharTraits<char>::format_float( +    char *buffer, std::size_t size, const char *format, +    unsigned width, int precision, long double value); + +// Explicit instantiations for wchar_t. + +template void internal::FixedBuffer<wchar_t>::grow(std::size_t); + +template FMT_API int internal::CharTraits<wchar_t>::format_float( +    wchar_t *buffer, std::size_t size, const wchar_t *format, +    unsigned width, int precision, double value); + +template FMT_API int internal::CharTraits<wchar_t>::format_float( +    wchar_t *buffer, std::size_t size, const wchar_t *format, +    unsigned width, int precision, long double value); + +#endif  // FMT_HEADER_ONLY + +}  // namespace fmt + +#ifdef _MSC_VER +# pragma warning(pop) +#endif  | 
