summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Elg <marcusaccounts@yahoo.se>2022-07-31 17:50:02 +0200
committerMarcus Elg <marcusaccounts@yahoo.se>2022-08-23 17:26:06 +0200
commitdbc165715bb0bdcac73e22cf81c51529e48be07f (patch)
treef1f0ca13a1650004e9eb89da4c5f2d87a7e1d3f3
parent0c5f254956f0115e363ce08045dd178dc30b54f8 (diff)
Add %v for formatting vectors
-rw-r--r--core/string/ustring.cpp75
-rw-r--r--tests/core/string/test_string.h94
2 files changed, 164 insertions, 5 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index e93375bff7..dbe14d8c68 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -4664,6 +4664,71 @@ String String::sprintf(const Array &values, bool *error) const {
in_format = false;
break;
}
+ case 'v': { // Vector2/3/4/2i/3i/4i
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ int count;
+ switch (values[value_index].get_type()) {
+ case Variant::VECTOR2:
+ case Variant::VECTOR2I: {
+ count = 2;
+ } break;
+ case Variant::VECTOR3:
+ case Variant::VECTOR3I: {
+ count = 3;
+ } break;
+ case Variant::VECTOR4:
+ case Variant::VECTOR4I: {
+ count = 4;
+ } break;
+ default: {
+ return "%v requires a vector type (Vector2/3/4/2i/3i/4i)";
+ }
+ }
+
+ Vector4 vec = values[value_index];
+ String str = "(";
+ for (int i = 0; i < count; i++) {
+ double val = vec[i];
+ // Pad decimals out.
+ String number_str = String::num(ABS(val), min_decimals).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(" ");
+ if (left_justified) {
+ number_str = number_str.rpad(pad_chars_count, pad_char);
+ } else {
+ number_str = number_str.lpad(pad_chars_count, pad_char);
+ }
+
+ // Add sign if needed.
+ if (val < 0) {
+ if (left_justified) {
+ number_str = number_str.insert(0, "-");
+ } else {
+ number_str = number_str.insert(pad_with_zeros ? 0 : number_str.length() - initial_len, "-");
+ }
+ }
+
+ // Add number to combined string
+ str += number_str;
+
+ if (i < count - 1) {
+ str += ", ";
+ }
+ }
+ str += ")";
+
+ formatted += str;
+ ++value_index;
+ in_format = false;
+ break;
+ }
case 's': { // String
if (value_index >= values.size()) {
return "not enough arguments for format string";
@@ -4756,7 +4821,7 @@ String String::sprintf(const Array &values, bool *error) const {
}
break;
}
- case '.': { // Float separator.
+ case '.': { // Float/Vector separator.
if (in_decimals) {
return "too many decimal points in format";
}
@@ -4770,8 +4835,12 @@ String String::sprintf(const Array &values, bool *error) const {
return "not enough arguments for format string";
}
- if (!values[value_index].is_num()) {
- return "* wants number";
+ Variant::Type value_type = values[value_index].get_type();
+ if (!values[value_index].is_num() &&
+ value_type != Variant::VECTOR2 && value_type != Variant::VECTOR2I &&
+ value_type != Variant::VECTOR3 && value_type != Variant::VECTOR3I &&
+ value_type != Variant::VECTOR4 && value_type != Variant::VECTOR4I) {
+ return "* wants number or vector";
}
int size = values[value_index];
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 8914dbfd9a..e05757c98d 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -803,6 +803,96 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish -99.990000 frog"));
+ ////// VECTORS
+
+ // Vector2
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector2(19.99, 1.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000) frog"));
+
+ // Vector3
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000, -2.050000) frog"));
+
+ // Vector4
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector4(19.99, 1.00, -2.05, 5.5)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000, -2.050000, 5.500000) frog"));
+
+ // Vector with negative values
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector2(-19.99, -1.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (-19.990000, -1.000000) frog"));
+
+ // Vector left-padded
+ format = "fish %11v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish ( 19.990000, 1.000000, -2.050000) frog"));
+
+ // Vector right-padded
+ format = "fish %-11v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000 , 1.000000 , -2.050000 ) frog"));
+
+ // Vector left-padded with zeros
+ format = "fish %011v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (0019.990000, 0001.000000, -002.050000) frog"));
+
+ // Vector given Vector3i.
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector3i(19, 1, -2)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.000000, 1.000000, -2.000000) frog"));
+
+ // Vector with 1 decimals.
+ format = "fish %.1v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (20.0, 1.0, -2.0) frog"));
+
+ // Vector with 12 decimals.
+ format = "fish %.12v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.00, 1.00, -2.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.000000000000, 1.000000000000, -2.000000000000) frog"));
+
+ // Vector with no decimals.
+ format = "fish %.v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (20, 1, -2) frog"));
+
/////// Strings.
// String
@@ -920,14 +1010,14 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error);
CHECK(output == "too many decimal points in format");
- // * not a number
+ // * not a number or vector
format = "fish %*f frog";
args.clear();
args.push_back("cheese");
args.push_back(99.99);
output = format.sprintf(args, &error);
REQUIRE(error);
- CHECK(output == "* wants number");
+ CHECK(output == "* wants number or vector");
// Character too long.
format = "fish %c frog";