-
-
Notifications
You must be signed in to change notification settings - Fork 21k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add String::replace_char(s)
methods for performance and convenience
#92475
base: master
Are you sure you want to change the base?
Add String::replace_char(s)
methods for performance and convenience
#92475
Conversation
String::replace_char(s)
methods for performanceString::replace_char(s)
methods for performance and convenience
989058a
to
d029832
Compare
611a214
to
6a49079
Compare
92cb3e7
to
4b78ad7
Compare
const char32_t *old_ptr = ptr(); | ||
|
||
while (*old_ptr) { | ||
if (p_keys.has(*old_ptr)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could have the keys be copied and then sorted here and use bsearch
instead but not sure it'll be worth it generally, not expecting large arrays here so the difference between O(n)
and O(log n)
will be marginal compared to the copying and sorting
++old_ptr; | ||
} | ||
|
||
*new_ptrw = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a const _null
for the zero car.
Impressive work!! I did some quick performance testing. I'm concern with the fact that each characters are copied one by one in the Test 1 (character replaced 14 times):Source string: "C:\Projects\godot-jolt\build\windows-msvc-x64\External\Build\jolt\CMakeFiles_CMakeLTOTest-CXX\bin\CMakeFiles\boo.dir\Debug\main.cpp.obj" Using Test 2 (character not replaced):Source string: "C:\Projects\godot-jolt\build\windows-msvc-x64\External\Build\jolt\CMakeFiles_CMakeLTOTest-CXX\bin\CMakeFiles\boo.dir\Debug\main.cpp.obj" Using Test 3 (small string 1 replace):Source string: "te_st" Using Test 4 (small string and character not replaced):Source string: "test" Using Alternative suggested version that does not update the string if search char not found and using memcpy:String String::replace_char(char32_t p_key, char32_t p_with) const {
ERR_FAIL_COND_V_MSG(p_with == 0, String(), "`with` must not be null.");
int len = length();
if (p_key == 0 || len == 0) {
return *this;
}
int index = 0;
const char32_t *old_ptr = ptr();
for (; index < len; index++) {
if (*old_ptr == p_key) {
break;
}
++old_ptr;
}
if (index == len) {
return *this;
}
String new_string;
new_string.resize(len + 1);
char32_t *new_ptrw = new_string.ptrw();
memcpy(new_ptrw, ptr(), len * sizeof(char32_t));
new_ptrw += index;
*new_ptrw = p_with;
++new_ptrw;
++old_ptr;
while (*old_ptr) {
if (*old_ptr == p_key) {
*new_ptrw = p_with;
}
++new_ptrw;
++old_ptr;
}
*new_ptrw = _null;
return new_string;
}
|
I'll take a look and measure some between these, I have some theories, I feel a method checking for existence and then using my method for replacement might be faster as it accesses twice not thrice, but will see and compare Thank you! |
4b78ad7
to
2ba2944
Compare
cedf230
to
6e6cbbb
Compare
6e6cbbb
to
6303e15
Compare
6303e15
to
5fdd528
Compare
Will try do some performance comparison soon, but these replace in-place essentially, avoiding any COW or other manipulation, and also avoids creating any temporaries etc.
The multi-character one is optional but added for completeness for a few cases where multiple cases are replaced at once
Can expose to scripting if desired, but generally using characters is a bit more complicated in scripting so haven't added yet
Kept as separate commits for ease of editing until approval
See #92433 (comment)
A few more complex cases like
String::validate_filename
,OS::get_safe_dir_name
, andget_csharp_project_name
could be replaced using this, instead using a vector of characters, but for right now I keep this to the simple cases (mostly, seeAnimationLibrary::validate_library_name
for an exception)See also:
String::remove_char(s)
methods for performance and convenience #92476