mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-09 06:00:07 +00:00
Fix MSVC 2013 build
This commit is contained in:
parent
ec218a3ad1
commit
e928b6724c
@ -948,10 +948,10 @@ struct get_type {
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
FMT_CONSTEXPR uint64_t get_types() { return 0; }
|
||||
FMT_CONSTEXPR unsigned long long get_types() { return 0; }
|
||||
|
||||
template <typename Context, typename Arg, typename... Args>
|
||||
FMT_CONSTEXPR uint64_t get_types() {
|
||||
FMT_CONSTEXPR unsigned long long get_types() {
|
||||
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
|
||||
}
|
||||
|
||||
@ -995,27 +995,32 @@ class format_arg_store {
|
||||
internal::value<Context>, basic_format_arg<Context>>::type value_type;
|
||||
|
||||
// If the arguments are not packed, add one more element to mark the end.
|
||||
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
|
||||
static const size_t DATA_SIZE =
|
||||
NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);
|
||||
value_type data_[DATA_SIZE];
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
|
||||
static FMT_CONSTEXPR int64_t get_types() {
|
||||
static FMT_CONSTEXPR long long get_types() {
|
||||
return IS_PACKED ?
|
||||
static_cast<int64_t>(internal::get_types<Context, Args...>()) :
|
||||
-static_cast<int64_t>(NUM_ARGS);
|
||||
static_cast<long long>(internal::get_types<Context, Args...>()) :
|
||||
-static_cast<long long>(NUM_ARGS);
|
||||
}
|
||||
|
||||
public:
|
||||
#if FMT_USE_CONSTEXPR
|
||||
static constexpr int64_t TYPES = get_types();
|
||||
static constexpr long long TYPES = get_types();
|
||||
#else
|
||||
static const int64_t TYPES;
|
||||
static const long long TYPES;
|
||||
#endif
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
|
||||
// Workaround an array initialization bug in gcc 4.5 and earlier.
|
||||
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
|
||||
(FMT_MSC_VER && FMT_MSC_VER <= 1800)
|
||||
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
|
||||
format_arg_store(const Args &... args) {
|
||||
data_ = {internal::make_arg<IS_PACKED, Context>(args)...};
|
||||
value_type init[DATA_SIZE] =
|
||||
{internal::make_arg<IS_PACKED, Context>(args)...};
|
||||
std::memcpy(data_, init, sizeof(init));
|
||||
}
|
||||
#else
|
||||
format_arg_store(const Args &... args)
|
||||
@ -1025,7 +1030,7 @@ class format_arg_store {
|
||||
|
||||
#if !FMT_USE_CONSTEXPR
|
||||
template <typename Context, typename ...Args>
|
||||
const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
|
||||
const long long format_arg_store<Context, Args...>::TYPES = get_types();
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -1057,7 +1062,7 @@ class basic_format_args {
|
||||
private:
|
||||
// To reduce compiled code size per formatting function call, types of first
|
||||
// max_packed_args arguments are passed in the types_ field.
|
||||
uint64_t types_;
|
||||
unsigned long long types_;
|
||||
union {
|
||||
// If the number of arguments is less than max_packed_args, the argument
|
||||
// values are stored in values_, otherwise they are stored in args_.
|
||||
@ -1070,7 +1075,7 @@ class basic_format_args {
|
||||
|
||||
typename internal::type type(unsigned index) const {
|
||||
unsigned shift = index * 4;
|
||||
uint64_t mask = 0xf;
|
||||
unsigned long long mask = 0xf;
|
||||
return static_cast<typename internal::type>(
|
||||
(types_ & (mask << shift)) >> shift);
|
||||
}
|
||||
@ -1081,9 +1086,9 @@ class basic_format_args {
|
||||
void set_data(const format_arg *args) { args_ = args; }
|
||||
|
||||
format_arg do_get(size_type index) const {
|
||||
int64_t signed_types = static_cast<int64_t>(types_);
|
||||
long long signed_types = static_cast<long long>(types_);
|
||||
if (signed_types < 0) {
|
||||
uint64_t num_args = static_cast<uint64_t>(-signed_types);
|
||||
unsigned long long num_args = static_cast<unsigned long long>(-signed_types);
|
||||
return index < num_args ? args_[index] : format_arg();
|
||||
}
|
||||
format_arg arg;
|
||||
@ -1119,10 +1124,10 @@ class basic_format_args {
|
||||
}
|
||||
|
||||
unsigned max_size() const {
|
||||
int64_t signed_types = static_cast<int64_t>(types_);
|
||||
long long signed_types = static_cast<long long>(types_);
|
||||
return static_cast<unsigned>(
|
||||
signed_types < 0 ?
|
||||
-signed_types : static_cast<int64_t>(internal::max_packed_args));
|
||||
-signed_types : static_cast<long long>(internal::max_packed_args));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1293,28 +1293,6 @@ struct align_spec : empty_spec {
|
||||
// Format specifiers.
|
||||
template <typename Char>
|
||||
class basic_format_specs : public align_spec {
|
||||
private:
|
||||
template <typename FillChar>
|
||||
typename std::enable_if<std::is_same<FillChar, Char>::value ||
|
||||
std::is_same<FillChar, char>::value, void>::type
|
||||
set(fill_spec<FillChar> fill) {
|
||||
fill_ = fill.value();
|
||||
}
|
||||
|
||||
void set(width_spec width) {
|
||||
width_ = width.value();
|
||||
}
|
||||
|
||||
void set(type_spec type) {
|
||||
type_ = type.value();
|
||||
}
|
||||
|
||||
template <typename Spec, typename... Specs>
|
||||
void set(Spec spec, Specs... tail) {
|
||||
set(spec);
|
||||
set(tail...);
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned flags_;
|
||||
int precision_;
|
||||
@ -1324,12 +1302,6 @@ class basic_format_specs : public align_spec {
|
||||
unsigned width = 0, char type = 0, wchar_t fill = ' ')
|
||||
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {}
|
||||
|
||||
template <typename... FormatSpecs>
|
||||
explicit basic_format_specs(FormatSpecs... specs)
|
||||
: align_spec(0, ' '), flags_(0), precision_(-1), type_(0) {
|
||||
set(specs...);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR bool flag(unsigned f) const { return (flags_ & f) != 0; }
|
||||
FMT_CONSTEXPR int precision() const { return precision_; }
|
||||
FMT_CONSTEXPR Char type() const { return type_; }
|
||||
@ -1576,7 +1548,18 @@ class arg_formatter_base {
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, iterator>::type
|
||||
operator()(T value) {
|
||||
writer_.write_int(value, specs_);
|
||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||
// use std::is_same instead.
|
||||
if (std::is_same<T, bool>::value) {
|
||||
if (specs_.type_)
|
||||
return (*this)(value ? 1 : 0);
|
||||
write(value);
|
||||
} else if (std::is_same<T, char_type>::value) {
|
||||
internal::handle_char_specs(
|
||||
specs_, char_spec_handler(*this, static_cast<char_type>(value)));
|
||||
} else {
|
||||
writer_.write_int(value, specs_);
|
||||
}
|
||||
return out();
|
||||
}
|
||||
|
||||
@ -1587,13 +1570,6 @@ class arg_formatter_base {
|
||||
return out();
|
||||
}
|
||||
|
||||
iterator operator()(bool value) {
|
||||
if (specs_.type_)
|
||||
return (*this)(value ? 1 : 0);
|
||||
write(value);
|
||||
return out();
|
||||
}
|
||||
|
||||
struct char_spec_handler : internal::error_handler {
|
||||
arg_formatter_base &formatter;
|
||||
char_type value;
|
||||
@ -1605,11 +1581,6 @@ class arg_formatter_base {
|
||||
void on_char() { formatter.write_char(value); }
|
||||
};
|
||||
|
||||
iterator operator()(char_type value) {
|
||||
internal::handle_char_specs(specs_, char_spec_handler(*this, value));
|
||||
return out();
|
||||
}
|
||||
|
||||
struct cstring_spec_handler : internal::error_handler {
|
||||
arg_formatter_base &formatter;
|
||||
const char_type *value;
|
||||
|
@ -252,23 +252,33 @@ class printf_arg_formatter:
|
||||
|
||||
using base::operator();
|
||||
|
||||
/** Formats an argument of type ``bool``. */
|
||||
iterator operator()(bool value) {
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return (*this)(value ? 1 : 0);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value);
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, iterator>::type
|
||||
operator()(T value) {
|
||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||
// use std::is_same instead.
|
||||
if (std::is_same<T, bool>::value) {
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return base::operator()(value ? 1 : 0);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value);
|
||||
} else if (std::is_same<T, char_type>::value) {
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_spec.flags_ = 0;
|
||||
fmt_spec.align_ = ALIGN_RIGHT;
|
||||
return base::operator()(value);
|
||||
} else {
|
||||
return base::operator()(value);
|
||||
}
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats a character. */
|
||||
iterator operator()(char_type value) {
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_spec.flags_ = 0;
|
||||
fmt_spec.align_ = ALIGN_RIGHT;
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value, iterator>::type
|
||||
operator()(T value) {
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user