summaryrefslogtreecommitdiffstats
path: root/core/string/ustring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/string/ustring.cpp')
-rw-r--r--core/string/ustring.cpp100
1 files changed, 71 insertions, 29 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index e6f7492a18..9e99fc3b2f 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -33,6 +33,7 @@
#include "core/crypto/crypto_core.h"
#include "core/math/color.h"
#include "core/math/math_funcs.h"
+#include "core/object/object.h"
#include "core/os/memory.h"
#include "core/string/print_string.h"
#include "core/string/string_name.h"
@@ -245,27 +246,27 @@ Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r
base = base.substr(pos + 3, base.length() - pos - 3);
}
}
- pos = base.find("#");
+ pos = base.find_char('#');
// Fragment
if (pos != -1) {
r_fragment = base.substr(pos + 1);
base = base.substr(0, pos);
}
- pos = base.find("/");
+ pos = base.find_char('/');
// Path
if (pos != -1) {
r_path = base.substr(pos, base.length() - pos);
base = base.substr(0, pos);
}
// Host
- pos = base.find("@");
+ pos = base.find_char('@');
if (pos != -1) {
// Strip credentials
base = base.substr(pos + 1, base.length() - pos - 1);
}
if (base.begins_with("[")) {
// Literal IPv6
- pos = base.rfind("]");
+ pos = base.rfind_char(']');
if (pos == -1) {
return ERR_INVALID_PARAMETER;
}
@@ -276,7 +277,7 @@ Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r
if (base.get_slice_count(":") > 2) {
return ERR_INVALID_PARAMETER;
}
- pos = base.rfind(":");
+ pos = base.rfind_char(':');
if (pos == -1) {
r_host = base;
base = "";
@@ -1818,7 +1819,7 @@ String String::num(double p_num, int p_decimals) {
#endif
buf[324] = 0;
- //destroy trailing zeroes
+ // Destroy trailing zeroes, except one after period.
{
bool period = false;
int z = 0;
@@ -1835,7 +1836,7 @@ String String::num(double p_num, int p_decimals) {
if (buf[z] == '0') {
buf[z] = 0;
} else if (buf[z] == '.') {
- buf[z] = 0;
+ buf[z + 1] = '0';
break;
} else {
break;
@@ -1850,6 +1851,8 @@ String String::num(double p_num, int p_decimals) {
}
String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
+ ERR_FAIL_COND_V_MSG(base < 2 || base > 36, "", "Cannot convert to base " + itos(base) + ", since the value is " + (base < 2 ? "less than 2." : "greater than 36."));
+
bool sign = p_num < 0;
int64_t n = p_num;
@@ -1888,6 +1891,8 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
}
String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
+ ERR_FAIL_COND_V_MSG(base < 2 || base > 36, "", "Cannot convert to base " + itos(base) + ", since the value is " + (base < 2 ? "less than 2." : "greater than 36."));
+
uint64_t n = p_num;
int chars = 0;
@@ -1924,14 +1929,28 @@ String String::num_real(double p_num, bool p_trailing) {
return num_int64((int64_t)p_num);
}
}
-#ifdef REAL_T_IS_DOUBLE
int decimals = 14;
-#else
+ // We want to align the digits to the above sane default, so we only need
+ // to subtract log10 for numbers with a positive power of ten magnitude.
+ const double abs_num = Math::abs(p_num);
+ if (abs_num > 10) {
+ decimals -= (int)floor(log10(abs_num));
+ }
+ return num(p_num, decimals);
+}
+
+String String::num_real(float p_num, bool p_trailing) {
+ if (p_num == (float)(int64_t)p_num) {
+ if (p_trailing) {
+ return num_int64((int64_t)p_num) + ".0";
+ } else {
+ return num_int64((int64_t)p_num);
+ }
+ }
int decimals = 6;
-#endif
// We want to align the digits to the above sane default, so we only need
// to subtract log10 for numbers with a positive power of ten magnitude.
- double abs_num = Math::abs(p_num);
+ const float abs_num = Math::abs(p_num);
if (abs_num > 10) {
decimals -= (int)floor(log10(abs_num));
}
@@ -2622,7 +2641,7 @@ int64_t String::to_int() const {
return 0;
}
- int to = (find(".") >= 0) ? find(".") : length();
+ int to = (find_char('.') >= 0) ? find_char('.') : length();
int64_t integer = 0;
int64_t sign = 1;
@@ -3368,7 +3387,7 @@ int String::find(const char *p_str, int p_from) const {
return -1;
}
-int String::find_char(const char32_t &p_char, int p_from) const {
+int String::find_char(char32_t p_char, int p_from) const {
return _cowdata.find(p_char, p_from);
}
@@ -3605,6 +3624,10 @@ int String::rfind(const char *p_str, int p_from) const {
return -1;
}
+int String::rfind_char(char32_t p_char, int p_from) const {
+ return _cowdata.rfind(p_char, p_from);
+}
+
int String::rfindn(const String &p_str, int p_from) const {
// establish a limit
int limit = length() - p_str.length();
@@ -3818,6 +3841,15 @@ bool String::is_quoted() const {
return is_enclosed_in("\"") || is_enclosed_in("'");
}
+bool String::is_lowercase() const {
+ for (const char32_t *str = &operator[](0); *str; str++) {
+ if (is_unicode_upper_case(*str)) {
+ return false;
+ }
+ }
+ return true;
+}
+
int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const {
if (p_string.is_empty()) {
return 0;
@@ -4060,8 +4092,18 @@ String String::format(const Variant &values, const String &placeholder) const {
for (const Variant &key : keys) {
new_string = new_string.replace(placeholder.replace("_", key), d[key]);
}
+ } else if (values.get_type() == Variant::OBJECT) {
+ Object *obj = values.get_validated_object();
+ ERR_FAIL_NULL_V(obj, new_string);
+
+ List<PropertyInfo> props;
+ obj->get_property_list(&props);
+
+ for (const PropertyInfo &E : props) {
+ new_string = new_string.replace(placeholder.replace("_", E.name), obj->get(E.name));
+ }
} else {
- ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data());
+ ERR_PRINT(String("Invalid type: use Array, Dictionary or Object.").ascii().get_data());
}
return new_string;
@@ -4538,7 +4580,7 @@ String String::simplify_path() const {
if (p == -1) {
p = s.find(":\\");
}
- if (p != -1 && p < s.find("/")) {
+ if (p != -1 && p < s.find_char('/')) {
drive = s.substr(0, p + 2);
s = s.substr(p + 2);
}
@@ -4601,7 +4643,7 @@ String String::humanize_size(uint64_t p_size) {
}
if (magnitude == 0) {
- return String::num(p_size) + " " + RTR("B");
+ return String::num_uint64(p_size) + " " + RTR("B");
} else {
String suffix;
switch (magnitude) {
@@ -4983,7 +5025,7 @@ String String::xml_unescape() const {
String String::pad_decimals(int p_digits) const {
String s = *this;
- int c = s.find(".");
+ int c = s.find_char('.');
if (c == -1) {
if (p_digits <= 0) {
@@ -5007,7 +5049,7 @@ String String::pad_decimals(int p_digits) const {
String String::pad_zeros(int p_digits) const {
String s = *this;
- int end = s.find(".");
+ int end = s.find_char('.');
if (end == -1) {
end = s.length();
@@ -5274,7 +5316,7 @@ String String::validate_filename() const {
}
bool String::is_valid_ip_address() const {
- if (find(":") >= 0) {
+ if (find_char(':') >= 0) {
Vector<String> ip = split(":");
for (int i = 0; i < ip.size(); i++) {
const String &n = ip[i];
@@ -5344,13 +5386,13 @@ String String::get_base_dir() const {
// Windows UNC network share path.
if (end == 0) {
if (is_network_share_path()) {
- basepos = find("/", 2);
+ basepos = find_char('/', 2);
if (basepos == -1) {
- basepos = find("\\", 2);
+ basepos = find_char('\\', 2);
}
- int servpos = find("/", basepos + 1);
+ int servpos = find_char('/', basepos + 1);
if (servpos == -1) {
- servpos = find("\\", basepos + 1);
+ servpos = find_char('\\', basepos + 1);
}
if (servpos != -1) {
end = servpos + 1;
@@ -5374,7 +5416,7 @@ String String::get_base_dir() const {
rs = *this;
}
- int sep = MAX(rs.rfind("/"), rs.rfind("\\"));
+ int sep = MAX(rs.rfind_char('/'), rs.rfind_char('\\'));
if (sep == -1) {
return base;
}
@@ -5383,7 +5425,7 @@ String String::get_base_dir() const {
}
String String::get_file() const {
- int sep = MAX(rfind("/"), rfind("\\"));
+ int sep = MAX(rfind_char('/'), rfind_char('\\'));
if (sep == -1) {
return *this;
}
@@ -5392,8 +5434,8 @@ String String::get_file() const {
}
String String::get_extension() const {
- int pos = rfind(".");
- if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) {
+ int pos = rfind_char('.');
+ if (pos < 0 || pos < MAX(rfind_char('/'), rfind_char('\\'))) {
return "";
}
@@ -5491,8 +5533,8 @@ String String::validate_node_name() const {
}
String String::get_basename() const {
- int pos = rfind(".");
- if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) {
+ int pos = rfind_char('.');
+ if (pos < 0 || pos < MAX(rfind_char('/'), rfind_char('\\'))) {
return *this;
}