Fixed bug #81 (Doesn't compile on OS X under gcc-4.9 )

This commit is contained in:
gabime 2015-04-26 23:38:43 +03:00
parent 9600028521
commit 2269f4d9f8
2 changed files with 2535 additions and 2746 deletions

View File

@ -1,29 +1,29 @@
/* /*
Formatting library for C++ Formatting library for C++
Copyright (c) 2012 - 2014, Victor Zverovich Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "format.h" #include "format.h"
@ -66,10 +66,8 @@ using fmt::internal::Arg;
#ifndef FMT_THROW #ifndef FMT_THROW
# if FMT_EXCEPTIONS # if FMT_EXCEPTIONS
# define FMT_THROW(x) throw x # define FMT_THROW(x) throw x
# define FMT_RETURN_AFTER_THROW(x)
# else # else
# define FMT_THROW(x) assert(false) # define FMT_THROW(x) assert(false)
# define FMT_RETURN_AFTER_THROW(x) return x
# endif # endif
#endif #endif
@ -83,8 +81,20 @@ using fmt::internal::Arg;
# pragma warning(push) # pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant # pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4702) // unreachable code # 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 #endif
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
static inline fmt::internal::None<> strerror_r(int, char *, ...) {
return fmt::internal::None<>();
}
static inline fmt::internal::None<> strerror_s(char *, std::size_t, ...) {
return fmt::internal::None<>();
}
namespace { namespace {
#ifndef _MSC_VER #ifndef _MSC_VER
@ -100,6 +110,12 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
# define FMT_SNPRINTF fmt_snprintf # define FMT_SNPRINTF fmt_snprintf
#endif // _MSC_VER #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 // Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers. // signed and unsigned integers.
template <bool IsSigned> template <bool IsSigned>
@ -121,7 +137,7 @@ struct IntChecker<true> {
const char RESET_COLOR[] = "\x1b[0m"; const char RESET_COLOR[] = "\x1b[0m";
typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef); typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// Portable thread-safe version of strerror. // Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code. // Sets buffer to point to a string describing the error code.
@ -133,59 +149,81 @@ typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// other - failure // other - failure
// Buffer should be at least of size 1. // Buffer should be at least of size 1.
int safe_strerror( int safe_strerror(
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT{ int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
assert(buffer != 0 && buffer_size != 0); assert(buffer != 0 && buffer_size != 0);
int result = 0;
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__ class StrError {
// XSI-compliant version of strerror_r. private:
result = strerror_r(error_code, buffer, buffer_size); int error_code_;
if (result != 0) char *&buffer_;
result = errno; std::size_t buffer_size_;
#elif _GNU_SOURCE
// GNU-specific version of strerror_r. // A noop assignment operator to avoid bogus warnings.
char *message = strerror_r(error_code, buffer, buffer_size); 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 the buffer is full then the message is probably truncated.
if (message == buffer && strlen(buffer) == buffer_size - 1) if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
result = ERANGE; return ERANGE;
buffer = message; buffer_ = message;
#elif __MINGW32__ return 0;
}
// Handle the case when strerror_r is not available.
int handle(fmt::internal::None<>) {
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(fmt::internal::None<>) {
errno = 0; errno = 0;
(void)buffer_size; buffer_ = strerror(error_code_);
buffer = strerror(error_code); return errno;
result = errno; }
#elif _WIN32
result = strerror_s(buffer, buffer_size, error_code); public:
// If the buffer is full then the message is probably truncated. StrError(int error_code, char *&buffer, std::size_t buffer_size)
if (result == 0 && std::strlen(buffer) == buffer_size - 1) : error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {}
result = ERANGE;
#else int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
result = strerror_r(error_code, buffer, buffer_size); };
if (result == -1) return StrError(error_code, buffer, buffer_size).run();
result = errno; // glibc versions before 2.13 return result in errno.
#endif
return result;
} }
void format_error_code(fmt::Writer &out, int error_code, void format_error_code(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
// Report error code making sure that the output fits into // Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc. // bad_alloc.
out.clear(); out.clear();
static const char SEP[] = ": "; static const char SEP[] = ": ";
static const char ERR[] = "error "; static const char ERROR_STR[] = "error ";
fmt::internal::IntTraits<int>::MainType ec_value = error_code; fmt::internal::IntTraits<int>::MainType ec_value = error_code;
// Subtract 2 to account for terminating null characters in SEP and ERR. // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
std::size_t error_code_size = std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
sizeof(SEP) + sizeof(ERR) + fmt::internal::count_digits(ec_value) - 2; error_code_size += fmt::internal::count_digits(ec_value);
if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size) if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
out << message << SEP; out << message << SEP;
out << ERR << error_code; out << ERROR_STR << error_code;
assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE); assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
} }
void report_error(FormatFunc func, void report_error(FormatFunc func,
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
fmt::MemoryWriter full_message; fmt::MemoryWriter full_message;
func(full_message, error_code, message); func(full_message, error_code, message);
// Use Writer::data instead of Writer::c_str to avoid potential memory // Use Writer::data instead of Writer::c_str to avoid potential memory
@ -196,11 +234,9 @@ void report_error(FormatFunc func,
// IsZeroInt::visit(arg) returns true iff arg is a zero integer. // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> { class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
public: public:
template <typename T> template <typename T>
bool visit_any_int(T value) { bool visit_any_int(T value) { return value == 0; }
return value == 0;
}
}; };
// Parses an unsigned integer advancing s to the end of the parsed input. // Parses an unsigned integer advancing s to the end of the parsed input.
@ -245,17 +281,16 @@ void check_sign(const Char *&s, const Arg &arg) {
// Checks if an argument is a valid printf width specifier and sets // Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative. // left alignment if it is negative.
class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> { class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
private: private:
fmt::FormatSpec &spec_; fmt::FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public: public:
explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {} explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
unsigned visit_unhandled_arg() { void report_unhandled_arg() {
FMT_THROW(fmt::FormatError("width is not integer")); FMT_THROW(fmt::FormatError("width is not integer"));
FMT_RETURN_AFTER_THROW(0);
} }
template <typename T> template <typename T>
@ -274,10 +309,9 @@ public:
class PrecisionHandler : class PrecisionHandler :
public fmt::internal::ArgVisitor<PrecisionHandler, int> { public fmt::internal::ArgVisitor<PrecisionHandler, int> {
public: public:
unsigned visit_unhandled_arg() { void report_unhandled_arg() {
FMT_THROW(fmt::FormatError("precision is not integer")); FMT_THROW(fmt::FormatError("precision is not integer"));
FMT_RETURN_AFTER_THROW(0);
} }
template <typename T> template <typename T>
@ -291,13 +325,13 @@ public:
// Converts an integer argument to an integral type T for printf. // Converts an integer argument to an integral type T for printf.
template <typename T> template <typename T>
class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> { class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
private: private:
fmt::internal::Arg &arg_; fmt::internal::Arg &arg_;
wchar_t type_; wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public: public:
ArgConverter(fmt::internal::Arg &arg, wchar_t type) ArgConverter(fmt::internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {} : arg_(arg), type_(type) {}
@ -310,20 +344,17 @@ public:
if (is_signed) { if (is_signed) {
arg_.type = Arg::INT; arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<T>(value)); arg_.int_value = static_cast<int>(static_cast<T>(value));
} } else {
else {
arg_.type = Arg::UINT; arg_.type = Arg::UINT;
arg_.uint_value = static_cast<unsigned>( arg_.uint_value = static_cast<unsigned>(
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value)); static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
} }
} } else {
else {
if (is_signed) { if (is_signed) {
arg_.type = Arg::LONG_LONG; arg_.type = Arg::LONG_LONG;
arg_.long_long_value = arg_.long_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value); static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
} } else {
else {
arg_.type = Arg::ULONG_LONG; arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value = arg_.ulong_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value); static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
@ -334,12 +365,12 @@ public:
// Converts an integer argument to char for printf. // Converts an integer argument to char for printf.
class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> { class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
private: private:
fmt::internal::Arg &arg_; fmt::internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public: public:
explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {} explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
template <typename T> template <typename T>
@ -357,15 +388,11 @@ Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
template <> template <>
inline Arg::StringValue<char> ignore_incompatible_str( inline Arg::StringValue<char> ignore_incompatible_str(
Arg::StringValue<wchar_t>) { Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
return Arg::StringValue<char>();
}
template <> template <>
inline Arg::StringValue<wchar_t> ignore_incompatible_str( inline Arg::StringValue<wchar_t> ignore_incompatible_str(
Arg::StringValue<wchar_t> s) { Arg::StringValue<wchar_t> s) { return s; }
return s;
}
} // namespace } // namespace
FMT_FUNC void fmt::SystemError::init( FMT_FUNC void fmt::SystemError::init(
@ -397,12 +424,12 @@ int fmt::internal::CharTraits<wchar_t>::format_float(
unsigned width, int precision, T value) { unsigned width, int precision, T value) {
if (width == 0) { if (width == 0) {
return precision < 0 ? return precision < 0 ?
swprintf(buffer, size, format, value) : FMT_SWPRINTF(buffer, size, format, value) :
swprintf(buffer, size, format, precision, value); FMT_SWPRINTF(buffer, size, format, precision, value);
} }
return precision < 0 ? return precision < 0 ?
swprintf(buffer, size, format, width, value) : FMT_SWPRINTF(buffer, size, format, width, value) :
swprintf(buffer, size, format, width, precision, value); FMT_SWPRINTF(buffer, size, format, width, precision, value);
} }
template <typename T> template <typename T>
@ -440,6 +467,7 @@ const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
}; };
FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
(void)type;
if (std::isprint(static_cast<unsigned char>(code))) { if (std::isprint(static_cast<unsigned char>(code))) {
FMT_THROW(fmt::FormatError( FMT_THROW(fmt::FormatError(
fmt::format("unknown format code '{}' for {}", code, type))); fmt::format("unknown format code '{}' for {}", code, type)));
@ -496,8 +524,8 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void fmt::internal::format_system_error( FMT_FUNC void fmt::internal::format_system_error(
fmt::Writer &out, int error_code, fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
FMT_TRY{ FMT_TRY {
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer; MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE); buffer.resize(INLINE_BUFFER_SIZE);
for (;;) { for (;;) {
@ -518,22 +546,18 @@ FMT_FUNC void fmt::internal::format_system_error(
#ifdef _WIN32 #ifdef _WIN32
FMT_FUNC void fmt::internal::format_windows_error( FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code, fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
class String { class String {
private: private:
LPWSTR str_; LPWSTR str_;
public: public:
String() : str_() {} String() : str_() {}
~String() { ~String() { LocalFree(str_); }
LocalFree(str_); LPWSTR *ptr() { return &str_; }
}
LPWSTR *ptr() {
return &str_;
}
LPCWSTR c_str() const { return str_; } LPCWSTR c_str() const { return str_; }
}; };
FMT_TRY{ FMT_TRY {
String system_message; String system_message;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
@ -554,7 +578,7 @@ FMT_FUNC void fmt::internal::format_windows_error(
template <typename Char> template <typename Char>
class fmt::internal::ArgFormatter : class fmt::internal::ArgFormatter :
public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> { public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
private: private:
fmt::BasicFormatter<Char> &formatter_; fmt::BasicFormatter<Char> &formatter_;
fmt::BasicWriter<Char> &writer_; fmt::BasicWriter<Char> &writer_;
fmt::FormatSpec &spec_; fmt::FormatSpec &spec_;
@ -562,20 +586,16 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatter); FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatter);
public: public:
ArgFormatter( ArgFormatter(
fmt::BasicFormatter<Char> &f, fmt::FormatSpec &s, const Char *fmt) fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
: formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {} : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
template <typename T> template <typename T>
void visit_any_int(T value) { void visit_any_int(T value) { writer_.write_int(value, spec_); }
writer_.write_int(value, spec_);
}
template <typename T> template <typename T>
void visit_any_double(T value) { void visit_any_double(T value) { writer_.write_double(value, spec_); }
writer_.write_double(value, spec_);
}
void visit_char(int value) { void visit_char(int value) {
if (spec_.type_ && spec_.type_ != 'c') { if (spec_.type_ && spec_.type_ != 'c') {
@ -597,15 +617,12 @@ public:
if (spec_.align_ == fmt::ALIGN_RIGHT) { if (spec_.align_ == fmt::ALIGN_RIGHT) {
std::fill_n(out, spec_.width_ - 1, fill); std::fill_n(out, spec_.width_ - 1, fill);
out += spec_.width_ - 1; out += spec_.width_ - 1;
} } else if (spec_.align_ == fmt::ALIGN_CENTER) {
else if (spec_.align_ == fmt::ALIGN_CENTER) {
out = writer_.fill_padding(out, spec_.width_, 1, fill); out = writer_.fill_padding(out, spec_.width_, 1, fill);
} } else {
else {
std::fill_n(out + 1, spec_.width_ - 1, fill); std::fill_n(out + 1, spec_.width_ - 1, fill);
} }
} } else {
else {
out = writer_.grow_buffer(1); out = writer_.grow_buffer(1);
} }
*out = static_cast<Char>(value); *out = static_cast<Char>(value);
@ -631,6 +648,11 @@ public:
} }
}; };
template <typename Char>
void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
}
template <typename Char> template <typename Char>
template <typename StrChar> template <typename StrChar>
void fmt::BasicWriter<Char>::write_str( void fmt::BasicWriter<Char>::write_str(
@ -720,6 +742,7 @@ void fmt::internal::PrintfFormatter<Char>::parse_flags(
template <typename Char> template <typename Char>
Arg fmt::internal::PrintfFormatter<Char>::get_arg( Arg fmt::internal::PrintfFormatter<Char>::get_arg(
const Char *s, unsigned arg_index) { const Char *s, unsigned arg_index) {
(void)s;
const char *error = 0; const char *error = 0;
Arg arg = arg_index == UINT_MAX ? Arg arg = arg_index == UINT_MAX ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
@ -740,8 +763,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
if (*s == '$') { // value is an argument index if (*s == '$') { // value is an argument index
++s; ++s;
arg_index = value; arg_index = value;
} } else {
else {
if (c == '0') if (c == '0')
spec.fill_ = '0'; spec.fill_ = '0';
if (value != 0) { if (value != 0) {
@ -756,8 +778,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
// Parse width. // Parse width.
if (*s >= '0' && *s <= '9') { if (*s >= '0' && *s <= '9') {
spec.width_ = parse_nonnegative_int(s); spec.width_ = parse_nonnegative_int(s);
} } else if (*s == '*') {
else if (*s == '*') {
++s; ++s;
spec.width_ = WidthHandler(spec).visit(get_arg(s)); spec.width_ = WidthHandler(spec).visit(get_arg(s));
} }
@ -792,8 +813,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
++s; ++s;
if ('0' <= *s && *s <= '9') { if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s); spec.precision_ = parse_nonnegative_int(s);
} } else if (*s == '*') {
else if (*s == '*') {
++s; ++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s)); spec.precision_ = PrecisionHandler().visit(get_arg(s));
} }
@ -848,8 +868,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (arg.type <= Arg::LAST_INTEGER_TYPE) { if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type. // Normalize type.
switch (spec.type_) { switch (spec.type_) {
case 'i': case 'i': case 'u':
case 'u':
spec.type_ = 'd'; spec.type_ = 'd';
break; break;
case 'c': case 'c':
@ -886,12 +905,10 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (spec.align_ != ALIGN_LEFT) { if (spec.align_ != ALIGN_LEFT) {
std::fill_n(out, spec.width_ - 1, fill); std::fill_n(out, spec.width_ - 1, fill);
out += spec.width_ - 1; out += spec.width_ - 1;
} } else {
else {
std::fill_n(out + 1, spec.width_ - 1, fill); std::fill_n(out + 1, spec.width_ - 1, fill);
} }
} } else {
else {
out = writer.grow_buffer(1); out = writer.grow_buffer(1);
} }
*out = static_cast<Char>(arg.int_value); *out = static_cast<Char>(arg.int_value);
@ -916,7 +933,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
case Arg::POINTER: case Arg::POINTER:
if (spec.type_ && spec.type_ != 'p') if (spec.type_ && spec.type_ != 'p')
internal::report_unknown_type(spec.type_, "pointer"); internal::report_unknown_type(spec.type_, "pointer");
spec.flags_ = HASH_FLAG; spec.flags_= HASH_FLAG;
spec.type_ = 'x'; spec.type_ = 'x';
writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer), spec); writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer), spec);
break; break;
@ -972,8 +989,7 @@ const Char *fmt::BasicFormatter<Char>::format(
FMT_THROW(FormatError("invalid fill character '{'")); FMT_THROW(FormatError("invalid fill character '{'"));
s += 2; s += 2;
spec.fill_ = c; spec.fill_ = c;
} } else ++s;
else ++s;
if (spec.align_ == ALIGN_NUMERIC) if (spec.align_ == ALIGN_NUMERIC)
require_numeric_argument(arg, '='); require_numeric_argument(arg, '=');
break; break;
@ -1021,8 +1037,7 @@ const Char *fmt::BasicFormatter<Char>::format(
spec.precision_ = 0; spec.precision_ = 0;
if ('0' <= *s && *s <= '9') { if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s); spec.precision_ = parse_nonnegative_int(s);
} } else if (*s == '{') {
else if (*s == '{') {
++s; ++s;
const Arg &precision_arg = parse_arg_index(s); const Arg &precision_arg = parse_arg_index(s);
if (*s++ != '}') if (*s++ != '}')
@ -1051,8 +1066,7 @@ const Char *fmt::BasicFormatter<Char>::format(
if (value > INT_MAX) if (value > INT_MAX)
FMT_THROW(FormatError("number is too big")); FMT_THROW(FormatError("number is too big"));
spec.precision_ = static_cast<int>(value); spec.precision_ = static_cast<int>(value);
} } else {
else {
FMT_THROW(FormatError("missing precision specifier")); FMT_THROW(FormatError("missing precision specifier"));
} }
if (arg.type < Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) { if (arg.type < Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
@ -1099,13 +1113,13 @@ void fmt::BasicFormatter<Char>::format(
} }
FMT_FUNC void fmt::report_system_error( FMT_FUNC void fmt::report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_system_error, error_code, message); report_error(internal::format_system_error, error_code, message);
} }
#ifdef _WIN32 #ifdef _WIN32
FMT_FUNC void fmt::report_windows_error( FMT_FUNC void fmt::report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_windows_error, error_code, message); report_error(internal::format_windows_error, error_code, message);
} }
#endif #endif
@ -1141,8 +1155,12 @@ FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) {
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
} }
#ifndef FMT_HEADER_ONLY
// Explicit instantiations for char. // Explicit instantiations for char.
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
template const char *fmt::BasicFormatter<char>::format( template const char *fmt::BasicFormatter<char>::format(
const char *&format_str, const fmt::internal::Arg &arg); const char *&format_str, const fmt::internal::Arg &arg);
@ -1162,6 +1180,8 @@ template int fmt::internal::CharTraits<char>::format_float(
// Explicit instantiations for wchar_t. // Explicit instantiations for wchar_t.
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
template const wchar_t *fmt::BasicFormatter<wchar_t>::format( template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
const wchar_t *&format_str, const fmt::internal::Arg &arg); const wchar_t *&format_str, const fmt::internal::Arg &arg);
@ -1180,6 +1200,8 @@ template int fmt::internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format, wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value); unsigned width, int precision, long double value);
#endif // FMT_HEADER_ONLY
#if _MSC_VER #if _MSC_VER
# pragma warning(pop) # pragma warning(pop)
#endif #endif

File diff suppressed because it is too large Load Diff