Commit e928b672 authored by Victor Zverovich's avatar Victor Zverovich

Fix MSVC 2013 build

parent ec218a3a
...@@ -948,10 +948,10 @@ struct get_type { ...@@ -948,10 +948,10 @@ struct get_type {
}; };
template <typename Context> 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> 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); return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
} }
...@@ -995,27 +995,32 @@ class format_arg_store { ...@@ -995,27 +995,32 @@ class format_arg_store {
internal::value<Context>, basic_format_arg<Context>>::type value_type; internal::value<Context>, basic_format_arg<Context>>::type value_type;
// If the arguments are not packed, add one more element to mark the end. // 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>; friend class basic_format_args<Context>;
static FMT_CONSTEXPR int64_t get_types() { static FMT_CONSTEXPR long long get_types() {
return IS_PACKED ? return IS_PACKED ?
static_cast<int64_t>(internal::get_types<Context, Args...>()) : static_cast<long long>(internal::get_types<Context, Args...>()) :
-static_cast<int64_t>(NUM_ARGS); -static_cast<long long>(NUM_ARGS);
} }
public: public:
#if FMT_USE_CONSTEXPR #if FMT_USE_CONSTEXPR
static constexpr int64_t TYPES = get_types(); static constexpr long long TYPES = get_types();
#else #else
static const int64_t TYPES; static const long long TYPES;
#endif #endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405 #if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
// Workaround an array initialization bug in gcc 4.5 and earlier. (FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store(const Args &... args) { 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 #else
format_arg_store(const Args &... args) format_arg_store(const Args &... args)
...@@ -1025,7 +1030,7 @@ class format_arg_store { ...@@ -1025,7 +1030,7 @@ class format_arg_store {
#if !FMT_USE_CONSTEXPR #if !FMT_USE_CONSTEXPR
template <typename Context, typename ...Args> 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 #endif
/** /**
...@@ -1057,7 +1062,7 @@ class basic_format_args { ...@@ -1057,7 +1062,7 @@ class basic_format_args {
private: private:
// To reduce compiled code size per formatting function call, types of first // To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field. // max_packed_args arguments are passed in the types_ field.
uint64_t types_; unsigned long long types_;
union { union {
// If the number of arguments is less than max_packed_args, the argument // If the number of arguments is less than max_packed_args, the argument
// values are stored in values_, otherwise they are stored in args_. // values are stored in values_, otherwise they are stored in args_.
...@@ -1070,7 +1075,7 @@ class basic_format_args { ...@@ -1070,7 +1075,7 @@ class basic_format_args {
typename internal::type type(unsigned index) const { typename internal::type type(unsigned index) const {
unsigned shift = index * 4; unsigned shift = index * 4;
uint64_t mask = 0xf; unsigned long long mask = 0xf;
return static_cast<typename internal::type>( return static_cast<typename internal::type>(
(types_ & (mask << shift)) >> shift); (types_ & (mask << shift)) >> shift);
} }
...@@ -1081,9 +1086,9 @@ class basic_format_args { ...@@ -1081,9 +1086,9 @@ class basic_format_args {
void set_data(const format_arg *args) { args_ = args; } void set_data(const format_arg *args) { args_ = args; }
format_arg do_get(size_type index) const { 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) { 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(); return index < num_args ? args_[index] : format_arg();
} }
format_arg arg; format_arg arg;
...@@ -1119,10 +1124,10 @@ class basic_format_args { ...@@ -1119,10 +1124,10 @@ class basic_format_args {
} }
unsigned max_size() const { 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>( return static_cast<unsigned>(
signed_types < 0 ? 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 { ...@@ -1293,28 +1293,6 @@ struct align_spec : empty_spec {
// Format specifiers. // Format specifiers.
template <typename Char> template <typename Char>
class basic_format_specs : public align_spec { 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: public:
unsigned flags_; unsigned flags_;
int precision_; int precision_;
...@@ -1324,12 +1302,6 @@ class basic_format_specs : public align_spec { ...@@ -1324,12 +1302,6 @@ class basic_format_specs : public align_spec {
unsigned width = 0, char type = 0, wchar_t fill = ' ') unsigned width = 0, char type = 0, wchar_t fill = ' ')
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {} : 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 bool flag(unsigned f) const { return (flags_ & f) != 0; }
FMT_CONSTEXPR int precision() const { return precision_; } FMT_CONSTEXPR int precision() const { return precision_; }
FMT_CONSTEXPR Char type() const { return type_; } FMT_CONSTEXPR Char type() const { return type_; }
...@@ -1576,7 +1548,18 @@ class arg_formatter_base { ...@@ -1576,7 +1548,18 @@ class arg_formatter_base {
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type typename std::enable_if<std::is_integral<T>::value, iterator>::type
operator()(T value) { 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(); return out();
} }
...@@ -1587,13 +1570,6 @@ class arg_formatter_base { ...@@ -1587,13 +1570,6 @@ class arg_formatter_base {
return out(); 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 { struct char_spec_handler : internal::error_handler {
arg_formatter_base &formatter; arg_formatter_base &formatter;
char_type value; char_type value;
...@@ -1605,11 +1581,6 @@ class arg_formatter_base { ...@@ -1605,11 +1581,6 @@ class arg_formatter_base {
void on_char() { formatter.write_char(value); } 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 { struct cstring_spec_handler : internal::error_handler {
arg_formatter_base &formatter; arg_formatter_base &formatter;
const char_type *value; const char_type *value;
......
...@@ -252,23 +252,33 @@ class printf_arg_formatter: ...@@ -252,23 +252,33 @@ class printf_arg_formatter:
using base::operator(); using base::operator();
/** Formats an argument of type ``bool``. */ template <typename T>
iterator operator()(bool value) { typename std::enable_if<std::is_integral<T>::value, iterator>::type
format_specs &fmt_spec = this->spec(); operator()(T value) {
if (fmt_spec.type_ != 's') // MSVC2013 fails to compile separate overloads for bool and char_type so
return (*this)(value ? 1 : 0); // use std::is_same instead.
fmt_spec.type_ = 0; if (std::is_same<T, bool>::value) {
this->write(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(); return this->out();
} }
/** Formats a character. */ template <typename T>
iterator operator()(char_type value) { typename std::enable_if<std::is_floating_point<T>::value, iterator>::type
format_specs &fmt_spec = this->spec(); operator()(T value) {
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); return base::operator()(value);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment