Browse Source

Improve usage of String.split() vs get_slice()

kobewi 2 years ago
parent
commit
d61a337a70

+ 2 - 2
core/config/project_settings.cpp

@@ -280,7 +280,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
 	if (p_value.get_type() == Variant::NIL) {
 	if (p_value.get_type() == Variant::NIL) {
 		props.erase(p_name);
 		props.erase(p_name);
 		if (p_name.operator String().begins_with("autoload/")) {
 		if (p_name.operator String().begins_with("autoload/")) {
-			String node_name = p_name.operator String().split("/")[1];
+			String node_name = p_name.operator String().get_slicec('/', 1);
 			if (autoloads.has(node_name)) {
 			if (autoloads.has(node_name)) {
 				remove_autoload(node_name);
 				remove_autoload(node_name);
 			}
 			}
@@ -326,7 +326,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
 			props[p_name] = VariantContainer(p_value, last_order++);
 			props[p_name] = VariantContainer(p_value, last_order++);
 		}
 		}
 		if (p_name.operator String().begins_with("autoload/")) {
 		if (p_name.operator String().begins_with("autoload/")) {
-			String node_name = p_name.operator String().split("/")[1];
+			String node_name = p_name.operator String().get_slicec('/', 1);
 			AutoloadInfo autoload;
 			AutoloadInfo autoload;
 			autoload.name = node_name;
 			autoload.name = node_name;
 			String path = p_value;
 			String path = p_value;

+ 1 - 2
core/input/input.cpp

@@ -1756,8 +1756,7 @@ void Input::parse_mapping(const String &p_mapping) {
 void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
 void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
 	parse_mapping(p_mapping);
 	parse_mapping(p_mapping);
 	if (p_update_existing) {
 	if (p_update_existing) {
-		Vector<String> entry = p_mapping.split(",");
-		const String &uid = entry[0];
+		const String uid = p_mapping.get_slicec(',', 0);
 		for (KeyValue<int, Joypad> &E : joy_names) {
 		for (KeyValue<int, Joypad> &E : joy_names) {
 			Joypad &joy = E.value;
 			Joypad &joy = E.value;
 			if (joy.uid == uid) {
 			if (joy.uid == uid) {

+ 4 - 6
core/input/input_map.cpp

@@ -843,9 +843,8 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
 	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
 	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
 		String fullname = E.key;
 		String fullname = E.key;
 
 
-		Vector<String> split = fullname.split(".");
-		const String &name = split[0];
-		String override_for = split.size() > 1 ? split[1] : String();
+		const String &name = fullname.get_slicec('.', 0);
+		String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
 
 
 		if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
 		if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
 			builtins_with_overrides[name].push_back(override_for);
 			builtins_with_overrides[name].push_back(override_for);
@@ -855,9 +854,8 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
 	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
 	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
 		String fullname = E.key;
 		String fullname = E.key;
 
 
-		Vector<String> split = fullname.split(".");
-		const String &name = split[0];
-		String override_for = split.size() > 1 ? split[1] : String();
+		const String &name = fullname.get_slicec('.', 0);
+		String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
 
 
 		if (builtins_with_overrides.has(name) && override_for.is_empty()) {
 		if (builtins_with_overrides.has(name) && override_for.is_empty()) {
 			// Builtin has an override but this particular one is not an override, so skip.
 			// Builtin has an override but this particular one is not an override, so skip.

+ 8 - 2
doc/classes/String.xml

@@ -331,7 +331,7 @@
 			<param index="1" name="slice" type="int" />
 			<param index="1" name="slice" type="int" />
 			<description>
 			<description>
 				Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns the original string if [param delimiter] does not occur in the string. Returns an empty string if the [param slice] does not exist.
 				Splits the string using a [param delimiter] and returns the substring at index [param slice]. Returns the original string if [param delimiter] does not occur in the string. Returns an empty string if the [param slice] does not exist.
-				This is faster than [method split], if you only need one substring.
+				This is faster than [method split], if you only need one or two substrings.
 				[codeblock]
 				[codeblock]
 				print("i/am/example/hi".get_slice("/", 2)) # Prints "example"
 				print("i/am/example/hi".get_slice("/", 2)) # Prints "example"
 				[/codeblock]
 				[/codeblock]
@@ -342,6 +342,11 @@
 			<param index="0" name="delimiter" type="String" />
 			<param index="0" name="delimiter" type="String" />
 			<description>
 			<description>
 				Returns the total number of slices when the string is split with the given [param delimiter] (see [method split]).
 				Returns the total number of slices when the string is split with the given [param delimiter] (see [method split]).
+				Use [method get_slice] to extract a specific slice.
+				[codeblock]
+				print("i/am/example/string".get_slice_count("/")) # Prints '4'.
+				print("i am example string".get_slice_count("/")) # Prints '1'.
+				[/codeblock]
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="get_slicec" qualifiers="const">
 		<method name="get_slicec" qualifiers="const">
@@ -350,7 +355,8 @@
 			<param index="1" name="slice" type="int" />
 			<param index="1" name="slice" type="int" />
 			<description>
 			<description>
 				Splits the string using a Unicode character with code [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
 				Splits the string using a Unicode character with code [param delimiter] and returns the substring at index [param slice]. Returns an empty string if the [param slice] does not exist.
-				This is faster than [method split], if you only need one substring.
+				This is faster than [method split], if you only need one or two substrings.
+				This is a Unicode version of [method get_slice].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="hash" qualifiers="const">
 		<method name="hash" qualifiers="const">

+ 1 - 1
editor/debugger/script_editor_debugger.cpp

@@ -1879,7 +1879,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
 			}
 			}
 
 
 			// Parse back the `file:line @ method()` string.
 			// Parse back the `file:line @ method()` string.
-			const Vector<String> file_line_number = ci->get_text(1).split("@")[0].strip_edges().split(":");
+			const Vector<String> file_line_number = ci->get_text(1).get_slicec('@', 0).strip_edges().split(":");
 			ERR_FAIL_COND_MSG(file_line_number.size() < 2, "Incorrect C++ source stack trace file:line format (please report).");
 			ERR_FAIL_COND_MSG(file_line_number.size() < 2, "Incorrect C++ source stack trace file:line format (please report).");
 			const String &file = file_line_number[0];
 			const String &file = file_line_number[0];
 			const int line_number = file_line_number[1].to_int();
 			const int line_number = file_line_number[1].to_int();

+ 6 - 8
editor/inspector/editor_inspector.cpp

@@ -3783,10 +3783,9 @@ void EditorInspector::update_tree() {
 			subgroup = p.name;
 			subgroup = p.name;
 			subgroup_togglable_property = nullptr;
 			subgroup_togglable_property = nullptr;
 
 
-			Vector<String> hint_parts = p.hint_string.split(",");
-			subgroup_base = hint_parts[0];
-			if (hint_parts.size() > 1) {
-				section_depth = hint_parts[1].to_int();
+			subgroup_base = p.hint_string.get_slicec(',', 0);
+			if (p.hint_string.get_slice_count(",") > 1) {
+				section_depth = p.hint_string.get_slicec(',', 1).to_int();
 			} else {
 			} else {
 				section_depth = 0;
 				section_depth = 0;
 			}
 			}
@@ -3798,10 +3797,9 @@ void EditorInspector::update_tree() {
 			group = p.name;
 			group = p.name;
 			group_togglable_property = nullptr;
 			group_togglable_property = nullptr;
 
 
-			Vector<String> hint_parts = p.hint_string.split(",");
-			group_base = hint_parts[0];
-			if (hint_parts.size() > 1) {
-				section_depth = hint_parts[1].to_int();
+			group_base = p.hint_string.get_slicec(',', 0);
+			if (p.hint_string.get_slice_count(",") > 1) {
+				section_depth = p.hint_string.get_slicec(',', 1).to_int();
 			} else {
 			} else {
 				section_depth = 0;
 				section_depth = 0;
 			}
 			}

+ 3 - 4
editor/inspector/editor_properties.cpp

@@ -835,11 +835,10 @@ void EditorPropertyEnum::setup(const Vector<String> &p_options) {
 	HashMap<int64_t, Vector<String>> items;
 	HashMap<int64_t, Vector<String>> items;
 	int64_t current_val = 0;
 	int64_t current_val = 0;
 	for (const String &option : p_options) {
 	for (const String &option : p_options) {
-		Vector<String> text_split = option.split(":");
-		if (text_split.size() != 1) {
-			current_val = text_split[1].to_int();
+		if (option.get_slice_count(":") != 1) {
+			current_val = option.get_slicec(':', 1).to_int();
 		}
 		}
-		items[current_val].push_back(text_split[0]);
+		items[current_val].push_back(option.get_slicec(':', 0));
 		current_val += 1;
 		current_val += 1;
 	}
 	}
 
 

+ 1 - 1
editor/scene/2d/tiles/tile_set_atlas_source_editor.cpp

@@ -867,7 +867,7 @@ void TileSetAtlasSourceEditor::_update_current_tile_data_editor() {
 	// Find the property to use.
 	// Find the property to use.
 	String property;
 	String property;
 	if (tools_button_group->get_pressed_button() == tool_select_button && tile_inspector->is_visible() && !tile_inspector->get_selected_path().is_empty()) {
 	if (tools_button_group->get_pressed_button() == tool_select_button && tile_inspector->is_visible() && !tile_inspector->get_selected_path().is_empty()) {
-		Vector<String> components = tile_inspector->get_selected_path().split("/");
+		Vector<String> components = tile_inspector->get_selected_path().split("/", true, 1);
 		if (components.size() >= 1) {
 		if (components.size() >= 1) {
 			property = components[0];
 			property = components[0];
 
 

+ 1 - 1
editor/script/script_create_dialog.cpp

@@ -492,7 +492,7 @@ void ScriptCreateDialog::_file_selected(const String &p_file) {
 }
 }
 
 
 void ScriptCreateDialog::_create() {
 void ScriptCreateDialog::_create() {
-	parent_name->set_text(select_class->get_selected_type().split(" ")[0]);
+	parent_name->set_text(select_class->get_selected_type().get_slicec(' ', 0));
 	_parent_name_changed(parent_name->get_text());
 	_parent_name_changed(parent_name->get_text());
 }
 }
 
 

+ 1 - 1
editor/shader/visual_shader_editor_plugin.cpp

@@ -1668,7 +1668,7 @@ void VisualShaderEditor::add_custom_type(const String &p_name, const String &p_t
 	ao.is_native = !p_type.is_empty();
 	ao.is_native = !p_type.is_empty();
 
 
 	bool begin = false;
 	bool begin = false;
-	String root = p_category.split("/")[0];
+	String root = p_category.get_slicec('/', 0);
 
 
 	for (int i = 0; i < add_options.size(); i++) {
 	for (int i = 0; i < add_options.size(); i++) {
 		if (add_options[i].is_custom) {
 		if (add_options[i].is_custom) {

+ 2 - 3
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -773,9 +773,8 @@ const LSP::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const LSP::TextDocu
 	String path = get_file_path(p_doc_pos.textDocument.uri);
 	String path = get_file_path(p_doc_pos.textDocument.uri);
 	if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
 	if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
 		String symbol_identifier = p_symbol_name;
 		String symbol_identifier = p_symbol_name;
-		Vector<String> identifier_parts = symbol_identifier.split("(");
-		if (identifier_parts.size()) {
-			symbol_identifier = identifier_parts[0];
+		if (symbol_identifier.get_slice_count("(") > 0) {
+			symbol_identifier = symbol_identifier.get_slicec('(', 0);
 		}
 		}
 
 
 		LSP::Position pos = p_doc_pos.position;
 		LSP::Position pos = p_doc_pos.position;

+ 1 - 1
platform/android/os_android.cpp

@@ -602,7 +602,7 @@ Vector<String> OS_Android::get_system_font_path_for_text(const String &p_font_na
 		font_name = font_aliases[font_name];
 		font_name = font_aliases[font_name];
 	}
 	}
 	String root = String(getenv("ANDROID_ROOT")).path_join("fonts");
 	String root = String(getenv("ANDROID_ROOT")).path_join("fonts");
-	String lang_prefix = p_locale.split("_")[0];
+	String lang_prefix = p_locale.get_slicec('_', 0);
 	Vector<String> ret;
 	Vector<String> ret;
 	int best_score = 0;
 	int best_score = 0;
 	for (const List<FontInfo>::Element *E = fonts.front(); E; E = E->next()) {
 	for (const List<FontInfo>::Element *E = fonts.front(); E; E = E->next()) {

+ 2 - 2
platform/linuxbsd/os_linuxbsd.cpp

@@ -210,7 +210,7 @@ String OS_LinuxBSD::get_processor_name() const {
 	while (!f->eof_reached()) {
 	while (!f->eof_reached()) {
 		const String line = f->get_line();
 		const String line = f->get_line();
 		if (line.to_lower().contains("model name")) {
 		if (line.to_lower().contains("model name")) {
-			return line.split(":")[1].strip_edges();
+			return line.get_slicec(':', 1).strip_edges();
 		}
 		}
 	}
 	}
 #endif
 #endif
@@ -295,7 +295,7 @@ String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
 		while (!f->eof_reached()) {
 		while (!f->eof_reached()) {
 			const String line = f->get_line();
 			const String line = f->get_line();
 			if (line.contains(key)) {
 			if (line.contains(key)) {
-				String value = line.split("=")[1].strip_edges();
+				String value = line.get_slicec('=', 1).strip_edges();
 				value = value.trim_prefix("\"");
 				value = value.trim_prefix("\"");
 				return value.trim_suffix("\"");
 				return value.trim_suffix("\"");
 			}
 			}

+ 1 - 3
scene/animation/animation_node_state_machine.cpp

@@ -1534,9 +1534,7 @@ bool AnimationNodeStateMachine::_can_connect(const StringName &p_name) {
 	}
 	}
 
 
 	String node_name = p_name;
 	String node_name = p_name;
-	Vector<String> path = node_name.split("/");
-
-	if (path.size() < 2) {
+	if (node_name.get_slice_count("/") < 2) {
 		return false;
 		return false;
 	}
 	}
 
 

+ 4 - 3
scene/debugger/scene_debugger.cpp

@@ -647,10 +647,11 @@ void SceneDebugger::_set_object_property(ObjectID p_id, const String &p_property
 		return;
 		return;
 	}
 	}
 
 
-	String prop_name = p_property;
+	String prop_name;
 	if (p_property.begins_with("Members/")) {
 	if (p_property.begins_with("Members/")) {
-		Vector<String> ss = p_property.split("/");
-		prop_name = ss[ss.size() - 1];
+		prop_name = p_property.get_slicec('/', p_property.get_slice_count("/") - 1);
+	} else {
+		prop_name = p_property;
 	}
 	}
 
 
 	Variant value;
 	Variant value;

+ 4 - 6
scene/resources/visual_shader.cpp

@@ -4835,8 +4835,7 @@ void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
 	int count = 0;
 	int count = 0;
 	int index = 0;
 	int index = 0;
 	for (int i = 0; i < inputs_strings.size(); i++) {
 	for (int i = 0; i < inputs_strings.size(); i++) {
-		Vector<String> arr = inputs_strings[i].split(",");
-		if (arr[0].to_int() == p_id) {
+		if (inputs_strings[i].get_slicec(',', 0).to_int() == p_id) {
 			count = inputs_strings[i].size();
 			count = inputs_strings[i].size();
 			break;
 			break;
 		}
 		}
@@ -4848,7 +4847,7 @@ void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
 	inputs = inputs.substr(0, index);
 	inputs = inputs.substr(0, index);
 
 
 	for (int i = p_id; i < inputs_strings.size(); i++) {
 	for (int i = p_id; i < inputs_strings.size(); i++) {
-		inputs += inputs_strings[i].replace_first(inputs_strings[i].split(",")[0], itos(i)) + ";";
+		inputs += inputs_strings[i].replace_first(inputs_strings[i].get_slicec(',', 0), itos(i)) + ";";
 	}
 	}
 
 
 	_apply_port_changes();
 	_apply_port_changes();
@@ -4910,8 +4909,7 @@ void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
 	int count = 0;
 	int count = 0;
 	int index = 0;
 	int index = 0;
 	for (int i = 0; i < outputs_strings.size(); i++) {
 	for (int i = 0; i < outputs_strings.size(); i++) {
-		Vector<String> arr = outputs_strings[i].split(",");
-		if (arr[0].to_int() == p_id) {
+		if (outputs_strings[i].get_slicec(',', 0).to_int() == p_id) {
 			count = outputs_strings[i].size();
 			count = outputs_strings[i].size();
 			break;
 			break;
 		}
 		}
@@ -4923,7 +4921,7 @@ void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
 	outputs = outputs.substr(0, index);
 	outputs = outputs.substr(0, index);
 
 
 	for (int i = p_id; i < outputs_strings.size(); i++) {
 	for (int i = p_id; i < outputs_strings.size(); i++) {
-		outputs += outputs_strings[i].replace_first(outputs_strings[i].split(",")[0], itos(i)) + ";";
+		outputs += outputs_strings[i].replace_first(outputs_strings[i].get_slicec(',', 0), itos(i)) + ";";
 	}
 	}
 
 
 	_apply_port_changes();
 	_apply_port_changes();

+ 3 - 4
scene/resources/visual_shader.h

@@ -97,13 +97,12 @@ public:
 				name(p_name), mode(p_mode), type(p_type) {}
 				name(p_name), mode(p_mode), type(p_type) {}
 
 
 		bool from_string(const String &p_str) {
 		bool from_string(const String &p_str) {
-			Vector<String> arr = p_str.split(",");
-			if (arr.size() != 2) {
+			if (p_str.get_slice_count(",") != 2) {
 				return false;
 				return false;
 			}
 			}
 
 
-			mode = (VaryingMode)arr[0].to_int();
-			type = (VaryingType)arr[1].to_int();
+			mode = (VaryingMode)p_str.get_slicec(',', 0).to_int();
+			type = (VaryingType)p_str.get_slicec(',', 1).to_int();
 
 
 			return true;
 			return true;
 		}
 		}