Updates for formatting output as a percentage.

* Added percentage sign if needed when dumping nan and infinity.
* Added unit tests.
* Used clang-format for changed source files.
This commit is contained in:
gawain 2019-03-03 20:47:37 +01:00
parent 29db6bd91f
commit 73f31a8bcc
3 changed files with 31 additions and 15 deletions

View File

@ -539,8 +539,7 @@ struct fixed_stop {
void on_exp(int exp) {
if (!fixed) return;
exp += exp10;
if (exp >= 0)
precision += exp;
if (exp >= 0) precision += exp;
}
bool operator()(char*, int& size, uint64_t remainder, uint64_t divisor,
@ -660,9 +659,9 @@ void sprintf_format(Double value, internal::buffer& buf,
char type = spec.type;
if (type == '%') {
type = 'f';
type = 'f';
} else if (type == 0) {
type = 'g';
type = 'g';
}
#if FMT_MSC_VER
if (type == 'F') {

View File

@ -2646,10 +2646,12 @@ template <typename Range> class basic_writer {
struct inf_or_nan_writer {
char sign;
bool as_percentage;
const char* str;
size_t size() const {
return static_cast<std::size_t>(INF_SIZE + (sign ? 1 : 0));
return static_cast<std::size_t>(INF_SIZE + (sign ? 1 : 0) +
(as_percentage ? 1 : 0));
}
size_t width() const { return size(); }
@ -2657,6 +2659,7 @@ template <typename Range> class basic_writer {
if (sign) *it++ = static_cast<char_type>(sign);
it = internal::copy_str<char_type>(
str, str + static_cast<std::size_t>(INF_SIZE), it);
if (as_percentage) *it++ = static_cast<char_type>('%');
}
};
@ -2832,8 +2835,8 @@ struct float_spec_handler {
}
void on_percent() {
fixed = true;
as_percentage = true;
fixed = true;
as_percentage = true;
}
void on_hex() {
@ -2864,17 +2867,22 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
basic_writer& writer;
format_specs spec;
char sign;
bool as_percentage;
void operator()(const char* str) const {
writer.write_padded(spec, inf_or_nan_writer{sign, str});
writer.write_padded(spec, inf_or_nan_writer{sign, as_percentage, str});
}
} write_inf_or_nan = {*this, spec, sign};
} write_inf_or_nan = {*this, spec, sign, handler.as_percentage};
// Format NaN and ininity ourselves because sprintf's output is not consistent
// across platforms.
if (internal::fputil::isnotanumber(value))
return write_inf_or_nan(handler.upper ? "NAN" : "nan");
if (internal::fputil::isinfinity(value))
return write_inf_or_nan(handler.upper ? "INF" : "inf");
if (internal::fputil::isnotanumber(value)) {
write_inf_or_nan(handler.upper ? "NAN" : "nan");
return;
}
if (internal::fputil::isinfinity(value)) {
write_inf_or_nan(handler.upper ? "INF" : "inf");
return;
}
memory_buffer buffer;
int exp = 0;
@ -2889,8 +2897,8 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
if (!use_grisu) internal::sprintf_format(value, buffer, spec);
if (handler.as_percentage) {
buffer.push_back('%');
--exp; // Adjust decimal place position.
buffer.push_back('%');
--exp; // Adjust decimal place position.
}
align_spec as = spec;
if (spec.align() == ALIGN_NUMERIC) {

View File

@ -1207,6 +1207,8 @@ TEST(FormatterTest, Precision) {
"precision not allowed for this argument type");
EXPECT_THROW_MSG(format("{0:.2f}", 42ull), format_error,
"precision not allowed for this argument type");
EXPECT_THROW_MSG(format("{0:.2%}", 42), format_error,
"precision not allowed for this argument type");
EXPECT_THROW_MSG(format("{0:3.0}", 'x'), format_error,
"precision not allowed for this argument type");
EXPECT_EQ("1.2", format("{0:.2}", 1.2345));
@ -1440,6 +1442,7 @@ TEST(FormatterTest, FormatConvertibleToLongLong) {
TEST(FormatterTest, FormatFloat) {
EXPECT_EQ("392.500000", format("{0:f}", 392.5f));
EXPECT_EQ("12.500000%", format("{0:%}", 0.125f));
}
TEST(FormatterTest, FormatDouble) {
@ -1452,6 +1455,8 @@ TEST(FormatterTest, FormatDouble) {
EXPECT_EQ("392.65", format("{:G}", 392.65));
EXPECT_EQ("392.650000", format("{:f}", 392.65));
EXPECT_EQ("392.650000", format("{:F}", 392.65));
EXPECT_EQ("12.500000%", format("{:%}", 0.125));
EXPECT_EQ("12.34%", format("{:.2%}", 0.1234432));
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%e", 392.65);
EXPECT_EQ(buffer, format("{0:e}", 392.65));
@ -1473,6 +1478,7 @@ TEST(FormatterTest, FormatNaN) {
EXPECT_EQ("nan ", format("{:<7}", nan));
EXPECT_EQ(" nan ", format("{:^7}", nan));
EXPECT_EQ(" nan", format("{:>7}", nan));
EXPECT_EQ("nan%", format("{:%}", nan));
}
TEST(FormatterTest, FormatInfinity) {
@ -1485,6 +1491,7 @@ TEST(FormatterTest, FormatInfinity) {
EXPECT_EQ("inf ", format("{:<7}", inf));
EXPECT_EQ(" inf ", format("{:^7}", inf));
EXPECT_EQ(" inf", format("{:>7}", inf));
EXPECT_EQ("inf%", format("{:%}", inf));
}
TEST(FormatterTest, FormatLongDouble) {
@ -1495,6 +1502,8 @@ TEST(FormatterTest, FormatLongDouble) {
EXPECT_EQ("392.65", format("{0:G}", 392.65l));
EXPECT_EQ("392.650000", format("{0:f}", 392.65l));
EXPECT_EQ("392.650000", format("{0:F}", 392.65l));
EXPECT_EQ("12.500000%", format("{:%}", 0.125l));
EXPECT_EQ("12.34%", format("{:.2%}", 0.1234432l));
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%Le", 392.65l);
EXPECT_EQ(buffer, format("{0:e}", 392.65l));