summaryrefslogtreecommitdiffstats
path: root/core/string
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2023-04-06 17:54:56 +0200
committerJuan Linietsky <reduzio@gmail.com>2023-04-07 13:18:47 +0200
commit223ce4fcb958619d0f3c62e79a2b5846240e7ff3 (patch)
tree89536f9be2d90bbeee7f74b67032076fc0357e39 /core/string
parent92b7a9603aa2395be6bf361067096538ba393c45 (diff)
downloadredot-engine-223ce4fcb958619d0f3c62e79a2b5846240e7ff3.tar.gz
Optimize Node::add_child validation
Adding 10k nodes is almost twice as fast.
Diffstat (limited to 'core/string')
-rw-r--r--core/string/ustring.cpp79
-rw-r--r--core/string/ustring.h3
2 files changed, 75 insertions, 7 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 773445edb6..73b5bc2d56 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -2593,6 +2593,23 @@ double String::to_float(const wchar_t *p_str, const wchar_t **r_end) {
return built_in_strtod<wchar_t>(p_str, (wchar_t **)r_end);
}
+uint32_t String::num_characters(int64_t p_int) {
+ int r = 1;
+ if (p_int < 0) {
+ r += 1;
+ if (p_int == INT64_MIN) {
+ p_int = INT64_MAX;
+ } else {
+ p_int = -p_int;
+ }
+ }
+ while (p_int >= 10) {
+ p_int /= 10;
+ r++;
+ }
+ return r;
+}
+
int64_t String::to_int(const char32_t *p_str, int p_len, bool p_clamp) {
if (p_len == 0 || !p_str[0]) {
return 0;
@@ -4561,15 +4578,65 @@ String String::property_name_encode() const {
}
// Changes made to the set of invalid characters must also be reflected in the String documentation.
-const String String::invalid_node_name_characters = ". : @ / \" " UNIQUE_NODE_PREFIX;
+
+static const char32_t invalid_node_name_characters[] = { '.', ':', '@', '/', '\"', UNIQUE_NODE_PREFIX[0], 0 };
+
+String String::get_invalid_node_name_characters() {
+ // Do not use this function for critical validation.
+ String r;
+ const char32_t *c = invalid_node_name_characters;
+ while (*c) {
+ if (c != invalid_node_name_characters) {
+ r += " ";
+ }
+ r += String::chr(*c);
+ c++;
+ }
+ return r;
+}
String String::validate_node_name() const {
- Vector<String> chars = String::invalid_node_name_characters.split(" ");
- String name = this->replace(chars[0], "");
- for (int i = 1; i < chars.size(); i++) {
- name = name.replace(chars[i], "");
+ // This is a critical validation in node addition, so it must be optimized.
+ const char32_t *cn = ptr();
+ if (cn == nullptr) {
+ return String();
}
- return name;
+ bool valid = true;
+ uint32_t idx = 0;
+ while (cn[idx]) {
+ const char32_t *c = invalid_node_name_characters;
+ while (*c) {
+ if (cn[idx] == *c) {
+ valid = false;
+ break;
+ }
+ c++;
+ }
+ if (!valid) {
+ break;
+ }
+ idx++;
+ }
+
+ if (valid) {
+ return *this;
+ }
+
+ String validated = *this;
+ char32_t *nn = validated.ptrw();
+ while (nn[idx]) {
+ const char32_t *c = invalid_node_name_characters;
+ while (*c) {
+ if (nn[idx] == *c) {
+ nn[idx] = '_';
+ break;
+ }
+ c++;
+ }
+ idx++;
+ }
+
+ return validated;
}
String String::get_basename() const {
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 90034b1b07..e1512cfb26 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -337,6 +337,7 @@ public:
static double to_float(const char *p_str);
static double to_float(const wchar_t *p_str, const wchar_t **r_end = nullptr);
static double to_float(const char32_t *p_str, const char32_t **r_end = nullptr);
+ static uint32_t num_characters(int64_t p_int);
String capitalize() const;
String to_camel_case() const;
@@ -432,7 +433,7 @@ public:
String property_name_encode() const;
// node functions
- static const String invalid_node_name_characters;
+ static String get_invalid_node_name_characters();
String validate_node_name() const;
String validate_identifier() const;
String validate_filename() const;