Skip to content

Commit 889410d

Browse files
Add String::replace_char(s) methods for performance and convenience
1 parent c374ce2 commit 889410d

File tree

67 files changed

+297
-137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+297
-137
lines changed

core/config/project_settings.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
173173

174174
if (dir->change_dir(path) == OK) {
175175
String cwd = dir->get_current_dir();
176-
cwd = cwd.replace("\\", "/");
176+
cwd = cwd.replace_char('\\', '/');
177177

178178
// Ensure that we end with a '/'.
179179
// This is important to ensure that we do not wrongly localize the resource path
@@ -591,7 +591,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
591591
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
592592
// OS will call ProjectSettings->get_resource_path which will be empty if not overridden!
593593
// If the OS would rather use a specific location, then it will not be empty.
594-
resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/");
594+
resource_path = OS::get_singleton()->get_resource_dir().replace_char('\\', '/');
595595
if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') {
596596
resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end.
597597
}
@@ -712,7 +712,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
712712
while (true) {
713713
// Set the resource path early so things can be resolved when loading.
714714
resource_path = current_dir;
715-
resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case.
715+
resource_path = resource_path.replace_char('\\', '/'); // Windows path to Unix path just in case.
716716
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
717717
if (err == OK && !p_ignore_override) {
718718
// Optional, we don't mind if it fails.

core/doc_data.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232

3333
String DocData::get_default_value_string(const Variant &p_value) {
3434
if (p_value.get_type() == Variant::ARRAY) {
35-
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
35+
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
3636
} else if (p_value.get_type() == Variant::DICTIONARY) {
37-
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
37+
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
3838
} else {
39-
return p_value.get_construct_string().replace("\n", " ");
39+
return p_value.get_construct_string().replace_char('\n', ' ');
4040
}
4141
}
4242

core/io/dir_access.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Error DirAccess::make_dir_recursive(const String &p_dir) {
146146
full_dir = p_dir;
147147
}
148148

149-
full_dir = full_dir.replace("\\", "/");
149+
full_dir = full_dir.replace_char('\\', '/');
150150

151151
String base;
152152

core/io/file_access.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ FileAccess::AccessType FileAccess::get_access_type() const {
259259
String FileAccess::fix_path(const String &p_path) const {
260260
// Helper used by file accesses that use a single filesystem.
261261

262-
String r_path = p_path.replace("\\", "/");
262+
String r_path = p_path.replace_char('\\', '/');
263263

264264
switch (_access_type) {
265265
case ACCESS_RESOURCES: {

core/io/file_access_pack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ String DirAccessPack::get_drive(int p_drive) {
548548
}
549549

550550
PackedData::PackedDir *DirAccessPack::_find_dir(const String &p_dir) {
551-
String nd = p_dir.replace("\\", "/");
551+
String nd = p_dir.replace_char('\\', '/');
552552

553553
// Special handling since simplify_path() will forbid it
554554
if (p_dir == "..") {

core/io/image.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,7 @@ void Image::initialize_data(const char **p_xpm) {
22942294
switch (status) {
22952295
case READING_HEADER: {
22962296
String line_str = line_ptr;
2297-
line_str.replace("\t", " ");
2297+
line_str.replace_char('\t', ' ');
22982298

22992299
size_width = line_str.get_slicec(' ', 0).to_int();
23002300
size_height = line_str.get_slicec(' ', 1).to_int();

core/io/logger.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void RotatedFileLogger::rotate_file() {
155155

156156
if (FileAccess::exists(base_path)) {
157157
if (max_files > 1) {
158-
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace(":", ".");
158+
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace_char(':', '.');
159159
String backup_name = base_path.get_basename() + timestamp;
160160
if (!base_path.get_extension().is_empty()) {
161161
backup_name += "." + base_path.get_extension();

core/os/os.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_paths) const
254254
if (p_allow_paths) {
255255
// Dir separators are allowed, but disallow ".." to avoid going up the filesystem
256256
invalid_chars.push_back("..");
257-
safe_dir_name = safe_dir_name.replace("\\", "/").replace("//", "/").strip_edges();
257+
safe_dir_name = safe_dir_name.replace_char('\\', '/').replace("//", "/").strip_edges();
258258
} else {
259259
invalid_chars.push_back("/");
260260
invalid_chars.push_back("\\");

core/string/translation_server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ TranslationServer::Locale::operator String() const {
135135

136136
TranslationServer::Locale::Locale(const TranslationServer &p_server, const String &p_locale, bool p_add_defaults) {
137137
// Replaces '-' with '_' for macOS style locales.
138-
String univ_locale = p_locale.replace("-", "_");
138+
String univ_locale = p_locale.replace_char('-', '_');
139139

140140
// Extract locale elements.
141141
Vector<String> locale_elements = univ_locale.get_slicec('@', 0).split("_");

core/string/ustring.cpp

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ String String::_camelcase_to_underscore() const {
925925
}
926926

927927
String String::capitalize() const {
928-
String aux = _camelcase_to_underscore().replace("_", " ").strip_edges();
928+
String aux = _camelcase_to_underscore().replace_char('_', ' ').strip_edges();
929929
String cap;
930930
for (int i = 0; i < aux.get_slice_count(" "); i++) {
931931
String slice = aux.get_slicec(' ', i);
@@ -954,7 +954,7 @@ String String::to_pascal_case() const {
954954
}
955955

956956
String String::to_snake_case() const {
957-
return _camelcase_to_underscore().replace(" ", "_").strip_edges();
957+
return _camelcase_to_underscore().replace_char(' ', '_').strip_edges();
958958
}
959959

960960
String String::get_with_code_lines() const {
@@ -4199,6 +4199,117 @@ String String::replace_first(const char *p_key, const char *p_with) const {
41994199
return *this;
42004200
}
42014201

4202+
String String::replace_char(char32_t p_key, char32_t p_with) const {
4203+
ERR_FAIL_COND_V_MSG(p_with == 0, *this, "`with` must not be the NUL character.");
4204+
4205+
if (p_key == 0) {
4206+
return *this;
4207+
}
4208+
4209+
int len = length();
4210+
if (len == 0) {
4211+
return *this;
4212+
}
4213+
4214+
int index = 0;
4215+
const char32_t *old_ptr = ptr();
4216+
for (; index < len; ++index) {
4217+
if (old_ptr[index] == p_key) {
4218+
break;
4219+
}
4220+
}
4221+
4222+
// If no occurrence of `key` was found, return this.
4223+
if (index == len) {
4224+
return *this;
4225+
}
4226+
4227+
// If we found at least one occurrence of `key`, create new string.
4228+
String new_string;
4229+
new_string.resize(len + 1);
4230+
char32_t *new_ptr = new_string.ptrw();
4231+
4232+
// Copy part of input before `key`.
4233+
memcpy(new_ptr, old_ptr, index * sizeof(char32_t));
4234+
4235+
new_ptr[index] = p_with;
4236+
4237+
// Copy or replace rest of input.
4238+
for (++index; index < len; ++index) {
4239+
if (old_ptr[index] == p_key) {
4240+
new_ptr[index] = p_with;
4241+
} else {
4242+
new_ptr[index] = old_ptr[index];
4243+
}
4244+
}
4245+
4246+
new_ptr[index] = _null;
4247+
4248+
return new_string;
4249+
}
4250+
4251+
template <class T>
4252+
static String _replace_chars_common(const String &p_this, const T *p_keys, int p_keys_len, char32_t p_with) {
4253+
ERR_FAIL_COND_V_MSG(p_with == 0, p_this, "`with` must not be the NUL character.");
4254+
4255+
// Delegate if p_keys is a single element.
4256+
if (p_keys_len == 1) {
4257+
return p_this.replace_char(*p_keys, p_with);
4258+
} else if (p_keys_len == 0) {
4259+
return p_this;
4260+
}
4261+
4262+
int len = p_this.length();
4263+
if (len == 0) {
4264+
return p_this;
4265+
}
4266+
4267+
int index = 0;
4268+
const char32_t *old_ptr = p_this.ptr();
4269+
for (; index < len; ++index) {
4270+
if (_contains_char(old_ptr[index], p_keys, p_keys_len)) {
4271+
break;
4272+
}
4273+
}
4274+
4275+
// If no occurrence of `keys` was found, return this.
4276+
if (index == len) {
4277+
return p_this;
4278+
}
4279+
4280+
// If we found at least one occurrence of `keys`, create new string.
4281+
String new_string;
4282+
new_string.resize(len + 1);
4283+
char32_t *new_ptr = new_string.ptrw();
4284+
4285+
// Copy part of input before `key`.
4286+
memcpy(new_ptr, old_ptr, index * sizeof(char32_t));
4287+
4288+
new_ptr[index] = p_with;
4289+
4290+
// Copy or replace rest of input.
4291+
for (++index; index < len; ++index) {
4292+
const char32_t old_char = old_ptr[index];
4293+
if (_contains_char(old_char, p_keys, p_keys_len)) {
4294+
new_ptr[index] = p_with;
4295+
} else {
4296+
new_ptr[index] = old_char;
4297+
}
4298+
}
4299+
4300+
new_ptr[index] = 0;
4301+
4302+
return new_string;
4303+
}
4304+
4305+
String String::replace_chars(const String &p_keys, char32_t p_with) const {
4306+
return _replace_chars_common(*this, p_keys.ptr(), p_keys.length(), p_with);
4307+
}
4308+
4309+
String String::replace_chars(const char *p_keys, char32_t p_with) const {
4310+
return _replace_chars_common(*this, p_keys, strlen(p_keys), p_with);
4311+
}
4312+
42024313
String String::replacen(const String &p_key, const String &p_with) const {
42034314
return _replace_common(*this, p_key, p_with, true);
42044315
}
@@ -4481,7 +4592,7 @@ String String::simplify_path() const {
44814592
}
44824593
}
44834594

4484-
s = s.replace("\\", "/");
4595+
s = s.replace_char('\\', '/');
44854596
while (true) { // in case of using 2 or more slash
44864597
String compare = s.replace("//", "/");
44874598
if (s == compare) {
@@ -5124,8 +5235,8 @@ bool String::is_valid_float() const {
51245235

51255236
String String::path_to_file(const String &p_path) const {
51265237
// Don't get base dir for src, this is expected to be a dir already.
5127-
String src = replace("\\", "/");
5128-
String dst = p_path.replace("\\", "/").get_base_dir();
5238+
String src = replace_char('\\', '/');
5239+
String dst = p_path.replace_char('\\', '/').get_base_dir();
51295240
String rel = src.path_to(dst);
51305241
if (rel == dst) { // failed
51315242
return p_path;
@@ -5135,8 +5246,8 @@ String String::path_to_file(const String &p_path) const {
51355246
}
51365247

51375248
String String::path_to(const String &p_path) const {
5138-
String src = replace("\\", "/");
5139-
String dst = p_path.replace("\\", "/");
5249+
String src = replace_char('\\', '/');
5250+
String dst = p_path.replace_char('\\', '/');
51405251
if (!src.ends_with("/")) {
51415252
src += "/";
51425253
}

0 commit comments

Comments
 (0)