mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-11-22 00:48:09 +01:00
Ported from godot 4: Optimize Node::add_child validation
Adding 10k nodes is almost twice as fast.
- reduz
223ce4fcb9
This commit is contained in:
parent
a14b058dc4
commit
8ab1998fcb
@ -4669,15 +4669,66 @@ 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 = ". : @ / \" %";
|
||||
|
||||
static const char32_t invalid_node_name_characters[] = { '.', ':', '@', '/', '\"', '%', 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;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ bool _is_valid_identifier_bit(int p_index, char32_t p_char) {
|
||||
@ -5604,6 +5655,23 @@ double String::to_double(const CharType *p_str, const CharType **r_end) {
|
||||
return built_in_strtod<CharType>(p_str, (CharType **)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;
|
||||
}
|
||||
|
||||
bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
|
||||
int len = length();
|
||||
if (len == 0) {
|
||||
|
@ -387,6 +387,8 @@ public:
|
||||
static double to_double(const wchar_t *p_str, const wchar_t **r_end = nullptr);
|
||||
static double to_double(const CharType *p_str, const CharType **r_end = nullptr);
|
||||
|
||||
static uint32_t num_characters(int64_t p_int);
|
||||
|
||||
String capitalize() const;
|
||||
String camelcase_to_underscore(bool lowercase = true) const;
|
||||
|
||||
@ -500,7 +502,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;
|
||||
|
||||
|
@ -856,7 +856,7 @@ void SceneTreeEditor::_renamed() {
|
||||
String raw_new_name = which->get_text(0);
|
||||
String new_name = raw_new_name.validate_node_name();
|
||||
if (new_name != raw_new_name) {
|
||||
error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + String::invalid_node_name_characters);
|
||||
error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + String::get_invalid_node_name_characters());
|
||||
error->popup_centered_minsize();
|
||||
|
||||
if (new_name.empty()) {
|
||||
|
@ -1346,8 +1346,31 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
|
||||
|
||||
if (!unique) {
|
||||
ERR_FAIL_COND(!node_hrcr_count.ref());
|
||||
String name = "@" + String(p_child->get_name()) + "@" + itos(node_hrcr_count.get());
|
||||
p_child->data.name = name;
|
||||
|
||||
// Optimized version of the code below:
|
||||
// String name = "@" + String(p_child->get_name()) + "@" + itos(node_hrcr_count.get());
|
||||
uint32_t c = node_hrcr_count.get();
|
||||
String cn = p_child->get_class_name().operator String();
|
||||
const char32_t *cn_ptr = cn.ptr();
|
||||
uint32_t cn_length = cn.length();
|
||||
uint32_t c_chars = String::num_characters(c);
|
||||
uint32_t len = 2 + cn_length + c_chars;
|
||||
char32_t *str = (char32_t *)alloca(sizeof(char32_t) * (len + 1));
|
||||
uint32_t idx = 0;
|
||||
str[idx++] = '@';
|
||||
for (uint32_t i = 0; i < cn_length; i++) {
|
||||
str[idx++] = cn_ptr[i];
|
||||
}
|
||||
str[idx++] = '@';
|
||||
idx += c_chars;
|
||||
ERR_FAIL_COND(idx != len);
|
||||
str[idx] = 0;
|
||||
while (c) {
|
||||
str[--idx] = '0' + (c % 10);
|
||||
c /= 10;
|
||||
}
|
||||
|
||||
p_child->data.name = String(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user