Selaa lähdekoodia

Change behavior of String.right

Tomasz Chabora 5 vuotta sitten
vanhempi
commit
b1859510ab

+ 2 - 2
core/debugger/local_debugger.cpp

@@ -183,7 +183,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
 						print_line("Error: Unknown option " + key);
 					} else {
 						// Allow explicit tab character
-						String value = key_value.right(value_pos + 1).replace("\\t", "\t");
+						String value = key_value.substr(value_pos + 1).replace("\\t", "\t");
 
 						options[key] = value;
 					}
@@ -348,7 +348,7 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) {
 	}
 
 	breakpoint.first = script_debugger->breakpoint_find_source(breakpoint_part.left(last_colon).strip_edges());
-	breakpoint.second = breakpoint_part.right(last_colon).strip_edges().to_int();
+	breakpoint.second = breakpoint_part.substr(last_colon).strip_edges().to_int();
 
 	return breakpoint;
 }

+ 6 - 6
core/input/input.cpp

@@ -1262,16 +1262,16 @@ void Input::parse_mapping(String p_mapping) {
 			} else if (output[0] == '-') {
 				output_range = NEGATIVE_HALF_AXIS;
 			}
-			output = output.right(1);
+			output = output.substr(1);
 		}
 
 		JoyAxisRange input_range = FULL_AXIS;
 		if (input[0] == '+') {
 			input_range = POSITIVE_HALF_AXIS;
-			input = input.right(1);
+			input = input.substr(1);
 		} else if (input[0] == '-') {
 			input_range = NEGATIVE_HALF_AXIS;
-			input = input.right(1);
+			input = input.substr(1);
 		}
 		bool invert_axis = false;
 		if (input[input.length() - 1] == '~') {
@@ -1299,11 +1299,11 @@ void Input::parse_mapping(String p_mapping) {
 		switch (input[0]) {
 			case 'b':
 				binding.inputType = TYPE_BUTTON;
-				binding.input.button = input.right(1).to_int();
+				binding.input.button = input.substr(1).to_int();
 				break;
 			case 'a':
 				binding.inputType = TYPE_AXIS;
-				binding.input.axis.axis = input.right(1).to_int();
+				binding.input.axis.axis = input.substr(1).to_int();
 				binding.input.axis.range = input_range;
 				binding.input.axis.invert = invert_axis;
 				break;
@@ -1312,7 +1312,7 @@ void Input::parse_mapping(String p_mapping) {
 						String(entry[idx] + "\nInvalid hat input: " + input));
 				binding.inputType = TYPE_HAT;
 				binding.input.hat.hat = input.substr(1, 1).to_int();
-				binding.input.hat.hat_mask = static_cast<HatMask>(input.right(3).to_int());
+				binding.input.hat.hat_mask = static_cast<HatMask>(input.substr(3).to_int());
 				break;
 			default:
 				ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input));

+ 1 - 1
core/io/resource_loader.cpp

@@ -867,7 +867,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
 				continue;
 			}
 
-			String l = res_remaps[i].right(split + 1).strip_edges();
+			String l = res_remaps[i].substr(split + 1).strip_edges();
 			if (l == locale) { // Exact match.
 				new_path = res_remaps[i].left(split);
 				break;

+ 16 - 8
core/string/ustring.cpp

@@ -3382,14 +3382,14 @@ String String::format(const Variant &values, String placeholder) const {
 				if (value_arr.size() == 2) {
 					Variant v_key = value_arr[0];
 					String key = v_key;
-					if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+					if (key.left(1) == "\"" && key.right(1) == "\"") {
 						key = key.substr(1, key.length() - 2);
 					}
 
 					Variant v_val = value_arr[1];
 					String val = v_val;
 
-					if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+					if (val.left(1) == "\"" && val.right(1) == "\"") {
 						val = val.substr(1, val.length() - 2);
 					}
 
@@ -3401,7 +3401,7 @@ String String::format(const Variant &values, String placeholder) const {
 				Variant v_val = values_arr[i];
 				String val = v_val;
 
-				if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+				if (val.left(1) == "\"" && val.right(1) == "\"") {
 					val = val.substr(1, val.length() - 2);
 				}
 
@@ -3421,11 +3421,11 @@ String String::format(const Variant &values, String placeholder) const {
 			String key = E->get();
 			String val = d[E->get()];
 
-			if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+			if (key.left(1) == "\"" && key.right(1) == "\"") {
 				key = key.substr(1, key.length() - 2);
 			}
 
-			if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+			if (val.left(1) == "\"" && val.right(1) == "\"") {
 				val = val.substr(1, val.length() - 2);
 			}
 
@@ -3529,6 +3529,10 @@ String String::repeat(int p_count) const {
 }
 
 String String::left(int p_pos) const {
+	if (p_pos < 0) {
+		p_pos = length() + p_pos;
+	}
+
 	if (p_pos <= 0) {
 		return "";
 	}
@@ -3541,15 +3545,19 @@ String String::left(int p_pos) const {
 }
 
 String String::right(int p_pos) const {
-	if (p_pos >= length()) {
-		return "";
+	if (p_pos < 0) {
+		p_pos = length() + p_pos;
 	}
 
 	if (p_pos <= 0) {
+		return "";
+	}
+
+	if (p_pos >= length()) {
 		return *this;
 	}
 
-	return substr(p_pos, (length() - p_pos));
+	return substr(length() - p_pos);
 }
 
 char32_t String::unicode_at(int p_idx) const {

+ 12 - 2
doc/classes/String.xml

@@ -397,7 +397,12 @@
 			<argument index="0" name="position" type="int">
 			</argument>
 			<description>
-				Returns a number of characters from the left of the string.
+				Returns a number of characters from the left of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+				Examples:
+				[codeblock]
+				print("sample text".left(3)) #prints "sam"
+				print("sample text".left(-3)) #prints "sample t"
+				[/codeblock]
 			</description>
 		</method>
 		<method name="length" qualifiers="const">
@@ -669,7 +674,12 @@
 			<argument index="0" name="position" type="int">
 			</argument>
 			<description>
-				Returns the right side of the string from a given position.
+				Returns a number of characters from the right of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length.
+				Examples:
+				[codeblock]
+				print("sample text".right(3)) #prints "ext"
+				print("sample text".right(-3)) #prints "ple text"
+				[/codeblock]
 			</description>
 		</method>
 		<method name="rpad" qualifiers="const">

+ 1 - 1
drivers/windows/dir_access_windows.cpp

@@ -198,7 +198,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) {
 		if (_get_root_string() == "") {
 			int p = current_dir.find(":");
 			if (p != -1) {
-				return current_dir.right(p + 1);
+				return current_dir.substr(p + 1);
 			}
 		}
 		return current_dir;

+ 3 - 3
editor/code_editor.cpp

@@ -1012,7 +1012,7 @@ void CodeTextEditor::convert_indent_to_spaces() {
 				if (cursor_line == i && cursor_column > j) {
 					cursor_column += indent_size - 1;
 				}
-				line = line.left(j) + indent + line.right(j + 1);
+				line = line.left(j) + indent + line.substr(j + 1);
 			}
 			j++;
 		}
@@ -1056,7 +1056,7 @@ void CodeTextEditor::convert_indent_to_tabs() {
 					if (cursor_line == i && cursor_column > j) {
 						cursor_column -= indent_size;
 					}
-					line = line.left(j - indent_size) + "\t" + line.right(j + 1);
+					line = line.left(j - indent_size) + "\t" + line.substr(j + 1);
 					j = 0;
 					space_count = -1;
 				}
@@ -1114,7 +1114,7 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
 			new_line = text_editor->get_line(i).left(begin_col) + new_line;
 		}
 		if (i == end) {
-			new_line = new_line + text_editor->get_line(i).right(end_col);
+			new_line = new_line + text_editor->get_line(i).substr(end_col);
 		}
 		text_editor->set_line(i, new_line);
 	}

+ 1 - 1
editor/editor_help.cpp

@@ -475,7 +475,7 @@ void EditorHelp::_update_doc() {
 			String linktxt = (cd.tutorials[i].title.is_empty()) ? link : DTR(cd.tutorials[i].title);
 			const int seppos = linktxt.find("//");
 			if (seppos != -1) {
-				linktxt = link.right(seppos + 2);
+				linktxt = link.substr(seppos + 2);
 			}
 
 			class_desc->push_color(symbol_color);

+ 1 - 1
editor/editor_help_search.cpp

@@ -334,7 +334,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes() {
 				for (int i = 0; i < class_doc.methods.size(); i++) {
 					String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
 					if (method_name.find(term) > -1 ||
-							(term.begins_with(".") && method_name.begins_with(term.right(1))) ||
+							(term.begins_with(".") && method_name.begins_with(term.substr(1))) ||
 							(term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
 							(term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) {
 						match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));

+ 2 - 2
editor/editor_inspector.cpp

@@ -1809,12 +1809,12 @@ void EditorInspector::update_tree() {
 			basename = group + "/" + basename;
 		}
 
-		String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename;
+		String name = (basename.find("/") != -1) ? basename.substr(basename.rfind("/") + 1) : basename;
 
 		if (capitalize_paths) {
 			int dot = name.find(".");
 			if (dot != -1) {
-				String ov = name.right(dot);
+				String ov = name.substr(dot);
 				name = name.substr(0, dot);
 				name = name.capitalize();
 				name += ov;

+ 2 - 2
editor/find_in_files.cpp

@@ -530,7 +530,7 @@ void FindInFilesDialog::_on_replace_text_entered(String text) {
 void FindInFilesDialog::_on_folder_selected(String path) {
 	int i = path.find("://");
 	if (i != -1) {
-		path = path.right(i + 3);
+		path = path.substr(i + 3);
 	}
 	_folder_line_edit->set_text(path);
 }
@@ -932,7 +932,7 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
 			continue;
 		}
 
-		line = line.left(repl_begin) + new_text + line.right(repl_end);
+		line = line.left(repl_begin) + new_text + line.substr(repl_end);
 		// keep an offset in case there are successive replaces in the same line
 		offset += new_text.length() - (repl_end - repl_begin);
 	}

+ 2 - 2
editor/project_manager.cpp

@@ -2138,8 +2138,8 @@ void ProjectManager::_run_project_confirm() {
 		const String &selected = selected_list[i].project_key;
 		String path = EditorSettings::get_singleton()->get("projects/" + selected);
 
-		// `.right(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://".
-		if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.right(6)))) {
+		// `.substr(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://".
+		if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.substr(6)))) {
 			run_error_diag->set_text(TTR("Can't run project: Assets need to be imported.\nPlease edit the project to trigger the initial import."));
 			run_error_diag->popup_centered();
 			continue;

+ 2 - 2
modules/gdscript/gdscript_editor.cpp

@@ -2873,7 +2873,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
 				StringName parent = ClassDB::get_parent_class(class_name);
 				if (parent != StringName()) {
 					if (String(parent).begins_with("_")) {
-						base_type.native_type = String(parent).right(1);
+						base_type.native_type = String(parent).substr(1);
 					} else {
 						base_type.native_type = parent;
 					}
@@ -3067,7 +3067,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
 
 							// proxy class remove the underscore.
 							if (r_result.class_name.begins_with("_")) {
-								r_result.class_name = r_result.class_name.right(1);
+								r_result.class_name = r_result.class_name.substr(1);
 							}
 							return OK;
 						}

+ 1 - 1
modules/gltf/gltf_document.cpp

@@ -664,7 +664,7 @@ static Vector<uint8_t> _parse_base64_uri(const String &uri) {
 	int start = uri.find(",");
 	ERR_FAIL_COND_V(start == -1, Vector<uint8_t>());
 
-	CharString substr = uri.right(start + 1).ascii();
+	CharString substr = uri.substr(start + 1).ascii();
 
 	int strlen = substr.length();
 

+ 1 - 1
scene/resources/tile_set.cpp

@@ -835,7 +835,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
 		} else if (what == "tile_mode") {
 			ctd->tile_mode = p_value;
 		} else if (what.left(9) == "autotile") {
-			what = what.right(9);
+			what = what.substr(9);
 			if (what == "bitmask_mode") {
 				ctd->autotile_bitmask_mode = p_value;
 			} else if (what == "icon_coordinate") {

+ 4 - 1
tests/test_string.h

@@ -299,6 +299,7 @@ TEST_CASE("[String] hex_encode_buffer") {
 TEST_CASE("[String] Substr") {
 	String s = "Killer Baby";
 	CHECK(s.substr(3, 4) == "ler ");
+	CHECK(s.substr(3) == "ler Baby");
 }
 
 TEST_CASE("[String] Find") {
@@ -1252,8 +1253,10 @@ TEST_CASE("[String] Trim") {
 TEST_CASE("[String] Right/Left") {
 	String s = "aaaTestbbb";
 	//                ^
-	CHECK(s.right(6) == "tbbb");
+	CHECK(s.right(6) == "estbbb");
+	CHECK(s.right(-6) == "tbbb");
 	CHECK(s.left(6) == "aaaTes");
+	CHECK(s.left(-6) == "aaaT");
 }
 
 TEST_CASE("[String] Repeat") {