diff options
Diffstat (limited to 'vendor/fmt-3.0.1/fmt/format.cc')
-rw-r--r-- | vendor/fmt-3.0.1/fmt/format.cc | 940 |
1 files changed, 0 insertions, 940 deletions
diff --git a/vendor/fmt-3.0.1/fmt/format.cc b/vendor/fmt-3.0.1/fmt/format.cc deleted file mode 100644 index 2bd774e4..00000000 --- a/vendor/fmt-3.0.1/fmt/format.cc +++ /dev/null @@ -1,940 +0,0 @@ -/* - 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(NOMINMAX) || defined(FMT_WIN_MINMAX) -# include <windows.h> -# else -# define NOMINMAX -# include <windows.h> -# undef NOMINMAX -# endif -#endif - -using fmt::internal::Arg; - -#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. -static inline fmt::internal::Null<> strerror_r(int, char *, ...) { - return fmt::internal::Null<>(); -} -static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { - return fmt::internal::Null<>(); -} - -namespace fmt { - -FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {} -FMT_FUNC FormatError::~FormatError() throw() {} -FMT_FUNC SystemError::~SystemError() throw() {} - -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) - -// Checks if a value fits in int - used to avoid warnings about comparing -// signed and unsigned integers. -template <bool IsSigned> -struct IntChecker { - template <typename T> - static bool fits_in_int(T value) { - unsigned max = INT_MAX; - return value <= max; - } - static bool fits_in_int(bool) { return true; } -}; - -template <> -struct IntChecker<true> { - template <typename T> - static bool fits_in_int(T value) { - return value >= INT_MIN && value <= INT_MAX; - } - static bool fits_in_int(int) { return true; } -}; - -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 != 0 && 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; - } - - // Fallback to strerror if strerror_r and strerror_s are not available. - int fallback(internal::Null<>) { - errno = 0; - buffer_ = strerror(error_code_); - return errno; - } - - public: - StrError(int err_code, char *&buf, std::size_t buf_size) - : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} - - int run() { - strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. - 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); -} - -// IsZeroInt::visit(arg) returns true iff arg is a zero integer. -class IsZeroInt : public ArgVisitor<IsZeroInt, bool> { - public: - template <typename T> - bool visit_any_int(T value) { return value == 0; } -}; - -// Checks if an argument is a valid printf width specifier and sets -// left alignment if it is negative. -class WidthHandler : public ArgVisitor<WidthHandler, unsigned> { - private: - FormatSpec &spec_; - - FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); - - public: - explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} - - void report_unhandled_arg() { - FMT_THROW(FormatError("width is not integer")); - } - - template <typename T> - unsigned visit_any_int(T value) { - typedef typename internal::IntTraits<T>::MainType UnsignedType; - UnsignedType width = static_cast<UnsignedType>(value); - if (internal::is_negative(value)) { - spec_.align_ = ALIGN_LEFT; - width = 0 - width; - } - if (width > INT_MAX) - FMT_THROW(FormatError("number is too big")); - return static_cast<unsigned>(width); - } -}; - -class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> { - public: - void report_unhandled_arg() { - FMT_THROW(FormatError("precision is not integer")); - } - - template <typename T> - int visit_any_int(T value) { - if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) - FMT_THROW(FormatError("number is too big")); - return static_cast<int>(value); - } -}; - -template <typename T, typename U> -struct is_same { - enum { value = 0 }; -}; - -template <typename T> -struct is_same<T, T> { - enum { value = 1 }; -}; - -// An argument visitor that converts an integer argument to T for printf, -// if T is an integral type. If T is void, the argument is converted to -// corresponding signed or unsigned type depending on the type specifier: -// 'd' and 'i' - signed, other - unsigned) -template <typename T = void> -class ArgConverter : public ArgVisitor<ArgConverter<T>, void> { - private: - internal::Arg &arg_; - wchar_t type_; - - FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); - - public: - ArgConverter(internal::Arg &arg, wchar_t type) - : arg_(arg), type_(type) {} - - void visit_bool(bool value) { - if (type_ != 's') - visit_any_int(value); - } - - template <typename U> - void visit_any_int(U value) { - bool is_signed = type_ == 'd' || type_ == 'i'; - using internal::Arg; - typedef typename internal::Conditional< - is_same<T, void>::value, U, T>::type TargetType; - if (sizeof(TargetType) <= sizeof(int)) { - // Extra casts are used to silence warnings. - if (is_signed) { - arg_.type = Arg::INT; - arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); - } else { - arg_.type = Arg::UINT; - typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; - arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); - } - } else { - if (is_signed) { - arg_.type = Arg::LONG_LONG; - // glibc's printf doesn't sign extend arguments of smaller types: - // std::printf("%lld", -42); // prints "4294967254" - // but we don't have to do the same because it's a UB. - arg_.long_long_value = static_cast<LongLong>(value); - } else { - arg_.type = Arg::ULONG_LONG; - arg_.ulong_long_value = - static_cast<typename internal::MakeUnsigned<U>::Type>(value); - } - } - } -}; - -// Converts an integer argument to char for printf. -class CharConverter : public ArgVisitor<CharConverter, void> { - private: - internal::Arg &arg_; - - FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); - - public: - explicit CharConverter(internal::Arg &arg) : arg_(arg) {} - - template <typename T> - void visit_any_int(T value) { - arg_.type = internal::Arg::CHAR; - arg_.int_value = static_cast<char>(value); - } -}; -} // namespace - -namespace internal { - -template <typename Char> -class PrintfArgFormatter : - public ArgFormatterBase<PrintfArgFormatter<Char>, Char> { - - void write_null_pointer() { - this->spec().type_ = 0; - this->write("(nil)"); - } - - typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base; - - public: - PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) - : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {} - - void visit_bool(bool value) { - FormatSpec &fmt_spec = this->spec(); - if (fmt_spec.type_ != 's') - return this->visit_any_int(value); - fmt_spec.type_ = 0; - this->write(value); - } - - void visit_char(int value) { - const FormatSpec &fmt_spec = this->spec(); - BasicWriter<Char> &w = this->writer(); - if (fmt_spec.type_ && fmt_spec.type_ != 'c') - w.write_int(value, fmt_spec); - typedef typename BasicWriter<Char>::CharPtr CharPtr; - CharPtr out = CharPtr(); - if (fmt_spec.width_ > 1) { - Char fill = ' '; - out = w.grow_buffer(fmt_spec.width_); - if (fmt_spec.align_ != ALIGN_LEFT) { - std::fill_n(out, fmt_spec.width_ - 1, fill); - out += fmt_spec.width_ - 1; - } else { - std::fill_n(out + 1, fmt_spec.width_ - 1, fill); - } - } else { - out = w.grow_buffer(1); - } - *out = static_cast<Char>(value); - } - - void visit_cstring(const char *value) { - if (value) - Base::visit_cstring(value); - else if (this->spec().type_ == 'p') - write_null_pointer(); - else - this->write("(null)"); - } - - void visit_pointer(const void *value) { - if (value) - return Base::visit_pointer(value); - this->spec().type_ = 0; - write_null_pointer(); - } - - void visit_custom(Arg::CustomValue c) { - BasicFormatter<Char> formatter(ArgList(), this->writer()); - const Char format_str[] = {'}', 0}; - const Char *format = format_str; - c.format(&formatter, c.value, &format); - } -}; -} // namespace internal -} // namespace fmt - -FMT_FUNC void fmt::SystemError::init( - int err_code, CStringRef format_str, ArgList args) { - error_code_ = err_code; - MemoryWriter w; - internal::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 fmt::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 fmt::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 fmt::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 fmt::internal::BasicData<T>::POWERS_OF_10_32[] = { - 0, FMT_POWERS_OF_10(1) -}; - -template <typename T> -const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = { - 0, - FMT_POWERS_OF_10(1), - FMT_POWERS_OF_10(fmt::ULongLong(1000000000)), - // Multiply several constants instead of using a single long long constant - // to avoid warnings about C++98 not supporting long long. - fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10 -}; - -FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { - (void)type; - if (std::isprint(static_cast<unsigned char>(code))) { - FMT_THROW(fmt::FormatError( - fmt::format("unknown format code '{}' for {}", code, type))); - } - FMT_THROW(fmt::FormatError( - fmt::format("unknown format code '\\x{:02x}' for {}", - static_cast<unsigned>(code), type))); -} - -#if FMT_USE_WINDOWS_H - -FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::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, 0, 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 fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::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 fmt::internal::UTF16ToUTF8::convert(fmt::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, 0, 0, 0, 0); - if (length == 0) - return GetLastError(); - buffer_.resize(length + 1); - length = WideCharToMultiByte( - CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0); - if (length == 0) - return GetLastError(); - buffer_[length] = 0; - return 0; -} - -FMT_FUNC void fmt::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 fmt::internal::format_windows_error( - fmt::Writer &out, int error_code, - fmt::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, - 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - system_message, static_cast<uint32_t>(buffer.size()), 0); - 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 fmt::internal::format_system_error( - fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT { - FMT_TRY { - MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer; - buffer.resize(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 fmt::internal::ArgMap<Char>::init(const ArgList &args) { - if (!map_.empty()) - return; - typedef internal::NamedArg<Char> NamedArg; - const NamedArg *named_arg = 0; - bool use_values = - args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; - if (use_values) { - for (unsigned i = 0;/*nothing*/; ++i) { - internal::Arg::Type arg_type = args.type(i); - switch (arg_type) { - case internal::Arg::NONE: - return; - case internal::Arg::NAMED_ARG: - named_arg = static_cast<const NamedArg*>(args.values_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - break; - default: - /*nothing*/; - } - } - return; - } - for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) { - internal::Arg::Type arg_type = args.type(i); - if (arg_type == internal::Arg::NAMED_ARG) { - named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - } - } - for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { - switch (args.args_[i].type) { - case internal::Arg::NONE: - return; - case internal::Arg::NAMED_ARG: - named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - break; - default: - /*nothing*/; - } - } -} - -template <typename Char> -void fmt::internal::FixedBuffer<Char>::grow(std::size_t) { - FMT_THROW(std::runtime_error("buffer overflow")); -} - -FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( - unsigned arg_index, const char *&error) { - Arg arg = args_[arg_index]; - switch (arg.type) { - case Arg::NONE: - error = "argument index out of range"; - break; - case Arg::NAMED_ARG: - arg = *static_cast<const internal::Arg*>(arg.pointer); - break; - default: - /*nothing*/; - } - return arg; -} - -template <typename Char> -void fmt::internal::PrintfFormatter<Char>::parse_flags( - FormatSpec &spec, const Char *&s) { - for (;;) { - switch (*s++) { - case '-': - spec.align_ = ALIGN_LEFT; - break; - case '+': - spec.flags_ |= SIGN_FLAG | PLUS_FLAG; - break; - case '0': - spec.fill_ = '0'; - break; - case ' ': - spec.flags_ |= SIGN_FLAG; - break; - case '#': - spec.flags_ |= HASH_FLAG; - break; - default: - --s; - return; - } - } -} - -template <typename Char> -Arg fmt::internal::PrintfFormatter<Char>::get_arg( - const Char *s, unsigned arg_index) { - (void)s; - const char *error = 0; - Arg arg = arg_index == UINT_MAX ? - next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); - if (error) - FMT_THROW(FormatError(!*s ? "invalid format string" : error)); - return arg; -} - -template <typename Char> -unsigned fmt::internal::PrintfFormatter<Char>::parse_header( - const Char *&s, FormatSpec &spec) { - unsigned arg_index = UINT_MAX; - Char c = *s; - if (c >= '0' && c <= '9') { - // Parse an argument index (if followed by '$') or a width possibly - // preceded with '0' flag(s). - unsigned value = parse_nonnegative_int(s); - if (*s == '$') { // value is an argument index - ++s; - arg_index = value; - } else { - if (c == '0') - spec.fill_ = '0'; - if (value != 0) { - // Nonzero value means that we parsed width and don't need to - // parse it or flags again, so return now. - spec.width_ = value; - return arg_index; - } - } - } - parse_flags(spec, s); - // Parse width. - if (*s >= '0' && *s <= '9') { - spec.width_ = parse_nonnegative_int(s); - } else if (*s == '*') { - ++s; - spec.width_ = WidthHandler(spec).visit(get_arg(s)); - } - return arg_index; -} - -template <typename Char> -void fmt::internal::PrintfFormatter<Char>::format( - BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) { - const Char *start = format_str.c_str(); - const Char *s = start; - while (*s) { - Char c = *s++; - if (c != '%') continue; - if (*s == c) { - write(writer, start, s); - start = ++s; - continue; - } - write(writer, start, s - 1); - - FormatSpec spec; - spec.align_ = ALIGN_RIGHT; - - // Parse argument index, flags and width. - unsigned arg_index = parse_header(s, spec); - - // Parse precision. - if (*s == '.') { - ++s; - if ('0' <= *s && *s <= '9') { - spec.precision_ = static_cast<int>(parse_nonnegative_int(s)); - } else if (*s == '*') { - ++s; - spec.precision_ = PrecisionHandler().visit(get_arg(s)); - } - } - - Arg arg = get_arg(s, arg_index); - if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg)) - spec.flags_ &= ~to_unsigned<int>(HASH_FLAG); - if (spec.fill_ == '0') { - if (arg.type <= Arg::LAST_NUMERIC_TYPE) - spec.align_ = ALIGN_NUMERIC; - else - spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. - } - - // Parse length and convert the argument to the required type. - switch (*s++) { - case 'h': - if (*s == 'h') - ArgConverter<signed char>(arg, *++s).visit(arg); - else - ArgConverter<short>(arg, *s).visit(arg); - break; - case 'l': - if (*s == 'l') - ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); - else - ArgConverter<long>(arg, *s).visit(arg); - break; - case 'j': - ArgConverter<intmax_t>(arg, *s).visit(arg); - break; - case 'z': - ArgConverter<std::size_t>(arg, *s).visit(arg); - break; - case 't': - ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); - break; - case 'L': - // printf produces garbage when 'L' is omitted for long double, no - // need to do the same. - break; - default: - --s; - ArgConverter<void>(arg, *s).visit(arg); - } - - // Parse type. - if (!*s) - FMT_THROW(FormatError("invalid format string")); - spec.type_ = static_cast<char>(*s++); - if (arg.type <= Arg::LAST_INTEGER_TYPE) { - // Normalize type. - switch (spec.type_) { - case 'i': case 'u': - spec.type_ = 'd'; - break; - case 'c': - // TODO: handle wchar_t - CharConverter(arg).visit(arg); - break; - } - } - - start = s; - - // Format argument. - internal::PrintfArgFormatter<Char>(writer, spec).visit(arg); - } - write(writer, start, s); -} - -FMT_FUNC void fmt::report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. - fmt::report_error(internal::format_system_error, error_code, message); -} - -#if FMT_USE_WINDOWS_H -FMT_FUNC void fmt::report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. - fmt::report_error(internal::format_windows_error, error_code, message); -} -#endif - -FMT_FUNC void fmt::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 fmt::print(CStringRef format_str, ArgList args) { - print(stdout, format_str, args); -} - -FMT_FUNC void fmt::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); -} - -FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) { - MemoryWriter w; - printf(w, format, args); - std::size_t size = w.size(); - return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); -} - -#ifndef FMT_HEADER_ONLY - -template struct fmt::internal::BasicData<void>; - -// Explicit instantiations for char. - -template void fmt::internal::FixedBuffer<char>::grow(std::size_t); - -template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args); - -template void fmt::internal::PrintfFormatter<char>::format( - BasicWriter<char> &writer, CStringRef format); - -template int fmt::internal::CharTraits<char>::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, double value); - -template int fmt::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 fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t); - -template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args); - -template void fmt::internal::PrintfFormatter<wchar_t>::format( - BasicWriter<wchar_t> &writer, WCStringRef format); - -template int fmt::internal::CharTraits<wchar_t>::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, double value); - -template int fmt::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 - -#ifdef _MSC_VER -# pragma warning(pop) -#endif |