diff --git a/format.cc b/format.cc index 895a7961..9e479fc4 100644 --- a/format.cc +++ b/format.cc @@ -171,27 +171,29 @@ const Char *find_closing_brace(const Char *s, int num_open_braces = 1) { // Checks if an argument is a valid printf width specifier and sets // left alignment if it is negative. -struct WidthHandler : public fmt::internal::ArgVisitor { +struct WidthHandler : public fmt::internal::ArgVisitor { private: fmt::FormatSpec &spec_; public: explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {} - ULongLong visit_unhandled_arg() { + unsigned visit_unhandled_arg() { throw fmt::FormatError("width is not integer"); } - ULongLong visit_any_int(fmt::LongLong value) { - ULongLong width = value; - if (value < 0) { + template + unsigned visit_any_int(T value) { + typedef typename fmt::internal::IntTraits::MainType UnsignedType; + UnsignedType width = value; + if (fmt::internal::is_negative(value)) { spec_.align_ = fmt::ALIGN_LEFT; width = 0 - width; } - return width; + if (width > INT_MAX) + throw fmt::FormatError("number is too big in format"); + return static_cast(width); } - - ULongLong visit_any_uint(ULongLong value) { return value; } }; // This function template is used to prevent compile errors when handling @@ -421,24 +423,11 @@ class fmt::internal::ArgFormatter : ArgFormatter(fmt::BasicWriter &w, fmt::FormatSpec &s, const Char *fmt) : writer_(w), spec_(s), format_(fmt) {} - void visit_int(int value) { - writer_.FormatInt(value, spec_); - } - void visit_uint(unsigned value) { - writer_.FormatInt(value, spec_); - } - void visit_long_long(LongLong value) { - writer_.FormatInt(value, spec_); - } - void visit_ulong_long(ULongLong value) { - writer_.FormatInt(value, spec_); - } - void visit_double(double value) { - writer_.FormatDouble(value, spec_); - } - void visit_long_double(long double value) { - writer_.FormatDouble(value, spec_); - } + template + void visit_any_int(T value) { writer_.FormatInt(value, spec_); } + + template + void visit_any_double(T value) { writer_.FormatDouble(value, spec_); } void visit_char(int value) { if (spec_.type_ && spec_.type_ != 'c') @@ -773,11 +762,7 @@ unsigned fmt::internal::PrintfParser::ParseHeader( spec.width_ = ParseNonnegativeInt(s, error); } else if (*s == '*') { ++s; - ULongLong width = WidthHandler(spec).visit(HandleArgIndex(UINT_MAX, error)); - if (width <= INT_MAX) - spec.width_ = static_cast(width); - else if (!error) - error = "number is too big in format"; + spec.width_ = WidthHandler(spec).visit(HandleArgIndex(UINT_MAX, error)); } return arg_index; } diff --git a/format.h b/format.h index 6a30dbac..fec1099f 100644 --- a/format.h +++ b/format.h @@ -393,20 +393,20 @@ struct TypeSelector { typedef uint64_t Type; }; template struct SignChecker { template - static bool IsNegative(T) { return false; } + static bool is_negative(T) { return false; } }; template <> struct SignChecker { template - static bool IsNegative(T value) { return value < 0; } + static bool is_negative(T value) { return value < 0; } }; // Returns true if value is negative, false otherwise. // Same as (value < 0) but doesn't produce warnings if T is an unsigned type. template -inline bool IsNegative(T value) { - return SignChecker::is_signed>::IsNegative(value); +inline bool is_negative(T value) { + return SignChecker::is_signed>::is_negative(value); } int SignBitNoInline(double value); @@ -734,31 +734,47 @@ class ArgVisitor { Result visit_unhandled_arg() { return Result(); } Result visit_int(int value) { - return FMT_DISPATCH(visit_any_int(value)); + return FMT_DISPATCH(visit_any_signed(value)); } Result visit_long_long(LongLong value) { - return FMT_DISPATCH(visit_any_int(value)); + return FMT_DISPATCH(visit_any_signed(value)); } - Result visit_any_int(LongLong) { - return FMT_DISPATCH(visit_unhandled_arg()); + + // Visit any signed integer. + template + Result visit_any_signed(T value) { + return FMT_DISPATCH(visit_any_int(value)); } Result visit_uint(unsigned value) { - return FMT_DISPATCH(visit_any_uint(value)); + return FMT_DISPATCH(visit_any_unsigned(value)); } Result visit_ulong_long(ULongLong value) { - return FMT_DISPATCH(visit_any_uint(value)); + return FMT_DISPATCH(visit_any_unsigned(value)); } - Result visit_any_uint(ULongLong) { + + // Visit any unsigned integer. + template + Result visit_any_unsigned(T value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + template + Result visit_any_int(T) { return FMT_DISPATCH(visit_unhandled_arg()); } - Result visit_double(double) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - Result visit_long_double(long double) { + Result visit_double(double value) { + return FMT_DISPATCH(visit_any_double(value)); + } + Result visit_long_double(long double value) { + return FMT_DISPATCH(visit_any_double(value)); + } + template + Result visit_any_double(T) { return FMT_DISPATCH(visit_unhandled_arg()); } + Result visit_char(int) { return FMT_DISPATCH(visit_unhandled_arg()); } @@ -1603,7 +1619,7 @@ void BasicWriter::FormatInt(T value, const Spec &spec) { typedef typename internal::IntTraits::MainType UnsignedType; UnsignedType abs_value = value; char prefix[4] = ""; - if (internal::IsNegative(value)) { + if (internal::is_negative(value)) { prefix[0] = '-'; ++prefix_size; abs_value = 0 - abs_value; @@ -1892,7 +1908,7 @@ class FormatInt { template inline void FormatDec(char *&buffer, T value) { typename internal::IntTraits::MainType abs_value = value; - if (internal::IsNegative(value)) { + if (internal::is_negative(value)) { *buffer++ = '-'; abs_value = 0 - abs_value; }