From a65542bdaf208e8f186d342f691c75268cce6349 Mon Sep 17 00:00:00 2001 From: Gregory Czajkowski Date: Mon, 18 Nov 2013 22:58:39 -0800 Subject: [PATCH] add support for unsigned long long Want to be able to format the following without any casting std::cout << fmt::str(fmt::Format("{:x}") << 0xAEull) << std::endl; std::cout << fmt::str(fmt::Format("{:x}") << 0xAEul) << std::endl; std::cout << fmt::str(fmt::Format("{:x}") << uint64_t(0xae)) << std::endl; --- format.cc | 12 +++++++++--- format.h | 11 +++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/format.cc b/format.cc index caddd3ad..4be211e5 100644 --- a/format.cc +++ b/format.cc @@ -400,7 +400,7 @@ void fmt::BasicFormatter::CheckSign(const Char *&s, const Arg &arg) { ReportError(s, Format("format specifier '{0}' requires numeric argument") << *s); } - if (arg.type == UINT || arg.type == ULONG) { + if (arg.type == UINT || arg.type == ULONG || arg.type == ULLONG) { ReportError(s, Format("format specifier '{0}' requires signed argument") << *s); } @@ -519,7 +519,7 @@ void fmt::BasicFormatter::DoFormat() { ++s; ++num_open_braces_; const Arg &precision_arg = ParseArgIndex(s); - unsigned long value = 0; + unsigned long long value = 0; switch (precision_arg.type) { case INT: if (precision_arg.int_value < 0) @@ -537,12 +537,15 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: value = precision_arg.ulong_value; break; + case ULLONG: + value = precision_arg.ulong_long_value; + break; default: ReportError(s, "precision is not integer"); } if (value > INT_MAX) ReportError(s, "number is too big in format"); - precision = value; + precision = static_cast(value); if (*s++ != '}') throw FormatError("unmatched '{' in format"); --num_open_braces_; @@ -578,6 +581,9 @@ void fmt::BasicFormatter::DoFormat() { case ULONG: writer.FormatInt(arg.ulong_value, spec); break; + case ULLONG: + writer.FormatInt(arg.ulong_long_value, spec); + break; case DOUBLE: writer.FormatDouble(arg.double_value, spec, precision); break; diff --git a/format.h b/format.h index d7c2b9f4..f4ed7720 100644 --- a/format.h +++ b/format.h @@ -189,6 +189,9 @@ struct SignedIntTraits { template <> struct IntTraits : SignedIntTraits {}; +template <> +struct IntTraits : SignedIntTraits {}; + template <> struct IntTraits : SignedIntTraits {}; @@ -444,6 +447,7 @@ DEFINE_INT_FORMATTERS(int) DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned long) +DEFINE_INT_FORMATTERS(unsigned long long) template class BasicFormatter; @@ -811,7 +815,7 @@ class BasicFormatter { enum Type { // Numeric types should go first. - INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE, + INT, UINT, LONG, ULONG, ULLONG, DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, CHAR, STRING, WSTRING, POINTER, CUSTOM }; @@ -846,6 +850,7 @@ class BasicFormatter { double double_value; long long_value; unsigned long ulong_value; + unsigned long long ulong_long_value; long double long_double_value; const void *pointer_value; struct { @@ -865,6 +870,7 @@ class BasicFormatter { Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {} Arg(long value) : type(LONG), long_value(value), formatter(0) {} Arg(unsigned long value) : type(ULONG), ulong_value(value), formatter(0) {} + Arg(unsigned long long value) : type(ULLONG), ulong_long_value(value), formatter(0) {} Arg(float value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(long double value) @@ -1148,7 +1154,7 @@ class FormatInt { enum {BUFFER_SIZE = std::numeric_limits::digits10 + 3}; char buffer_[BUFFER_SIZE]; char *str_; - + // Formats value in reverse and returns the number of digits. char *FormatDecimal(uint64_t value) { char *buffer_end = buffer_ + BUFFER_SIZE; @@ -1183,6 +1189,7 @@ class FormatInt { *--str_ = '-'; } explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} + explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {} const char *c_str() const { return str_; } std::string str() const { return str_; }