summaryrefslogtreecommitdiff
path: root/lib/spdlog/fmt/bundled/format.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spdlog/fmt/bundled/format.cc')
-rw-r--r--lib/spdlog/fmt/bundled/format.cc495
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