Browse Source

Improve string formatting for %f and %v for inf and nan

Marcus Elg 3 years ago
parent
commit
b21460981d
2 changed files with 28 additions and 4 deletions
  1. 12 4
      core/string/ustring.cpp
  2. 16 0
      tests/core/string/test_string.h

+ 12 - 4
core/string/ustring.cpp

@@ -4637,15 +4637,18 @@ String String::sprintf(const Array &values, bool *error) const {
 					double value = values[value_index];
 					bool is_negative = (value < 0);
 					String str = String::num(ABS(value), min_decimals);
+					bool not_numeric = isinf(value) || isnan(value);
 
 					// Pad decimals out.
-					str = str.pad_decimals(min_decimals);
+					if (!not_numeric) {
+						str = str.pad_decimals(min_decimals);
+					}
 
 					int initial_len = str.length();
 
 					// Padding. Leave room for sign later if required.
 					int pad_chars_count = (is_negative || show_sign) ? min_chars - 1 : min_chars;
-					String pad_char = pad_with_zeros ? String("0") : String(" ");
+					String pad_char = (pad_with_zeros && !not_numeric) ? String("0") : String(" "); // Never pad NaN or inf with zeros
 					if (left_justified) {
 						str = str.rpad(pad_chars_count, pad_char);
 					} else {
@@ -4695,14 +4698,19 @@ String String::sprintf(const Array &values, bool *error) const {
 					String str = "(";
 					for (int i = 0; i < count; i++) {
 						double val = vec[i];
+						String number_str = String::num(ABS(val), min_decimals);
+						bool not_numeric = isinf(val) || isnan(val);
+
 						// Pad decimals out.
-						String number_str = String::num(ABS(val), min_decimals).pad_decimals(min_decimals);
+						if (!not_numeric) {
+							number_str = number_str.pad_decimals(min_decimals);
+						}
 
 						int initial_len = number_str.length();
 
 						// Padding. Leave room for sign later if required.
 						int pad_chars_count = val < 0 ? min_chars - 1 : min_chars;
-						String pad_char = pad_with_zeros ? String("0") : String(" ");
+						String pad_char = (pad_with_zeros && !not_numeric) ? String("0") : String(" "); // Never pad NaN or inf with zeros
 						if (left_justified) {
 							number_str = number_str.rpad(pad_chars_count, pad_char);
 						} else {

+ 16 - 0
tests/core/string/test_string.h

@@ -745,6 +745,14 @@ TEST_CASE("[String] sprintf") {
 	REQUIRE(error == false);
 	CHECK(output == String("fish   99.990000 frog"));
 
+	// Real (infinity) left-padded
+	format = "fish %11f frog";
+	args.clear();
+	args.push_back(INFINITY);
+	output = format.sprintf(args, &error);
+	REQUIRE(error == false);
+	CHECK(output == String("fish         inf frog"));
+
 	// Real right-padded.
 	format = "fish %-11f frog";
 	args.clear();
@@ -845,6 +853,14 @@ TEST_CASE("[String] sprintf") {
 	REQUIRE(error == false);
 	CHECK(output == String("fish (  19.990000,    1.000000,   -2.050000) frog"));
 
+	// Vector left-padded with inf/nan
+	format = "fish %11v frog";
+	args.clear();
+	args.push_back(Variant(Vector2(INFINITY, NAN)));
+	output = format.sprintf(args, &error);
+	REQUIRE(error == false);
+	CHECK(output == String("fish (        inf,         nan) frog"));
+
 	// Vector right-padded.
 	format = "fish %-11v frog";
 	args.clear();